diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 6bad87f..8922f19 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2011.12.15.161349" +#define Cdrskin_timestamP "2011.12.15.174914" diff --git a/libburn/cdtext.c b/libburn/cdtext.c index 014642a..852312c 100755 --- a/libburn/cdtext.c +++ b/libburn/cdtext.c @@ -19,11 +19,432 @@ #include "libburn.h" #include "init.h" +#include "structure.h" +#include "options.h" #include "libdax_msgs.h" extern struct libdax_msgs *libdax_messenger; +/* --------------------- Production of CD-TEXT packs -------------------- */ + + +struct burn_pack_cursor { + unsigned char *packs; + int num_packs; + int td_used; + int hiseq[8]; + int pack_count[16]; +}; + + +/* @param flag bit0= double_byte characters +*/ +int burn_create_new_pack(int pack_type, int track_no, int double_byte, + int block, int char_pos, + struct burn_pack_cursor *crs, int flag) +{ + int idx; + + if (crs->num_packs >= Libburn_leadin_cdtext_packs_maX) { + libdax_msgs_submit(libdax_messenger, -1, 0x0002018b, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "Too many CD-TEXT packs", 0, 0); + return 0; + } + if (crs->hiseq[block] >= 255) { + libdax_msgs_submit(libdax_messenger, -1, 0x0002018e, + LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, + "Too many CD-TEXT packs in block", 0, 0); + return 0; + } + if (char_pos > 15) + char_pos = 15; + else if (char_pos < 0) + char_pos = 0; + idx = crs->num_packs * 18; + crs->packs[idx++] = pack_type; + crs->packs[idx++] = track_no; + crs->packs[idx++] = crs->hiseq[block]; + crs->packs[idx++] = ((flag & 1) << 7) | (block << 4) | char_pos; + crs->hiseq[block]++; + crs->td_used = 0; + crs->pack_count[pack_type - Libburn_pack_type_basE]++; + return 1; +} + + +/* Plain implementation of polynomial division on a Galois field, where + addition and subtraction both are binary exor. Euclidian algorithm. + Divisor is x^16 + x^12 + x^5 + 1 = 0x11021. +*/ +static int crc_11021(unsigned char *data, int count, int flag) +{ + int acc = 0, i; + + for (i = 0; i < count * 8 + 16; i++) { + acc = (acc << 1); + if (i < count * 8) + acc |= ((data[i / 8] >> (7 - (i % 8))) & 1); + if (acc & 0x10000) + acc ^= 0x11021; + } + return acc; +} + + +/* @param flag bit0= repair mismatching checksums + bit1= repair checksums if all pack CRCs are 0 + @return 0= no mismatch , >0 number of unrepaired mismatches + <0 number of repaired mismatches that were not 0 +*/ +int burn_cdtext_crc_mismatches(unsigned char *packs, int num_packs, int flag) +{ + int i, residue, count = 0, repair; + unsigned char crc[2]; + + repair = flag & 1; + if (flag & 2) { + for (i = 0; i < num_packs * 18; i += 18) + if (packs[i + 16] || packs[i + 17]) + break; + if (i == num_packs * 18) + repair = 1; + } + for (i = 0; i < num_packs * 18; i += 18) { + residue = crc_11021(packs + i, 16, 0); + crc[0] = ((residue >> 8) & 0xff) ^ 0xff; + crc[1] = ((residue ) & 0xff) ^ 0xff; + if(crc[0] != packs[i + 16] || crc[1] != packs[i + 17]) { + if (repair) { + if (packs[i + 16] || packs[i + 17]) + count--; + packs[i + 16] = crc[0]; + packs[i + 17] = crc[1]; + } else + count++; + } + + } + return count; +} + + +static int burn_finalize_text_pack(struct burn_pack_cursor *crs, int flag) +{ + int residue = 0, i, idx; + + idx = 18 * crs->num_packs; + for(i = 4 + crs->td_used; i < 16; i++) + crs->packs[idx + i] = 0; + crs->td_used = 12; + + /* MMC-3 Annex J : CRC Field consists of 2 bytes. + The polynomial is X16 + X12 + X5 + 1. All bits shall be inverted. + */ + residue = crc_11021(crs->packs + idx, 16, 0) ^ 0xffff; + + crs->packs[idx + 16] = (residue >> 8) & 0xff; + crs->packs[idx + 17] = residue & 0xff; + crs->num_packs++; + crs->td_used = 0; + return 1; +} + + +/* @param flag bit0= double_byte characters +*/ +static int burn_create_tybl_packs(unsigned char *payload, int length, + int track_no, int pack_type, int block, + struct burn_pack_cursor *crs, int flag) +{ + int i, ret, binary_part = 0, char_pos; + + if (pack_type == 0x87) + binary_part = 2; + else if ((pack_type >= 0x88 && pack_type <= 0x8c) || pack_type == 0x8f) + binary_part = length; + for(i = 0; i < length; i++) { + if (crs->td_used == 0 || crs->td_used >= 12) { + if (crs->td_used > 0) { + ret = burn_finalize_text_pack(crs, 0); + if (ret <= 0) + return ret; + } + char_pos = (i - binary_part) / (1 + (flag & 1)); + ret = burn_create_new_pack(pack_type, track_no, + (flag & 1), block, char_pos, + crs, flag & 1); + if (ret <= 0) + return ret; + } + crs->packs[crs->num_packs * 18 + 4 + crs->td_used] = + payload[i]; + crs->td_used++; + } + return 1; +} + + +/* Finalize block by 0x8f. Set bytes 20 to 27 to 0 for now. */ +static int burn_create_bl_size_packs(int block, unsigned char *char_codes, + unsigned char *copyrights, + unsigned char *languages, + int num_tracks, + struct burn_pack_cursor *crs, int flag) +{ + int i, ret; + unsigned char payload[12]; + /* Normal is track_offset = 0. + But if the CUE sheet supports offset, then it is needed here too */ + int track_offset = 0; + + payload[0] = char_codes[block]; + payload[1] = 1 + track_offset; + payload[2] = num_tracks + track_offset; + payload[3] = copyrights[block]; + for (i = 0; i < 8; i++) + payload[i + 4] = crs->pack_count[i]; + ret = burn_create_tybl_packs(payload, 12, 0, 0x8f, block, crs, 0); + if (ret <= 0) + return ret; + + for (i = 0; i < 7; i++) + payload[i] = crs->pack_count[i + 8]; + payload[7] = 3; /* always 3 packs of type 0x8f */ + for (i = 0; i < 4; i++) { + /* Will be set when all blocks are done */ + payload[i + 8] = 0; + } + ret = burn_create_tybl_packs(payload, 12, 1, 0x8f, block, crs, 0); + if (ret <= 0) + return ret; + + for (i = 0; i < 4; i++) { + /* Will be set when all blocks are done */ + payload[i] = 0; + } + for (i = 0; i < 8; i++) { + payload[i + 4] = languages[i]; + } + ret = burn_create_tybl_packs(payload, 12, 2, 0x8f, block, crs, 0); + if (ret <= 0) + return ret; + ret = burn_finalize_text_pack(crs, 0); + if (ret <= 0) + return ret; + + for (i = 0; i < 16; i++) + crs->pack_count[i] = 0; + return 1; +} + + +/* Text packs of track for type and block + @param flag bit0= write TAB, because content is identical to previous track +*/ +static int burn_create_tybl_t_packs(struct burn_track *t, int track_no, + int pack_type, int block, + struct burn_pack_cursor *crs, int flag) +{ + int ret, length = 0, idx, double_byte, flags= 0; + unsigned char *payload = NULL, dummy[8]; + struct burn_cdtext *cdt; + + cdt = t->cdtext[block]; + idx = pack_type - Libburn_pack_type_basE; + if (cdt != NULL) { + if (cdt->length[idx] > 0) { + payload = cdt->payload[idx]; + length = cdt->length[idx]; + } + flags = cdt->flags; + } + if (payload == NULL) { + dummy[0]= 0; + payload = dummy; + length = strlen((char *) dummy) + 1; + } + double_byte = !!(flags & (1 <<(pack_type - Libburn_pack_type_basE))); + if (flag & 1) { + length = 0; + dummy[length++] = 9; + if (double_byte) + dummy[length++] = 9; + dummy[length++] = 0; + if (double_byte) + dummy[length++] = 0; + payload = dummy; + } + ret = burn_create_tybl_packs(payload, length, track_no, + pack_type, block, crs, double_byte); + return ret; +} + + +/* Check whether the content is the same as in the previous pack. If so, + advise to use the TAB abbreviation. +*/ +static int burn_decide_cdtext_tab(int block, int pack_type, + struct burn_cdtext *cdt_curr, + struct burn_cdtext *cdt_prev, int flag) +{ + int length, j, idx; + + idx = pack_type - Libburn_pack_type_basE; + if (cdt_curr == NULL || cdt_prev == NULL) + return 0; + if (((cdt_curr->flags >> idx) & 1) != ((cdt_prev->flags >> idx) & 1)) + return 0; + length = cdt_curr->length[idx]; + if (length != cdt_prev->length[idx] || + length <= 1 + ((cdt_curr->flags >> idx) & 1)) + return 0; + for (j = 0; j < length; j++) + if (cdt_curr->payload[idx][j] != cdt_prev->payload[idx][j]) + break; + if (j < length) + return 0; + return 1; +} + + +/* Text packs of session and of tracks (if applicable), for type and block +*/ +static int burn_create_tybl_s_packs(struct burn_session *s, + int pack_type, int block, + struct burn_pack_cursor *crs, int flag) +{ + int i, ret, idx, double_byte, use_tab; + struct burn_cdtext *cdt; + /* Normal is track_offset = 0. + But if the CUE sheet supports offset, then it is needed here too */ + int track_offset = 0; + + cdt = s->cdtext[block]; + idx = pack_type - Libburn_pack_type_basE; + if (cdt->length[idx] == 0 || cdt->payload[idx] == NULL) + return 1; + + double_byte = !!(cdt->flags & + (1 <<(pack_type - Libburn_pack_type_basE))); + ret = burn_create_tybl_packs(cdt->payload[idx], cdt->length[idx], 0, + pack_type, block, crs, double_byte); + if (ret <= 0) + return ret; + + if ((pack_type < 0x80 || pack_type > 0x85) && pack_type != 0x8e) { + ret = burn_finalize_text_pack(crs, 0); + return ret; + } + + for (i = 0; i < s->tracks; i++) { + if (i > 0) + use_tab = burn_decide_cdtext_tab(block, pack_type, + s->track[i]->cdtext[block], + s->track[i - 1]->cdtext[block], 0); + else + use_tab = 0; + ret = burn_create_tybl_t_packs(s->track[i], + i + 1 + track_offset, pack_type, + block, crs, use_tab); + if (ret <= 0) + return ret; + } + /* Fill up last pack with 0s */ + ret = burn_finalize_text_pack(crs, 0); + return ret; +} + + +/* ts B11210 : API */ +/* @param flag bit0= do not return CD-TEXT packs, but return number of packs +*/ +int burn_cdtext_from_session(struct burn_session *s, + unsigned char **text_packs, int *num_packs, + int flag) +{ + int pack_type, block, ret, i, idx, j, residue; + struct burn_pack_cursor crs; + + if (text_packs == NULL || num_packs == NULL) { + flag |= 1; + } else if (!(flag & 1)) { + *text_packs = NULL; + *num_packs = 0; + } + memset(&crs, 0, sizeof(struct burn_pack_cursor)); + BURN_ALLOC_MEM(crs.packs, unsigned char, + Libburn_leadin_cdtext_packs_maX * 18); + + for (block = 0; block < 8; block++) + if (s->cdtext[block] != NULL) + break; + if (block == 8) + {ret = 1; goto ex;} + + for (block= 0; block < 8; block++) { + if (s->cdtext[block] == NULL) + continue; + for (pack_type = 0x80; + pack_type < 0x80 + Libburn_pack_num_typeS; pack_type++) { + if (pack_type == 0x8f) + continue; + ret = burn_create_tybl_s_packs(s, + pack_type, block, &crs, 0); + if (ret <= 0) + goto ex; + } + ret = burn_create_bl_size_packs(block, + s->cdtext_char_code, s->cdtext_copyright, + s->cdtext_language, s->tracks, &crs, 0); + if (ret <= 0) + goto ex; + } + + /* Insert the highest sequence numbers of each block into + the 0x8f packs 2 and 3 (bytes 20 to 27) + */ + for (i = 0; i < crs.num_packs; i++) { + idx = i * 18; + if (crs.packs[idx] == 0x8f && crs.packs[idx + 1] == 1) { + for (j = 0; j < 4; j++) + if (crs.hiseq[j] > 0) + crs.packs[idx + 4 + 8 + j] = + crs.hiseq[j] - 1; + else + crs.packs[idx + 4 + 8 + j] = 0; + } else if (crs.packs[idx] == 0x8f && crs.packs[idx + 1] == 2) { + for (j = 0; j < 4; j++) + if (crs.hiseq[j + 4] > 0) + crs.packs[idx + 4 + j] = + crs.hiseq[j + 4] - 1; + else + crs.packs[idx + 4 + j] = 0; + } else + continue; + /* Re-compute checksum */ + residue = crc_11021(crs.packs + idx, 16, 0) ^ 0xffff; + crs.packs[idx + 16] = (residue >> 8) & 0xff; + crs.packs[idx + 17] = residue & 0xff; + } + + ret = 1; +ex:; + if (ret <= 0 || (flag & 1)) { + if (ret > 0) + ret = crs.num_packs; + else if (flag & 1) + ret = -1; + BURN_FREE_MEM(crs.packs); + } else if (crs.num_packs > 0) { + *text_packs = crs.packs; + *num_packs = crs.num_packs; + } + return(ret); +} + + /* ---------------- Reader of Sony Input Sheet Version 0.7T ------------- */ diff --git a/libburn/write.c b/libburn/write.c index e604ba8..56034cf 100644 --- a/libburn/write.c +++ b/libburn/write.c @@ -669,422 +669,6 @@ int burn_write_leadout(struct burn_write_opts *o, } -struct burn_pack_cursor { - unsigned char *packs; - int num_packs; - int td_used; - int hiseq[8]; - int pack_count[16]; -}; - - -/* @param flag bit0= double_byte characters -*/ -int burn_create_new_pack(int pack_type, int track_no, int double_byte, - int block, int char_pos, - struct burn_pack_cursor *crs, int flag) -{ - int idx; - - if (crs->num_packs >= Libburn_leadin_cdtext_packs_maX) { - libdax_msgs_submit(libdax_messenger, -1, 0x0002018b, - LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, - "Too many CD-TEXT packs", 0, 0); - return 0; - } - if (crs->hiseq[block] >= 255) { - libdax_msgs_submit(libdax_messenger, -1, 0x0002018e, - LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, - "Too many CD-TEXT packs in block", 0, 0); - return 0; - } - if (char_pos > 15) - char_pos = 15; - else if (char_pos < 0) - char_pos = 0; - idx = crs->num_packs * 18; - crs->packs[idx++] = pack_type; - crs->packs[idx++] = track_no; - crs->packs[idx++] = crs->hiseq[block]; - crs->packs[idx++] = ((flag & 1) << 7) | (block << 4) | char_pos; - crs->hiseq[block]++; - crs->td_used = 0; - crs->pack_count[pack_type - Libburn_pack_type_basE]++; - return 1; -} - - -/* Plain implementation of polynomial division on a Galois field, where - addition and subtraction both are binary exor. Euclidian algorithm. - Divisor is x^16 + x^12 + x^5 + 1 = 0x11021. -*/ -static int crc_11021(unsigned char *data, int count, int flag) -{ - int acc = 0, i; - - for (i = 0; i < count * 8 + 16; i++) { - acc = (acc << 1); - if (i < count * 8) - acc |= ((data[i / 8] >> (7 - (i % 8))) & 1); - if (acc & 0x10000) - acc ^= 0x11021; - } - return acc; -} - - -/* @param flag bit0= repair mismatching checksums - bit1= repair checksums if all pack CRCs are 0 - @return 0= no mismatch , >0 number of unrepaired mismatches - <0 number of repaired mismatches that were not 0 -*/ -int burn_cdtext_crc_mismatches(unsigned char *packs, int num_packs, int flag) -{ - int i, residue, count = 0, repair; - unsigned char crc[2]; - - repair = flag & 1; - if (flag & 2) { - for (i = 0; i < num_packs * 18; i += 18) - if (packs[i + 16] || packs[i + 17]) - break; - if (i == num_packs * 18) - repair = 1; - } - for (i = 0; i < num_packs * 18; i += 18) { - residue = crc_11021(packs + i, 16, 0); - crc[0] = ((residue >> 8) & 0xff) ^ 0xff; - crc[1] = ((residue ) & 0xff) ^ 0xff; - if(crc[0] != packs[i + 16] || crc[1] != packs[i + 17]) { - if (repair) { - if (packs[i + 16] || packs[i + 17]) - count--; - packs[i + 16] = crc[0]; - packs[i + 17] = crc[1]; - } else - count++; - } - - } - return count; -} - - -static int burn_finalize_text_pack(struct burn_pack_cursor *crs, int flag) -{ - int residue = 0, i, idx; - - idx = 18 * crs->num_packs; - for(i = 4 + crs->td_used; i < 16; i++) - crs->packs[idx + i] = 0; - crs->td_used = 12; - - /* MMC-3 Annex J : CRC Field consists of 2 bytes. - The polynomial is X16 + X12 + X5 + 1. All bits shall be inverted. - */ - residue = crc_11021(crs->packs + idx, 16, 0) ^ 0xffff; - - crs->packs[idx + 16] = (residue >> 8) & 0xff; - crs->packs[idx + 17] = residue & 0xff; - crs->num_packs++; - crs->td_used = 0; - return 1; -} - - -/* @param flag bit0= double_byte characters -*/ -static int burn_create_tybl_packs(unsigned char *payload, int length, - int track_no, int pack_type, int block, - struct burn_pack_cursor *crs, int flag) -{ - int i, ret, binary_part = 0, char_pos; - - if (pack_type == 0x87) - binary_part = 2; - else if ((pack_type >= 0x88 && pack_type <= 0x8c) || pack_type == 0x8f) - binary_part = length; - for(i = 0; i < length; i++) { - if (crs->td_used == 0 || crs->td_used >= 12) { - if (crs->td_used > 0) { - ret = burn_finalize_text_pack(crs, 0); - if (ret <= 0) - return ret; - } - char_pos = (i - binary_part) / (1 + (flag & 1)); - ret = burn_create_new_pack(pack_type, track_no, - (flag & 1), block, char_pos, - crs, flag & 1); - if (ret <= 0) - return ret; - } - crs->packs[crs->num_packs * 18 + 4 + crs->td_used] = - payload[i]; - crs->td_used++; - } - return 1; -} - - -/* Finalize block by 0x8f. Set bytes 20 to 27 to 0 for now. */ -static int burn_create_bl_size_packs(int block, unsigned char *char_codes, - unsigned char *copyrights, - unsigned char *languages, - int num_tracks, - struct burn_pack_cursor *crs, int flag) -{ - int i, ret; - unsigned char payload[12]; - /* Normal is track_offset = 0. - But if the CUE sheet supports offset, then it is needed here too */ - int track_offset = 0; - - payload[0] = char_codes[block]; - payload[1] = 1 + track_offset; - payload[2] = num_tracks + track_offset; - payload[3] = copyrights[block]; - for (i = 0; i < 8; i++) - payload[i + 4] = crs->pack_count[i]; - ret = burn_create_tybl_packs(payload, 12, 0, 0x8f, block, crs, 0); - if (ret <= 0) - return ret; - - for (i = 0; i < 7; i++) - payload[i] = crs->pack_count[i + 8]; - payload[7] = 3; /* always 3 packs of type 0x8f */ - for (i = 0; i < 4; i++) { - /* Will be set when all blocks are done */ - payload[i + 8] = 0; - } - ret = burn_create_tybl_packs(payload, 12, 1, 0x8f, block, crs, 0); - if (ret <= 0) - return ret; - - for (i = 0; i < 4; i++) { - /* Will be set when all blocks are done */ - payload[i] = 0; - } - for (i = 0; i < 8; i++) { - payload[i + 4] = languages[i]; - } - ret = burn_create_tybl_packs(payload, 12, 2, 0x8f, block, crs, 0); - if (ret <= 0) - return ret; - ret = burn_finalize_text_pack(crs, 0); - if (ret <= 0) - return ret; - - for (i = 0; i < 16; i++) - crs->pack_count[i] = 0; - return 1; -} - - -/* Text packs of track for type and block - @param flag bit0= write TAB, because content is identical to previous track -*/ -static int burn_create_tybl_t_packs(struct burn_track *t, int track_no, - int pack_type, int block, - struct burn_pack_cursor *crs, int flag) -{ - int ret, length = 0, idx, double_byte, flags= 0; - unsigned char *payload = NULL, dummy[8]; - struct burn_cdtext *cdt; - - cdt = t->cdtext[block]; - idx = pack_type - Libburn_pack_type_basE; - if (cdt != NULL) { - if (cdt->length[idx] > 0) { - payload = cdt->payload[idx]; - length = cdt->length[idx]; - } - flags = cdt->flags; - } - if (payload == NULL) { - dummy[0]= 0; - payload = dummy; - length = strlen((char *) dummy) + 1; - } - double_byte = !!(flags & (1 <<(pack_type - Libburn_pack_type_basE))); - if (flag & 1) { - length = 0; - dummy[length++] = 9; - if (double_byte) - dummy[length++] = 9; - dummy[length++] = 0; - if (double_byte) - dummy[length++] = 0; - payload = dummy; - } - ret = burn_create_tybl_packs(payload, length, track_no, - pack_type, block, crs, double_byte); - return ret; -} - - -/* Check whether the content is the same as in the previous pack. If so, - advise to use the TAB abbreviation. -*/ -static int burn_decide_cdtext_tab(int block, int pack_type, - struct burn_cdtext *cdt_curr, - struct burn_cdtext *cdt_prev, int flag) -{ - int length, j, idx; - - idx = pack_type - Libburn_pack_type_basE; - if (cdt_curr == NULL || cdt_prev == NULL) - return 0; - if (((cdt_curr->flags >> idx) & 1) != ((cdt_prev->flags >> idx) & 1)) - return 0; - length = cdt_curr->length[idx]; - if (length != cdt_prev->length[idx] || - length <= 1 + ((cdt_curr->flags >> idx) & 1)) - return 0; - for (j = 0; j < length; j++) - if (cdt_curr->payload[idx][j] != cdt_prev->payload[idx][j]) - break; - if (j < length) - return 0; - return 1; -} - - -/* Text packs of session and of tracks (if applicable), for type and block -*/ -static int burn_create_tybl_s_packs(struct burn_session *s, - int pack_type, int block, - struct burn_pack_cursor *crs, int flag) -{ - int i, ret, idx, double_byte, use_tab; - struct burn_cdtext *cdt; - /* Normal is track_offset = 0. - But if the CUE sheet supports offset, then it is needed here too */ - int track_offset = 0; - - cdt = s->cdtext[block]; - idx = pack_type - Libburn_pack_type_basE; - if (cdt->length[idx] == 0 || cdt->payload[idx] == NULL) - return 1; - - double_byte = !!(cdt->flags & - (1 <<(pack_type - Libburn_pack_type_basE))); - ret = burn_create_tybl_packs(cdt->payload[idx], cdt->length[idx], 0, - pack_type, block, crs, double_byte); - if (ret <= 0) - return ret; - - if ((pack_type < 0x80 || pack_type > 0x85) && pack_type != 0x8e) { - ret = burn_finalize_text_pack(crs, 0); - return ret; - } - - for (i = 0; i < s->tracks; i++) { - if (i > 0) - use_tab = burn_decide_cdtext_tab(block, pack_type, - s->track[i]->cdtext[block], - s->track[i - 1]->cdtext[block], 0); - else - use_tab = 0; - ret = burn_create_tybl_t_packs(s->track[i], - i + 1 + track_offset, pack_type, - block, crs, use_tab); - if (ret <= 0) - return ret; - } - /* Fill up last pack with 0s */ - ret = burn_finalize_text_pack(crs, 0); - return ret; -} - - -/* ts B11210 : API */ -/* @param flag bit0= do not return CD-TEXT packs, but return number of packs -*/ -int burn_cdtext_from_session(struct burn_session *s, - unsigned char **text_packs, int *num_packs, - int flag) -{ - int pack_type, block, ret, i, idx, j, residue; - struct burn_pack_cursor crs; - - if (text_packs == NULL || num_packs == NULL) { - flag |= 1; - } else if (!(flag & 1)) { - *text_packs = NULL; - *num_packs = 0; - } - memset(&crs, 0, sizeof(struct burn_pack_cursor)); - BURN_ALLOC_MEM(crs.packs, unsigned char, - Libburn_leadin_cdtext_packs_maX * 18); - - for (block = 0; block < 8; block++) - if (s->cdtext[block] != NULL) - break; - if (block == 8) - {ret = 1; goto ex;} - - for (block= 0; block < 8; block++) { - if (s->cdtext[block] == NULL) - continue; - for (pack_type = 0x80; - pack_type < 0x80 + Libburn_pack_num_typeS; pack_type++) { - if (pack_type == 0x8f) - continue; - ret = burn_create_tybl_s_packs(s, - pack_type, block, &crs, 0); - if (ret <= 0) - goto ex; - } - ret = burn_create_bl_size_packs(block, - s->cdtext_char_code, s->cdtext_copyright, - s->cdtext_language, s->tracks, &crs, 0); - if (ret <= 0) - goto ex; - } - - /* Insert the highest sequence numbers of each block into - the 0x8f packs 2 and 3 (bytes 20 to 27) - */ - for (i = 0; i < crs.num_packs; i++) { - idx = i * 18; - if (crs.packs[idx] == 0x8f && crs.packs[idx + 1] == 1) { - for (j = 0; j < 4; j++) - if (crs.hiseq[j] > 0) - crs.packs[idx + 4 + 8 + j] = - crs.hiseq[j] - 1; - else - crs.packs[idx + 4 + 8 + j] = 0; - } else if (crs.packs[idx] == 0x8f && crs.packs[idx + 1] == 2) { - for (j = 0; j < 4; j++) - if (crs.hiseq[j + 4] > 0) - crs.packs[idx + 4 + j] = - crs.hiseq[j + 4] - 1; - else - crs.packs[idx + 4 + j] = 0; - } else - continue; - /* Re-compute checksum */ - residue = crc_11021(crs.packs + idx, 16, 0) ^ 0xffff; - crs.packs[idx + 16] = (residue >> 8) & 0xff; - crs.packs[idx + 17] = residue & 0xff; - } - - ret = 1; -ex:; - if (ret <= 0 || (flag & 1)) { - if (ret > 0) - ret = crs.num_packs; - else if (flag & 1) - ret = -1; - BURN_FREE_MEM(crs.packs); - } else if (crs.num_packs > 0) { - *text_packs = crs.packs; - *num_packs = crs.num_packs; - } - return(ret); -} - - static int burn_create_text_packs(struct burn_write_opts *o, struct burn_session *s, int flag)