From 17a020e9fc5c91de092584b04ce8f130dab91e49 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Tue, 27 Feb 2024 20:48:11 +0100 Subject: [PATCH] Augmented struct burn_toc_entry by new off_t block addresses and counters --- cdrskin/cdrskin_timestamp.h | 2 +- libburn/libburn.h | 16 +++- libburn/mmc.c | 143 ++++++++++++++++++++++++++---------- libburn/mmc.h | 2 + libburn/structure.c | 10 ++- 5 files changed, 128 insertions(+), 45 deletions(-) diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index acd5041..71b4ab3 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2024.02.26.150632" +#define Cdrskin_timestamP "2024.02.27.194737" diff --git a/libburn/libburn.h b/libburn/libburn.h index 9b2d8e5..c604be8 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -1,7 +1,7 @@ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens - Copyright (c) 2006 - 2023 Thomas Schmitt + Copyright (c) 2006 - 2024 Thomas Schmitt Provided under GPL version 2 or later. This is the official API definition of libburn. @@ -9,6 +9,8 @@ */ /* Important: If you add a public API function then add its name to file libburn/libburn.ver + in the node LIBBURN4_Major.Minor.Micro with the numbers of + the next release version, citing the previous node. */ @@ -376,6 +378,9 @@ struct burn_toc_entry @since 0.5.2 : DVD extensions are made valid for CD too bit1= LRA extension is valid @since 0.7.2 bit2= Track status bits extension is valid @since 1.2.8 + bit3= Long block address is valid: + long_start_lba, long_track_blocks, long_last_rec_adr + @since 1.5.8 */ unsigned char extensions_valid; @@ -386,8 +391,10 @@ struct burn_toc_entry unsigned char session_msb; unsigned char point_msb; /* pmin, psec, and pframe may be too small if DVD extension is valid */ + /* -1 means that only long_start_lba is valid */ int start_lba; /* min, sec, and frame may be too small if DVD extension is valid */ + /* -1 means that only long_track_blocks is valid */ int track_blocks; /* ts A90909 : LRA extension. extensions_valid:bit1 */ @@ -396,6 +403,7 @@ struct burn_toc_entry DVD-R DL when LJRS = 00b, DVD-RW, HD DVD-R, and BD-R. This would mean profiles: 0x11, 0x15, 0x13, 0x14, 0x51, 0x41, 0x42 */ + /* -1 means that only long_last_rec_adr is valid */ int last_recorded_address; /* ts B30112 : Track status bits extension. extensions_valid:bit2 */ @@ -415,6 +423,12 @@ struct burn_toc_entry */ int track_status_bits; + /* ts C40221 : Long block address extension. extensions_valid:bit3 */ + /* @since 1.5.8 */ + off_t long_start_lba; + off_t long_track_blocks; + off_t long_last_rec_adr; + }; diff --git a/libburn/mmc.c b/libburn/mmc.c index a312e2a..5946d9c 100644 --- a/libburn/mmc.c +++ b/libburn/mmc.c @@ -300,6 +300,14 @@ int mmc_four_char_to_int(unsigned char *data) } +/* ts C40226 */ +unsigned int mmc_four_char_to_uint(unsigned char *data) +{ + return (((unsigned int) data[0]) << 24) | (data[1] << 16) | + (data[2] << 8) | data[3]; +} + + /* ts A70201 */ int mmc_int_to_four_char(unsigned char *data, int num) { @@ -311,6 +319,17 @@ int mmc_int_to_four_char(unsigned char *data, int num) } +/* ts C40226 */ +int mmc_uint_to_four_char(unsigned char *data, unsigned int num) +{ + data[0] = (num >> 24) & 0xff; + data[1] = (num >> 16) & 0xff; + data[2] = (num >> 8) & 0xff; + data[3] = num & 0xff; + return 1; +} + + static int mmc_start_for_bit0 = 0; /* @param flag bit0= the calling function should need no START UNIT. @@ -1087,10 +1106,11 @@ int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number, unsigned char *size_data, unsigned char *start_data, unsigned char *last_adr_data) { - int min, sec, frames, num; + int min, sec, frames; + unsigned int num; - /* mark DVD extensions and Track Info extension as valid */ - entry->extensions_valid |= (1 | 2); + /* mark extensions as valid: DVD, Track Info, Long block address */ + entry->extensions_valid |= (1 | 2 | 8); /* defaults are as of mmc5r03.pdf 6.26.3.2.4 Fabricated TOC */ entry->session = session_number & 0xff; @@ -1100,9 +1120,16 @@ int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number, entry->tno = 0; entry->point = track_number & 0xff; entry->point_msb = (track_number >> 8) & 0xff; - num = mmc_four_char_to_int(size_data); - entry->track_blocks = num; - burn_lba_to_msf(num, &min, &sec, &frames); + num = mmc_four_char_to_uint(size_data); + if (num < 0x80000000) { + entry->track_blocks = num; + burn_lba_to_msf(num, &min, &sec, &frames); + } else { + entry->track_blocks = -1; + min = 477218; /* ~=LBA 0x7fffffff */ + sec = frames = 0; + } + entry->long_track_blocks = num; if (min > 255) { min = 255; sec = 255; @@ -1112,9 +1139,16 @@ int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number, entry->sec = sec; entry->frame = frames; entry->zero = 0; - num = mmc_four_char_to_int(start_data); - entry->start_lba = num; - burn_lba_to_msf(num, &min, &sec, &frames); + num = mmc_four_char_to_uint(start_data); + if (num < 0x80000000) { + entry->start_lba = num; + burn_lba_to_msf(num, &min, &sec, &frames); + } else { + entry->start_lba = -1; + min = 477218; + sec = frames = 0; + } + entry->long_start_lba = num; if (min > 255) { min = 255; sec = 255; @@ -1123,7 +1157,13 @@ int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number, entry->pmin = min; entry->psec = sec; entry->pframe = frames; - entry->last_recorded_address = mmc_four_char_to_int(last_adr_data); + num = mmc_four_char_to_uint(last_adr_data); + if (num < 0x80000000) { + entry->last_recorded_address = num; + } else { + entry->last_recorded_address = -1; + } + entry->long_last_rec_adr = num; return 1; } @@ -1137,7 +1177,7 @@ static int mmc_read_toc_fmt0_al(struct burn_drive *d, int *alloc_len) struct buffer *buf = NULL; struct command *c = NULL; int dlen, i, old_alloc_len, session_number, prev_session = -1, ret; - int lba, size; + unsigned int lba, size; unsigned char *tdata, size_data[4], start_data[4], end_data[4]; if (*alloc_len < 4) @@ -1216,11 +1256,11 @@ err_ex:; if (session_number != prev_session && prev_session > 0) { /* leadout entry previous session */ entry = &(d->toc_entry[(i - 1) + prev_session]); - lba = mmc_four_char_to_int(start_data) + - mmc_four_char_to_int(size_data); - mmc_int_to_four_char(start_data, lba); - mmc_int_to_four_char(size_data, 0); - mmc_int_to_four_char(end_data, lba - 1); + lba = mmc_four_char_to_uint(start_data) + + mmc_four_char_to_uint(size_data); + mmc_uint_to_four_char(start_data, lba); + mmc_uint_to_four_char(size_data, 0); + mmc_uint_to_four_char(end_data, lba - 1); mmc_fake_toc_entry(entry, prev_session, 0xA2, size_data, start_data, end_data); entry->min= entry->sec= entry->frame= 0; @@ -1245,11 +1285,11 @@ err_ex:; memcpy(start_data, tdata + 4, 4); /* size_data are estimated from next track start */ memcpy(size_data, tdata + 8 + 4, 4); - mmc_int_to_four_char(end_data, - mmc_four_char_to_int(size_data) - 1); - size = mmc_four_char_to_int(size_data) - - mmc_four_char_to_int(start_data); - mmc_int_to_four_char(size_data, size); + mmc_uint_to_four_char(end_data, + mmc_four_char_to_uint(size_data) - 1); + size = mmc_four_char_to_uint(size_data) - + mmc_four_char_to_uint(start_data); + mmc_uint_to_four_char(size_data, size); mmc_fake_toc_entry(entry, session_number, i + 1, size_data, start_data, end_data); if (prev_session != session_number) @@ -1262,9 +1302,9 @@ err_ex:; tdata = c->page->data + 4 + d->last_track_no * 8; entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]); memcpy(start_data, tdata + 4, 4); - mmc_int_to_four_char(size_data, 0); - mmc_int_to_four_char(end_data, - mmc_four_char_to_int(start_data) - 1); + mmc_uint_to_four_char(size_data, 0); + mmc_uint_to_four_char(end_data, + mmc_four_char_to_uint(start_data) - 1); mmc_fake_toc_entry(entry, prev_session, 0xA2, size_data, start_data, end_data); entry->min= entry->sec= entry->frame= 0; @@ -1301,7 +1341,8 @@ int mmc_fake_toc(struct burn_drive *d) struct burn_session *session; struct burn_toc_entry *entry; struct buffer *buf = NULL; - int i, session_number, prev_session = -1, ret, lba, alloc_len = 34; + int i, session_number, prev_session = -1, ret, alloc_len = 34; + unsigned int lba; unsigned char *tdata, size_data[4], start_data[4], end_data[4]; char *msg = NULL; @@ -1406,11 +1447,11 @@ int mmc_fake_toc(struct burn_drive *d) if (session_number != prev_session && prev_session > 0) { /* leadout entry previous session */ entry = &(d->toc_entry[(i - 1) + prev_session]); - lba = mmc_four_char_to_int(start_data) + - mmc_four_char_to_int(size_data); - mmc_int_to_four_char(start_data, lba); - mmc_int_to_four_char(size_data, 0); - mmc_int_to_four_char(end_data, lba - 1); + lba = mmc_four_char_to_uint(start_data) + + mmc_four_char_to_uint(size_data); + mmc_uint_to_four_char(start_data, lba); + mmc_uint_to_four_char(size_data, 0); + mmc_uint_to_four_char(end_data, lba - 1); mmc_fake_toc_entry(entry, prev_session, 0xA2, size_data, start_data, end_data); entry->min= entry->sec= entry->frame= 0; @@ -1431,7 +1472,7 @@ int mmc_fake_toc(struct burn_drive *d) if (i == d->last_track_no - 1) { /* ts A70212 : Last track field Free Blocks */ burn_drive_set_media_capacity_remaining(d, - ((off_t) mmc_four_char_to_int(tdata + 16)) * + ((off_t) mmc_four_char_to_uint(tdata + 16)) * ((off_t) 2048)); d->media_lba_limit = 0; } @@ -1477,11 +1518,11 @@ int mmc_fake_toc(struct burn_drive *d) if (prev_session > 0 && prev_session <= d->disc->sessions) { /* leadout entry of last session of closed disc */ entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]); - lba = mmc_four_char_to_int(start_data) + - mmc_four_char_to_int(size_data); - mmc_int_to_four_char(start_data, lba); - mmc_int_to_four_char(size_data, 0); - mmc_int_to_four_char(end_data, lba - 1); + lba = mmc_four_char_to_uint(start_data) + + mmc_four_char_to_uint(size_data); + mmc_uint_to_four_char(start_data, lba); + mmc_uint_to_four_char(size_data, 0); + mmc_uint_to_four_char(end_data, lba - 1); mmc_fake_toc_entry(entry, prev_session, 0xA2, size_data, start_data, end_data); entry->min= entry->sec= entry->frame= 0; @@ -1774,12 +1815,12 @@ void mmc_read_toc(struct burn_drive *d) } -/* ts A70131 : This tries to get the start of the last complete session */ +/* ts C40226 : long address reply version of mmc_read_multi_session_c1 */ /* man mkisofs , option -C : The first number is the sector number of the first sector in the last session of the disk that should be appended to. */ -int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start) +int mmc_read_msc1_long(struct burn_drive *d, int *trackno, off_t *start) { struct buffer *buf = NULL; struct command *c = NULL; @@ -1812,7 +1853,11 @@ int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start) continue; burn_track_get_entry(tracks[0], &toc_entry); if (toc_entry.extensions_valid & 1) { /* DVD extension valid */ - *start = toc_entry.start_lba; + if (toc_entry.extensions_valid & 8) { /* Long adr */ + *start = toc_entry.long_start_lba; + } else { + *start = toc_entry.start_lba; + } *trackno = (toc_entry.point_msb << 8)| toc_entry.point; } else { *start = burn_msf_to_lba(toc_entry.pmin, @@ -1847,7 +1892,7 @@ inquire_drive:; tdata = c->page->data + 4; *trackno = tdata[2]; - *start = mmc_four_char_to_int(tdata + 4); + *start = mmc_four_char_to_uint(tdata + 4); ret = 1; ex:; BURN_FREE_MEM(buf); @@ -1856,6 +1901,24 @@ ex:; } +/* ts A70131 : This tries to get the start of the last complete session */ +int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start) +{ + int ret; + off_t num; + + ret = mmc_read_msc1_long(d, trackno, &num); + if (ret <= 0) + return ret; + if(num >= 0x80000000) { + *start = 0x7fffffff; + return 0; + } + *start = num; + return 1; +} + + /* ts A61201 */ char *mmc_obtain_profile_name(int profile_number) { diff --git a/libburn/mmc.h b/libburn/mmc.h index a995317..89eee85 100644 --- a/libburn/mmc.h +++ b/libburn/mmc.h @@ -78,6 +78,8 @@ int mmc_compose_mode_page_5(struct burn_drive *d, /* ts A70201 */ int mmc_four_char_to_int(unsigned char *data); +/* ts C40226 */ +unsigned int mmc_four_char_to_uint(unsigned char *data); /* ts A70201 : Common track info fetcher for mmc_get_nwa() and mmc_fake_toc() diff --git a/libburn/structure.c b/libburn/structure.c index 42c7817..41857af 100644 --- a/libburn/structure.c +++ b/libburn/structure.c @@ -768,7 +768,7 @@ int burn_session_get_hidefirst(struct burn_session *session) } -/* ts A80808 : Enhance CD toc to DVD toc */ +/* ts A80808,C40226 : Enhance CD toc to DVD toc with Long block addresses */ int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag) { int sidx= 0, tidx= 0, ret, track_offset, alloc_len = 34; @@ -836,6 +836,7 @@ int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag) entry->point_msb = 0; entry->start_lba = burn_msf_to_lba(entry->pmin, entry->psec, entry->pframe); + entry->long_start_lba = entry->start_lba; if (tidx > 0) { prev_entry->track_blocks = entry->start_lba @@ -855,13 +856,16 @@ int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag) ret < prev_entry->track_blocks - 2)) prev_entry->track_blocks = ret; } - prev_entry->extensions_valid |= 1; + prev_entry->long_track_blocks = + prev_entry->track_blocks; + prev_entry->extensions_valid |= 1 | 8; } if (tidx == d->session[sidx]->tracks) { entry->session_msb = 0; entry->point_msb = 0; entry->track_blocks = 0; - entry->extensions_valid |= 1; + entry->long_track_blocks = entry->track_blocks; + entry->extensions_valid |= 1 | 8; } prev_entry = entry; }