From 57d29ae3e522c3b1310076336430f32b429aeb09 Mon Sep 17 00:00:00 2001 From: Andre Zeps Date: Sun, 19 Jan 2025 08:49:05 +0100 Subject: [PATCH] Philips CD-i: Subcode and image handling (#954) * Philips CD-i: Rewritten image handling Added subchannel Q data Added Table of Contents Fixed differences between CUE and CHD Fixed handling of data in pregap * Philips CD-i: Add support for scrambled sectors Fixes "The Apprentice (Europe)" --- support/cdi/cdi.cpp | 544 ++++++++++++++++++++++++++++++++++++-------- user_io.cpp | 10 +- 2 files changed, 456 insertions(+), 98 deletions(-) diff --git a/support/cdi/cdi.cpp b/support/cdi/cdi.cpp index 21035ef..3fe3807 100644 --- a/support/cdi/cdi.cpp +++ b/support/cdi/cdi.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "../../file_io.h" @@ -13,9 +14,39 @@ #include "../../cd.h" #include "../chd/mister_chd.h" #include +#include + +struct subcode +{ + uint16_t control; + uint16_t track; + uint16_t index; + uint16_t mode1_mins; + uint16_t mode1_secs; + uint16_t mode1_frac; + uint16_t mode1_zero; + uint16_t mode1_amins; + uint16_t mode1_asecs; + uint16_t mode1_afrac; + uint16_t mode1_crc0; + uint16_t mode1_crc1; +}; +static_assert(sizeof(struct subcode) == 24); + +struct toc_entry +{ + uint8_t control; + uint8_t track; + uint8_t m; + uint8_t s; + uint8_t f; +}; static char buf[1024]; #define CD_SECTOR_LEN 2352 +#define CDIC_BUFFER_SIZE (CD_SECTOR_LEN + sizeof(subcode)) +static std::array toc_buffer; +uint32_t toc_entry_count = 0; static uint8_t *chd_hunkbuf = NULL; static int chd_hunknum; @@ -84,28 +115,17 @@ static int load_chd(const char *filename, toc_t *table) return 0; } - /* CD-i core expects the TOC values for track start/end to not take into account - * pregap, unlike some other cores. Adjust the CHD toc to reflect this - */ - for (int i = 0; i < table->last; i++) { - if (i == 0) // First track fakes a pregap even if it doesn't exist - { - table->tracks[i].indexes[1] = 150; - table->tracks[i].start = 150; - table->tracks[i].end += 150 - 1; - } - else - { - int frame_cnt = table->tracks[i].end - table->tracks[i].start; - frame_cnt += table->tracks[i].indexes[1]; - table->tracks[i].start = table->tracks[i - 1].end + 1; - table->tracks[i].end = table->tracks[i].start + frame_cnt - 1; - } + table->tracks[i].pregap = table->tracks[i].indexes[1]; + table->tracks[i].start += 150; + table->tracks[i].end += 150; + + printf("\x1b[32mCHD: Track = %u, start = %u, end = %u, offset = %d, sector_size=%d, type = %u, pregap = %u\n\x1b[0m", i, table->tracks[i].start, table->tracks[i].end, table->tracks[i].offset, table->tracks[i].sector_size, table->tracks[i].type, table->tracks[i].pregap); + printf("\x1b[32mCHD: Track = %u, Index %u %u seconds\n\x1b[0m", i, table->tracks[i].indexes[0], table->tracks[i].indexes[1]); } - table->end = table->tracks[table->last - 1].end + 1; + table->end += 150; chd_hunkbuf = (uint8_t *)malloc(table->chd_hunksize); chd_hunknum = -1; @@ -133,7 +153,8 @@ static int load_cue(const char *filename, toc_t *table) } int mm, ss, bb; - int pregap = 0; + int index0 = 0; + int index1 = 0; char *buf = toc; while (sgets(line, sizeof(line), &buf)) @@ -186,14 +207,12 @@ static int load_cue(const char *filename, toc_t *table) /* decode PREGAP commands */ else if (sscanf(lptr, "PREGAP %02d:%02d:%02d", &mm, &ss, &bb) == 3) { - // Single bin specific, add pregab but subtract inherent pregap - pregap += bb + ss * 75 + mm * 60 * 75; - table->tracks[table->last].pregap = 1; + // TODO Find an example image } /* decode TRACK commands */ else if ((sscanf(lptr, "TRACK %02d %*s", &bb)) || (sscanf(lptr, "TRACK %d %*s", &bb))) { - pregap = 0; + index0 = 0; if (bb != (table->last + 1)) { FileClose(&table->tracks[table->last].f); @@ -212,6 +231,8 @@ static int load_cue(const char *filename, toc_t *table) { table->tracks[table->last].sector_size = CD_SECTOR_LEN; table->tracks[table->last].type = 0; + if (!table->last) + table->end = 150; // implicit 2 seconds pregap for track 1 } else { @@ -225,51 +246,25 @@ static int load_cue(const char *filename, toc_t *table) else if ((sscanf(lptr, "INDEX 00 %02d:%02d:%02d", &mm, &ss, &bb) == 3) || (sscanf(lptr, "INDEX 0 %02d:%02d:%02d", &mm, &ss, &bb) == 3)) { - // Single bin specific - if (!table->tracks[table->last].f.opened()) - { - - pregap = bb + ss * 75 + mm * 60 * 75; - } + index0 = bb + ss * 75 + mm * 60 * 75; } else if ((sscanf(lptr, "INDEX 01 %02d:%02d:%02d", &mm, &ss, &bb) == 3) || (sscanf(lptr, "INDEX 1 %02d:%02d:%02d", &mm, &ss, &bb) == 3)) { + index1 = bb + ss * 75 + mm * 60 * 75; + if (!table->tracks[table->last].f.opened()) { - table->tracks[table->last].start = bb + ss * 75 + mm * 60 * 75; - if (table->tracks[table->last].pregap) - table->tracks[table->last].start += pregap; + table->tracks[table->last].start = index1 + 150; + table->tracks[table->last].pregap = index1 - index0; // Subtract the fake 150 sector pregap used for the first data track - table->tracks[table->last].offset = table->tracks[table->last].start * table->tracks[table->last].sector_size; - if (table->last) - { - table->tracks[table->last - 1].end = table->tracks[table->last].start - 1; - if (pregap) - { - table->tracks[table->last].indexes[1] = table->tracks[table->last].start - pregap; - if (!table->tracks[table->last].pregap) - { - table->tracks[table->last].offset -= CD_SECTOR_LEN * table->tracks[table->last].indexes[1]; - table->tracks[table->last].indexes[1] = table->tracks[table->last].start - pregap; - } - else - { - table->tracks[table->last].indexes[1] = pregap; - } - } - } - else if (table->tracks[table->last].type) - { - table->tracks[table->last].indexes[1] = 150; - } + table->tracks[table->last].offset = index0 * table->tracks[table->last].sector_size; + table->tracks[table->last - 1].end = table->tracks[table->last].start - 1 - table->tracks[table->last].pregap; } else { - table->tracks[table->last].indexes[1] = bb + ss * 75 + mm * 60 * 75; - if (table->tracks[table->last].type && !table->last) - table->tracks[table->last].indexes[1] = 150; - table->tracks[table->last].start = table->end; + table->tracks[table->last].start = table->end + index0 + index1; + table->tracks[table->last].pregap = index1 - index0; table->end += (table->tracks[table->last].f.size / table->tracks[table->last].sector_size); table->tracks[table->last].offset = 0; } @@ -282,9 +277,7 @@ static int load_cue(const char *filename, toc_t *table) for (int i = 0; i < table->last; i++) { - printf("\x1b[32mCDI: Track = %u, start = %u, end = %u, offset = %d, sector_size=%d, type = %u\n\x1b[0m", i, table->tracks[i].start, table->tracks[i].end, table->tracks[i].offset, table->tracks[i].sector_size, table->tracks[i].type); - if (table->tracks[i].indexes[1]) - printf("\x1b[32mCDI: Track = %u,Index1 = %u seconds\n\x1b[0m", i, table->tracks[i].indexes[1] / 75); + printf("\x1b[32mCUE: Track = %u, start = %u, end = %u, offset = %d, sector_size=%d, type = %u, pregap = %u\n\x1b[0m", i, table->tracks[i].start, table->tracks[i].end, table->tracks[i].offset, table->tracks[i].sector_size, table->tracks[i].type, table->tracks[i].pregap); } return 1; @@ -309,23 +302,52 @@ static int load_cd_image(const char *filename, toc_t *table) return 0; } -struct track_t +static void prepare_toc_buffer(toc_t *toc) { - uint32_t start_lba; - uint32_t end_lba; - uint32_t bcd; - uint32_t reserved; -}; + struct toc_entry *toc_ptr = toc_buffer.data(); + toc_entry_count = 0; -struct disk_t -{ - uint32_t track_count; - uint32_t total_lba; - uint32_t total_bcd; - uint16_t libcrypt_mask; - uint16_t metadata; // lower 2 bits encode the region, 3rd bit is reset request, the other bits are reseved - track_t track[99]; -}; + auto add_entry = [&](uint8_t control, uint8_t track, uint8_t m, uint8_t s, uint8_t f) + { + for (int i = 0; i < 3; i++) + { + toc_ptr->control = control; + toc_ptr->track = track; + toc_ptr->m = m; + toc_ptr->s = s; + toc_ptr->f = f; + + toc_ptr++; + + if (toc_entry_count < toc_buffer.size()) + toc_entry_count++; + } + }; + + for (int i = 0; i < toc->last; i++) + { + int lba = toc->tracks[i].start; + uint8_t m, s, f; + m = lba / (60 * 75); + lba -= m * (60 * 75); + s = lba / 75; + f = lba % 75; + add_entry((toc->tracks[i].type ? 0x41 : 0x01), BCD(i + 1), BCD(m), BCD(s), BCD(f)); + } + + add_entry(1, 0xA0, 1, 0, 0); + add_entry(1, 0xA1, BCD(toc->last), 0, 0); + + { + int lba = toc->end; + uint8_t m, s, f; + m = lba / (60 * 75); + lba -= m * (60 * 75); + s = lba / 75; + f = lba % 75; + add_entry(1, 0xA2, BCD(m), BCD(s), BCD(f)); + } +} #define TIMEKEEPER_SIZE (8 * 1024) @@ -355,13 +377,349 @@ int cdi_chd_hunksize() return 0; } +// CRC routine from https://github.com/mamedev/mame/blob/master/src/mame/philips/cdicdic.cpp +const uint16_t s_crc_ccitt_table[256] = + { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; + +#define CRC_CCITT_ROUND(accum, data) (((accum << 8) | data) ^ s_crc_ccitt_table[accum >> 8]) + +// sector descrambling routine from https://github.com/mamedev/mame/blob/master/src/mame/philips/cdicdic.cpp +const uint8_t s_sector_scramble[] = + { + 0x01, 0x80, 0x00, 0x60, 0x00, 0x28, 0x00, 0x1e, 0x80, 0x08, 0x60, 0x06, 0xa8, 0x02, 0xfe, 0x81, + 0x80, 0x60, 0x60, 0x28, 0x28, 0x1e, 0x9e, 0x88, 0x68, 0x66, 0xae, 0xaa, 0xfc, 0x7f, 0x01, 0xe0, + 0x00, 0x48, 0x00, 0x36, 0x80, 0x16, 0xe0, 0x0e, 0xc8, 0x04, 0x56, 0x83, 0x7e, 0xe1, 0xe0, 0x48, + 0x48, 0x36, 0xb6, 0x96, 0xf6, 0xee, 0xc6, 0xcc, 0x52, 0xd5, 0xfd, 0x9f, 0x01, 0xa8, 0x00, 0x7e, + 0x80, 0x20, 0x60, 0x18, 0x28, 0x0a, 0x9e, 0x87, 0x28, 0x62, 0x9e, 0xa9, 0xa8, 0x7e, 0xfe, 0xa0, + 0x40, 0x78, 0x30, 0x22, 0x94, 0x19, 0xaf, 0x4a, 0xfc, 0x37, 0x01, 0xd6, 0x80, 0x5e, 0xe0, 0x38, + 0x48, 0x12, 0xb6, 0x8d, 0xb6, 0xe5, 0xb6, 0xcb, 0x36, 0xd7, 0x56, 0xde, 0xbe, 0xd8, 0x70, 0x5a, + 0xa4, 0x3b, 0x3b, 0x53, 0x53, 0x7d, 0xfd, 0xe1, 0x81, 0x88, 0x60, 0x66, 0xa8, 0x2a, 0xfe, 0x9f, + 0x00, 0x68, 0x00, 0x2e, 0x80, 0x1c, 0x60, 0x09, 0xe8, 0x06, 0xce, 0x82, 0xd4, 0x61, 0x9f, 0x68, + 0x68, 0x2e, 0xae, 0x9c, 0x7c, 0x69, 0xe1, 0xee, 0xc8, 0x4c, 0x56, 0xb5, 0xfe, 0xf7, 0x00, 0x46, + 0x80, 0x32, 0xe0, 0x15, 0x88, 0x0f, 0x26, 0x84, 0x1a, 0xe3, 0x4b, 0x09, 0xf7, 0x46, 0xc6, 0xb2, + 0xd2, 0xf5, 0x9d, 0x87, 0x29, 0xa2, 0x9e, 0xf9, 0xa8, 0x42, 0xfe, 0xb1, 0x80, 0x74, 0x60, 0x27, + 0x68, 0x1a, 0xae, 0x8b, 0x3c, 0x67, 0x51, 0xea, 0xbc, 0x4f, 0x31, 0xf4, 0x14, 0x47, 0x4f, 0x72, + 0xb4, 0x25, 0xb7, 0x5b, 0x36, 0xbb, 0x56, 0xf3, 0x7e, 0xc5, 0xe0, 0x53, 0x08, 0x3d, 0xc6, 0x91, + 0x92, 0xec, 0x6d, 0x8d, 0xed, 0xa5, 0x8d, 0xbb, 0x25, 0xb3, 0x5b, 0x35, 0xfb, 0x57, 0x03, 0x7e, + 0x81, 0xe0, 0x60, 0x48, 0x28, 0x36, 0x9e, 0x96, 0xe8, 0x6e, 0xce, 0xac, 0x54, 0x7d, 0xff, 0x61, + 0x80, 0x28, 0x60, 0x1e, 0xa8, 0x08, 0x7e, 0x86, 0xa0, 0x62, 0xf8, 0x29, 0x82, 0x9e, 0xe1, 0xa8, + 0x48, 0x7e, 0xb6, 0xa0, 0x76, 0xf8, 0x26, 0xc2, 0x9a, 0xd1, 0xab, 0x1c, 0x7f, 0x49, 0xe0, 0x36, + 0xc8, 0x16, 0xd6, 0x8e, 0xde, 0xe4, 0x58, 0x4b, 0x7a, 0xb7, 0x63, 0x36, 0xa9, 0xd6, 0xfe, 0xde, + 0xc0, 0x58, 0x50, 0x3a, 0xbc, 0x13, 0x31, 0xcd, 0xd4, 0x55, 0x9f, 0x7f, 0x28, 0x20, 0x1e, 0x98, + 0x08, 0x6a, 0x86, 0xaf, 0x22, 0xfc, 0x19, 0x81, 0xca, 0xe0, 0x57, 0x08, 0x3e, 0x86, 0x90, 0x62, + 0xec, 0x29, 0x8d, 0xde, 0xe5, 0x98, 0x4b, 0x2a, 0xb7, 0x5f, 0x36, 0xb8, 0x16, 0xf2, 0x8e, 0xc5, + 0xa4, 0x53, 0x3b, 0x7d, 0xd3, 0x61, 0x9d, 0xe8, 0x69, 0x8e, 0xae, 0xe4, 0x7c, 0x4b, 0x61, 0xf7, + 0x68, 0x46, 0xae, 0xb2, 0xfc, 0x75, 0x81, 0xe7, 0x20, 0x4a, 0x98, 0x37, 0x2a, 0x96, 0x9f, 0x2e, + 0xe8, 0x1c, 0x4e, 0x89, 0xf4, 0x66, 0xc7, 0x6a, 0xd2, 0xaf, 0x1d, 0xbc, 0x09, 0xb1, 0xc6, 0xf4, + 0x52, 0xc7, 0x7d, 0x92, 0xa1, 0xad, 0xb8, 0x7d, 0xb2, 0xa1, 0xb5, 0xb8, 0x77, 0x32, 0xa6, 0x95, + 0xba, 0xef, 0x33, 0x0c, 0x15, 0xc5, 0xcf, 0x13, 0x14, 0x0d, 0xcf, 0x45, 0x94, 0x33, 0x2f, 0x55, + 0xdc, 0x3f, 0x19, 0xd0, 0x0a, 0xdc, 0x07, 0x19, 0xc2, 0x8a, 0xd1, 0xa7, 0x1c, 0x7a, 0x89, 0xe3, + 0x26, 0xc9, 0xda, 0xd6, 0xdb, 0x1e, 0xdb, 0x48, 0x5b, 0x76, 0xbb, 0x66, 0xf3, 0x6a, 0xc5, 0xef, + 0x13, 0x0c, 0x0d, 0xc5, 0xc5, 0x93, 0x13, 0x2d, 0xcd, 0xdd, 0x95, 0x99, 0xaf, 0x2a, 0xfc, 0x1f, + 0x01, 0xc8, 0x00, 0x56, 0x80, 0x3e, 0xe0, 0x10, 0x48, 0x0c, 0x36, 0x85, 0xd6, 0xe3, 0x1e, 0xc9, + 0xc8, 0x56, 0xd6, 0xbe, 0xde, 0xf0, 0x58, 0x44, 0x3a, 0xb3, 0x53, 0x35, 0xfd, 0xd7, 0x01, 0x9e, + 0x80, 0x68, 0x60, 0x2e, 0xa8, 0x1c, 0x7e, 0x89, 0xe0, 0x66, 0xc8, 0x2a, 0xd6, 0x9f, 0x1e, 0xe8, + 0x08, 0x4e, 0x86, 0xb4, 0x62, 0xf7, 0x69, 0x86, 0xae, 0xe2, 0xfc, 0x49, 0x81, 0xf6, 0xe0, 0x46, + 0xc8, 0x32, 0xd6, 0x95, 0x9e, 0xef, 0x28, 0x4c, 0x1e, 0xb5, 0xc8, 0x77, 0x16, 0xa6, 0x8e, 0xfa, + 0xe4, 0x43, 0x0b, 0x71, 0xc7, 0x64, 0x52, 0xab, 0x7d, 0xbf, 0x61, 0xb0, 0x28, 0x74, 0x1e, 0xa7, + 0x48, 0x7a, 0xb6, 0xa3, 0x36, 0xf9, 0xd6, 0xc2, 0xde, 0xd1, 0x98, 0x5c, 0x6a, 0xb9, 0xef, 0x32, + 0xcc, 0x15, 0x95, 0xcf, 0x2f, 0x14, 0x1c, 0x0f, 0x49, 0xc4, 0x36, 0xd3, 0x56, 0xdd, 0xfe, 0xd9, + 0x80, 0x5a, 0xe0, 0x3b, 0x08, 0x13, 0x46, 0x8d, 0xf2, 0xe5, 0x85, 0x8b, 0x23, 0x27, 0x59, 0xda, + 0xba, 0xdb, 0x33, 0x1b, 0x55, 0xcb, 0x7f, 0x17, 0x60, 0x0e, 0xa8, 0x04, 0x7e, 0x83, 0x60, 0x61, + 0xe8, 0x28, 0x4e, 0x9e, 0xb4, 0x68, 0x77, 0x6e, 0xa6, 0xac, 0x7a, 0xfd, 0xe3, 0x01, 0x89, 0xc0, + 0x66, 0xd0, 0x2a, 0xdc, 0x1f, 0x19, 0xc8, 0x0a, 0xd6, 0x87, 0x1e, 0xe2, 0x88, 0x49, 0xa6, 0xb6, + 0xfa, 0xf6, 0xc3, 0x06, 0xd1, 0xc2, 0xdc, 0x51, 0x99, 0xfc, 0x6a, 0xc1, 0xef, 0x10, 0x4c, 0x0c, + 0x35, 0xc5, 0xd7, 0x13, 0x1e, 0x8d, 0xc8, 0x65, 0x96, 0xab, 0x2e, 0xff, 0x5c, 0x40, 0x39, 0xf0, + 0x12, 0xc4, 0x0d, 0x93, 0x45, 0xad, 0xf3, 0x3d, 0x85, 0xd1, 0xa3, 0x1c, 0x79, 0xc9, 0xe2, 0xd6, + 0xc9, 0x9e, 0xd6, 0xe8, 0x5e, 0xce, 0xb8, 0x54, 0x72, 0xbf, 0x65, 0xb0, 0x2b, 0x34, 0x1f, 0x57, + 0x48, 0x3e, 0xb6, 0x90, 0x76, 0xec, 0x26, 0xcd, 0xda, 0xd5, 0x9b, 0x1f, 0x2b, 0x48, 0x1f, 0x76, + 0x88, 0x26, 0xe6, 0x9a, 0xca, 0xeb, 0x17, 0x0f, 0x4e, 0x84, 0x34, 0x63, 0x57, 0x69, 0xfe, 0xae, + 0xc0, 0x7c, 0x50, 0x21, 0xfc, 0x18, 0x41, 0xca, 0xb0, 0x57, 0x34, 0x3e, 0x97, 0x50, 0x6e, 0xbc, + 0x2c, 0x71, 0xdd, 0xe4, 0x59, 0x8b, 0x7a, 0xe7, 0x63, 0x0a, 0xa9, 0xc7, 0x3e, 0xd2, 0x90, 0x5d, + 0xac, 0x39, 0xbd, 0xd2, 0xf1, 0x9d, 0x84, 0x69, 0xa3, 0x6e, 0xf9, 0xec, 0x42, 0xcd, 0xf1, 0x95, + 0x84, 0x6f, 0x23, 0x6c, 0x19, 0xed, 0xca, 0xcd, 0x97, 0x15, 0xae, 0x8f, 0x3c, 0x64, 0x11, 0xeb, + 0x4c, 0x4f, 0x75, 0xf4, 0x27, 0x07, 0x5a, 0x82, 0xbb, 0x21, 0xb3, 0x58, 0x75, 0xfa, 0xa7, 0x03, + 0x3a, 0x81, 0xd3, 0x20, 0x5d, 0xd8, 0x39, 0x9a, 0x92, 0xeb, 0x2d, 0x8f, 0x5d, 0xa4, 0x39, 0xbb, + 0x52, 0xf3, 0x7d, 0x85, 0xe1, 0xa3, 0x08, 0x79, 0xc6, 0xa2, 0xd2, 0xf9, 0x9d, 0x82, 0xe9, 0xa1, + 0x8e, 0xf8, 0x64, 0x42, 0xab, 0x71, 0xbf, 0x64, 0x70, 0x2b, 0x64, 0x1f, 0x6b, 0x48, 0x2f, 0x76, + 0x9c, 0x26, 0xe9, 0xda, 0xce, 0xdb, 0x14, 0x5b, 0x4f, 0x7b, 0x74, 0x23, 0x67, 0x59, 0xea, 0xba, + 0xcf, 0x33, 0x14, 0x15, 0xcf, 0x4f, 0x14, 0x34, 0x0f, 0x57, 0x44, 0x3e, 0xb3, 0x50, 0x75, 0xfc, + 0x27, 0x01, 0xda, 0x80, 0x5b, 0x20, 0x3b, 0x58, 0x13, 0x7a, 0x8d, 0xe3, 0x25, 0x89, 0xdb, 0x26, + 0xdb, 0x5a, 0xdb, 0x7b, 0x1b, 0x63, 0x4b, 0x69, 0xf7, 0x6e, 0xc6, 0xac, 0x52, 0xfd, 0xfd, 0x81, + 0x81, 0xa0, 0x60, 0x78, 0x28, 0x22, 0x9e, 0x99, 0xa8, 0x6a, 0xfe, 0xaf, 0x00, 0x7c, 0x00, 0x21, + 0xc0, 0x18, 0x50, 0x0a, 0xbc, 0x07, 0x31, 0xc2, 0x94, 0x51, 0xaf, 0x7c, 0x7c, 0x21, 0xe1, 0xd8, + 0x48, 0x5a, 0xb6, 0xbb, 0x36, 0xf3, 0x56, 0xc5, 0xfe, 0xd3, 0x00, 0x5d, 0xc0, 0x39, 0x90, 0x12, + 0xec, 0x0d, 0x8d, 0xc5, 0xa5, 0x93, 0x3b, 0x2d, 0xd3, 0x5d, 0x9d, 0xf9, 0xa9, 0x82, 0xfe, 0xe1, + 0x80, 0x48, 0x60, 0x36, 0xa8, 0x16, 0xfe, 0x8e, 0xc0, 0x64, 0x50, 0x2b, 0x7c, 0x1f, 0x61, 0xc8, + 0x28, 0x56, 0x9e, 0xbe, 0xe8, 0x70, 0x4e, 0xa4, 0x34, 0x7b, 0x57, 0x63, 0x7e, 0xa9, 0xe0, 0x7e, + 0xc8, 0x20, 0x56, 0x98, 0x3e, 0xea, 0x90, 0x4f, 0x2c, 0x34, 0x1d, 0xd7, 0x49, 0x9e, 0xb6, 0xe8, + 0x76, 0xce, 0xa6, 0xd4, 0x7a, 0xdf, 0x63, 0x18, 0x29, 0xca, 0x9e, 0xd7, 0x28, 0x5e, 0x9e, 0xb8, + 0x68, 0x72, 0xae, 0xa5, 0xbc, 0x7b, 0x31, 0xe3, 0x54, 0x49, 0xff, 0x76, 0xc0, 0x26, 0xd0, 0x1a, + 0xdc, 0x0b, 0x19, 0xc7, 0x4a, 0xd2, 0xb7, 0x1d, 0xb6, 0x89, 0xb6, 0xe6, 0xf6, 0xca, 0xc6, 0xd7, + 0x12, 0xde, 0x8d, 0x98, 0x65, 0xaa, 0xab, 0x3f, 0x3f, 0x50, 0x10, 0x3c, 0x0c, 0x11, 0xc5, 0xcc, + 0x53, 0x15, 0xfd, 0xcf, 0x01, 0x94, 0x00, 0x6f, 0x40, 0x2c, 0x30, 0x1d, 0xd4, 0x09, 0x9f, 0x46, + 0xe8, 0x32, 0xce, 0x95, 0x94, 0x6f, 0x2f, 0x6c, 0x1c, 0x2d, 0xc9, 0xdd, 0x96, 0xd9, 0xae, 0xda, + 0xfc, 0x5b, 0x01, 0xfb, 0x40, 0x43, 0x70, 0x31, 0xe4, 0x14, 0x4b, 0x4f, 0x77, 0x74, 0x26, 0xa7, + 0x5a, 0xfa, 0xbb, 0x03, 0x33, 0x41, 0xd5, 0xf0, 0x5f, 0x04, 0x38, 0x03, 0x52, 0x81, 0xfd, 0xa0, + 0x41, 0xb8, 0x30, 0x72, 0x94, 0x25, 0xaf, 0x5b, 0x3c, 0x3b, 0x51, 0xd3, 0x7c, 0x5d, 0xe1, 0xf9, + 0x88, 0x42, 0xe6, 0xb1, 0x8a, 0xf4, 0x67, 0x07, 0x6a, 0x82, 0xaf, 0x21, 0xbc, 0x18, 0x71, 0xca, + 0xa4, 0x57, 0x3b, 0x7e, 0x93, 0x60, 0x6d, 0xe8, 0x2d, 0x8e, 0x9d, 0xa4, 0x69, 0xbb, 0x6e, 0xf3, + 0x6c, 0x45, 0xed, 0xf3, 0x0d, 0x85, 0xc5, 0xa3, 0x13, 0x39, 0xcd, 0xd2, 0xd5, 0x9d, 0x9f, 0x29, + 0xa8, 0x1e, 0xfe, 0x88, 0x40, 0x66, 0xb0, 0x2a, 0xf4, 0x1f, 0x07, 0x48, 0x02, 0xb6, 0x81, 0xb6, + 0xe0, 0x76, 0xc8, 0x26, 0xd6, 0x9a, 0xde, 0xeb, 0x18, 0x4f, 0x4a, 0xb4, 0x37, 0x37, 0x56, 0x96, + 0xbe, 0xee, 0xf0, 0x4c, 0x44, 0x35, 0xf3, 0x57, 0x05, 0xfe, 0x83, 0x00, 0x61, 0xc0, 0x28, 0x50, + 0x1e, 0xbc, 0x08, 0x71, 0xc6, 0xa4, 0x52, 0xfb, 0x7d, 0x83, 0x61, 0xa1, 0xe8, 0x78, 0x4e, 0xa2, + 0xb4, 0x79, 0xb7, 0x62, 0xf6, 0xa9, 0x86, 0xfe, 0xe2, 0xc0, 0x49, 0x90, 0x36, 0xec, 0x16, 0xcd, + 0xce, 0xd5, 0x94, 0x5f, 0x2f, 0x78, 0x1c, 0x22, 0x89, 0xd9, 0xa6, 0xda, 0xfa, 0xdb, 0x03, 0x1b, + 0x41, 0xcb, 0x70, 0x57, 0x64, 0x3e, 0xab, 0x50, 0x7f, 0x7c, 0x20, 0x21, 0xd8, 0x18, 0x5a, 0x8a, + 0xbb, 0x27, 0x33, 0x5a, 0x95, 0xfb, 0x2f, 0x03, 0x5c, 0x01, 0xf9, 0xc0, 0x42, 0xd0, 0x31, 0x9c, + 0x14, 0x69, 0xcf, 0x6e, 0xd4, 0x2c, 0x5f, 0x5d, 0xf8, 0x39, 0x82, 0x92, 0xe1, 0xad, 0x88, 0x7d, + 0xa6, 0xa1, 0xba, 0xf8, 0x73, 0x02, 0xa5, 0xc1, 0xbb, 0x10, 0x73, 0x4c, 0x25, 0xf5, 0xdb, 0x07, + 0x1b, 0x42, 0x8b, 0x71, 0xa7, 0x64, 0x7a, 0xab, 0x63, 0x3f, 0x69, 0xd0, 0x2e, 0xdc, 0x1c, 0x59, + 0xc9, 0xfa, 0xd6, 0xc3, 0x1e, 0xd1, 0xc8, 0x5c, 0x56, 0xb9, 0xfe, 0xf2, 0xc0, 0x45, 0x90, 0x33, + 0x2c, 0x15, 0xdd, 0xcf, 0x19, 0x94, 0x0a, 0xef, 0x47, 0x0c, 0x32, 0x85, 0xd5, 0xa3, 0x1f, 0x39, + 0xc8, 0x12, 0xd6, 0x8d, 0x9e, 0xe5, 0xa8, 0x4b, 0x3e, 0xb7, 0x50, 0x76, 0xbc, 0x26, 0xf1, 0xda, + 0xc4, 0x5b, 0x13, 0x7b, 0x4d, 0xe3, 0x75, 0x89, 0xe7, 0x26, 0xca, 0x9a, 0xd7, 0x2b, 0x1e, 0x9f, + 0x48, 0x68, 0x36, 0xae, 0x96, 0xfc, 0x6e, 0xc1, 0xec, 0x50, 0x4d, 0xfc, 0x35, 0x81, 0xd7, 0x20, + 0x5e, 0x98, 0x38, 0x6a, 0x92, 0xaf, 0x2d, 0xbc, 0x1d, 0xb1, 0xc9, 0xb4, 0x56, 0xf7, 0x7e, 0xc6, + 0xa0, 0x52, 0xf8, 0x3d, 0x82, 0x91, 0xa1, 0xac, 0x78, 0x7d, 0xe2, 0xa1, 0x89, 0xb8, 0x66, 0xf2, + 0xaa, 0xc5, 0xbf, 0x13, 0x30, 0x0d, 0xd4, 0x05, 0x9f, 0x43, 0x28, 0x31, 0xde, 0x94, 0x58, 0x6f, + 0x7a, 0xac, 0x23, 0x3d, 0xd9, 0xd1, 0x9a, 0xdc, 0x6b, 0x19, 0xef, 0x4a, 0xcc, 0x37, 0x15, 0xd6, + 0x8f, 0x1e, 0xe4, 0x08, 0x4b, 0x46, 0xb7, 0x72, 0xf6, 0xa5, 0x86, 0xfb, 0x22, 0xc3, 0x59, 0x91, + 0xfa, 0xec, 0x43, 0x0d, 0xf1, 0xc5, 0x84, 0x53, 0x23, 0x7d, 0xd9, 0xe1, 0x9a, 0xc8, 0x6b, 0x16, + 0xaf, 0x4e, 0xfc, 0x34, 0x41, 0xd7, 0x70, 0x5e, 0xa4, 0x38, 0x7b, 0x52, 0xa3, 0x7d, 0xb9, 0xe1, + 0xb2, 0xc8, 0x75, 0x96, 0xa7, 0x2e, 0xfa, 0x9c, 0x43, 0x29, 0xf1, 0xde, 0xc4, 0x58, 0x53, 0x7a, + 0xbd, 0xe3, 0x31, 0x89, 0xd4, 0x66, 0xdf, 0x6a, 0xd8, 0x2f, 0x1a, 0x9c, 0x0b, 0x29, 0xc7, 0x5e, + 0xd2, 0xb8, 0x5d, 0xb2, 0xb9, 0xb5, 0xb2, 0xf7, 0x35, 0x86, 0x97, 0x22, 0xee, 0x99, 0x8c, 0x6a, + 0xe5, 0xef, 0x0b, 0x0c, 0x07, 0x45, 0xc2, 0xb3, 0x11, 0xb5, 0xcc, 0x77, 0x15, 0xe6, 0x8f, 0x0a, + 0xe4, 0x07, 0x0b, 0x42, 0x87, 0x71, 0xa2, 0xa4, 0x79, 0xbb, 0x62, 0xf3, 0x69, 0x85, 0xee, 0xe3, + 0x0c, 0x49, 0xc5, 0xf6, 0xd3, 0x06, 0xdd, 0xc2, 0xd9, 0x91, 0x9a, 0xec, 0x6b, 0x0d, 0xef, 0x45, + 0x8c, 0x33, 0x25, 0xd5, 0xdb, 0x1f, 0x1b, 0x48, 0x0b, 0x76, 0x87, 0x66, 0xe2, 0xaa, 0xc9, 0xbf, + 0x16, 0xf0, 0x0e, 0xc4, 0x04, 0x53, 0x43, 0x7d, 0xf1, 0xe1, 0x84, 0x48, 0x63, 0x76, 0xa9, 0xe6, + 0xfe, 0xca, 0xc0, 0x57, 0x10, 0x3e, 0x8c, 0x10, 0x65, 0xcc, 0x2b, 0x15, 0xdf, 0x4f, 0x18, 0x34, + 0x0a, 0x97, 0x47, 0x2e, 0xb2, 0x9c, 0x75, 0xa9, 0xe7, 0x3e, 0xca, 0x90, 0x57, 0x2c, 0x3e, 0x9d, + 0xd0, 0x69, 0x9c, 0x2e, 0xe9, 0xdc, 0x4e, 0xd9, 0xf4, 0x5a, 0xc7, 0x7b, 0x12, 0xa3, 0x4d, 0xb9, + 0xf5, 0xb2, 0xc7, 0x35, 0x92, 0x97, 0x2d, 0xae, 0x9d, 0xbc, 0x69, 0xb1, 0xee, 0xf4, 0x4c, 0x47, + 0x75, 0xf2, 0xa7, 0x05, 0xba, 0x83, 0x33, 0x21, 0xd5, 0xd8, 0x5f, 0x1a, 0xb8, 0x0b, 0x32, 0x87, + 0x55, 0xa2, 0xbf, 0x39, 0xb0, 0x12, 0xf4, 0x0d, 0x87, 0x45, 0xa2, 0xb3, 0x39, 0xb5, 0xd2, 0xf7, + 0x1d, 0x86, 0x89, 0xa2, 0xe6, 0xf9, 0x8a, 0xc2, 0xe7, 0x11, 0x8a, 0x8c, 0x67, 0x25, 0xea, 0x9b, + 0x0f, 0x2b, 0x44, 0x1f, 0x73, 0x48, 0x25, 0xf6, 0x9b, 0x06, 0xeb, 0x42, 0xcf, 0x71, 0x94, 0x24, + 0x6f, 0x5b, 0x6c, 0x3b, 0x6d, 0xd3, 0x6d, 0x9d, 0xed, 0xa9, 0x8d, 0xbe, 0xe5, 0xb0, 0x4b, 0x34, + 0x37, 0x57, 0x56, 0xbe, 0xbe, 0xf0, 0x70, 0x44, 0x24, 0x33, 0x5b, 0x55, 0xfb, 0x7f, 0x03, 0x60, + 0x01, 0xe8, 0x00, 0x4e, 0x80, 0x34, 0x60, 0x17, 0x68, 0x0e, 0xae, 0x84, 0x7c, 0x63, 0x61, 0xe9, + 0xe8, 0x4e, 0xce, 0xb4, 0x54, 0x77, 0x7f, 0x66, 0xa0, 0x2a, 0xf8, 0x1f, 0x02, 0x88, 0x01, 0xa6, + 0x80, 0x7a, 0xe0, 0x23, 0x08, 0x19, 0xc6, 0x8a, 0xd2, 0xe7, 0x1d, 0x8a, 0x89, 0xa7, 0x26, 0xfa, + 0x9a, 0xc3, 0x2b, 0x11, 0xdf, 0x4c, 0x58, 0x35, 0xfa, 0x97, 0x03, 0x2e, 0x81, 0xdc, 0x60, 0x59, + 0xe8, 0x3a, 0xce, 0x93, 0x14, 0x6d, 0xcf, 0x6d, 0x94, 0x2d, 0xaf, 0x5d, 0xbc, 0x39, 0xb1, 0xd2, + 0xf4, 0x5d, 0x87, 0x79, 0xa2, 0xa2, 0xf9, 0xb9, 0x82, 0xf2, 0xe1, 0x85, 0x88, 0x63, 0x26, 0xa9, + 0xda, 0xfe, 0xdb, 0x00, 0x5b, 0x40, 0x3b, 0x70, 0x13, 0x64, 0x0d, 0xeb, 0x45, 0x8f, 0x73, 0x24, + 0x25, 0xdb, 0x5b, 0x1b, 0x7b, 0x4b, 0x63, 0x77, 0x69, 0xe6, 0xae, 0xca, 0xfc, 0x57, 0x01, 0xfe, + 0x80, 0x40, 0x60, 0x30, 0x28, 0x14, 0x1e, 0x8f, 0x48, 0x64, 0x36, 0xab, 0x56, 0xff, 0x7e, 0xc0, + 0x20, 0x50, 0x18, 0x3c, 0x0a, 0x91, 0xc7, 0x2c, 0x52, 0x9d, 0xfd, 0xa9, 0x81, 0xbe, 0xe0, 0x70, + 0x48, 0x24, 0x36, 0x9b, 0x56, 0xeb, 0x7e, 0xcf, 0x60, 0x54, 0x28, 0x3f, 0x5e, 0x90, 0x38, 0x6c, + 0x12, 0xad, 0xcd, 0xbd, 0x95, 0xb1, 0xaf, 0x34, 0x7c, 0x17, 0x61, 0xce, 0xa8, 0x54, 0x7e, 0xbf, + 0x60, 0x70, 0x28, 0x24, 0x1e, 0x9b, 0x48, 0x6b, 0x76, 0xaf, 0x66, 0xfc, 0x2a, 0xc1, 0xdf, 0x10, + 0x58, 0x0c, 0x3a, 0x85, 0xd3, 0x23, 0x1d, 0xd9, 0xc9, 0x9a, 0xd6, 0xeb, 0x1e, 0xcf, 0x48, 0x54, + 0x36, 0xbf, 0x56, 0xf0, 0x3e, 0xc4, 0x10, 0x53, 0x4c, 0x3d, 0xf5, 0xd1, 0x87, 0x1c, 0x62, 0x89, + 0xe9, 0xa6, 0xce, 0xfa, 0xd4, 0x43, 0x1f, 0x71, 0xc8, 0x24, 0x56, 0x9b, 0x7e, 0xeb, 0x60, 0x4f, + 0x68, 0x34, 0x2e, 0x97, 0x5c, 0x6e, 0xb9, 0xec, 0x72, 0xcd, 0xe5, 0x95, 0x8b, 0x2f, 0x27, 0x5c, + 0x1a, 0xb9, 0xcb, 0x32, 0xd7, 0x55, 0x9e, 0xbf, 0x28, 0x70, 0x1e, 0xa4, 0x08, 0x7b, 0x46, 0xa3, + 0x72, 0xf9, 0xe5, 0x82, 0xcb, 0x21, 0x97, 0x58, 0x6e, 0xba, 0xac, 0x73, 0x3d, 0xe5, 0xd1, 0x8b, + 0x1c, 0x67, 0x49, 0xea, 0xb6, 0xcf, 0x36, 0xd4, 0x16, 0xdf, 0x4e, 0xd8, 0x34, 0x5a, 0x97, 0x7b, + 0x2e, 0xa3, 0x5c, 0x79, 0xf9, 0xe2, 0xc2, 0xc9, 0x91, 0x96, 0xec, 0x6e, 0xcd, 0xec, 0x55, 0x8d, + 0xff, 0x25, 0x80, 0x1b, 0x20, 0x0b, 0x58, 0x07, 0x7a, 0x82, 0xa3, 0x21, 0xb9, 0xd8, 0x72, 0xda, + 0xa5, 0x9b, 0x3b, 0x2b, 0x53, 0x5f, 0x7d, 0xf8, 0x21, 0x82, 0x98, 0x61, 0xaa, 0xa8, 0x7f, 0x3e, + 0xa0, 0x10, 0x78, 0x0c, 0x22, 0x85, 0xd9, 0xa3, 0x1a, 0xf9, 0xcb, 0x02, 0xd7, 0x41, 0x9e, 0xb0, + 0x68, 0x74, 0x2e, 0xa7, 0x5c, 0x7a, 0xb9, 0xe3, 0x32, 0xc9, 0xd5, 0x96, 0xdf, 0x2e, 0xd8, 0x1c, + 0x5a, 0x89, 0xfb, 0x26, 0xc3, 0x5a, 0xd1, 0xfb, 0x1c, 0x43, 0x49, 0xf1, 0xf6, 0xc4, 0x46, 0xd3, + 0x72, 0xdd, 0xe5, 0x99}; + +void descramble_sector(uint8_t *buffer) +{ + for (uint32_t i = 12; i < CD_SECTOR_LEN; i++) + { + buffer[i] ^= s_sector_scramble[i - 12]; + } +} + +static inline uint32_t unBCD(uint32_t val) +{ + return ((val & 0xf0) >> 4) * 10 + (val & 0x0f); +} + +void check_scramble(int lba, uint8_t *buffer) +{ + // Check for sync pattern to confirm mode 2 + // Starts and ends with 0x00 and ... + if ((buffer[0] != 0) || (buffer[11] != 0)) + return; + + // ... inbetween there are 0xff bytes + for (uint32_t i = 01; i < 11; i++) + if (buffer[i] != 0xff) + return; + + // Sync pattern confirmed. check validity of mode2 header + uint32_t mm, ss, ff; + uint8_t mode; + + mm = unBCD(buffer[12]); + ss = unBCD(buffer[13]); + ff = unBCD(buffer[14]); + mode = buffer[15]; + int mode2_lba = mm * 75 * 60 + ss * 75 + ff; + + if (mode2_lba == lba && mode == 2) + { + // Is a valid header. Do nothing + } + else + { + // Can we fix it? Let's test on 4 bytes + mm = unBCD(buffer[12] ^ s_sector_scramble[0]); + ss = unBCD(buffer[13] ^ s_sector_scramble[1]); + ff = unBCD(buffer[14] ^ s_sector_scramble[2]); + mode = buffer[15] ^ s_sector_scramble[3]; + mode2_lba = mm * 75 * 60 + ss * 75 + ff; + if (mode2_lba == lba && mode == 2) + { + descramble_sector(buffer); + } + } +} + +void subcode_data(int lba, struct subcode &out) +{ + if (lba < 0) + { + // TOC is expected by the core at lba -65536 + lba += 65536; + + uint8_t am, as, af; + am = lba / (60 * 75); + int rem_lba = lba - am * (60 * 75); + as = rem_lba / 75; + af = rem_lba % 75; + + auto &toc_entry = toc_buffer[lba % toc_entry_count]; + + out.control = htons(toc_entry.control); + out.track = 0; // Track 0 for TOC + out.index = htons(toc_entry.track); + out.mode1_mins = htons(BCD(am)); + out.mode1_secs = htons(BCD(as)); + out.mode1_frac = htons(BCD(af)); + out.mode1_zero = 0; + out.mode1_amins = htons(toc_entry.m); + out.mode1_asecs = htons(toc_entry.s); + out.mode1_afrac = htons(toc_entry.f); + out.mode1_crc0 = htons(0xff); + out.mode1_crc1 = htons(0xff); + } + else + { + uint8_t am, as, af; + am = lba / (60 * 75); + int rem_lba = lba - am * (60 * 75); + as = rem_lba / 75; + af = rem_lba % 75; + + int track = toc.GetTrackByLBA(lba + 150); + + int track_lba = lba - toc.tracks[track].start; + int index = 1; + + if (track_lba < 0) + { + // Fix index 0 tracks which are defined as pause + // The timecode seems to go backwards on a real machine + track_lba = -track_lba; + index = 0; + }; + + uint8_t tm, ts, tf; + tm = track_lba / (60 * 75); + track_lba -= tm * (60 * 75); + ts = track_lba / 75; + tf = track_lba % 75; + + out.control = htons(toc.tracks[track].type ? 0x41 : 0x01); + out.track = htons(BCD(track + 1)); + out.index = htons(BCD(index)); + out.mode1_mins = htons(BCD(tm)); + out.mode1_secs = htons(BCD(ts)); + out.mode1_frac = htons(BCD(tf)); + out.mode1_zero = 0; + out.mode1_amins = htons(BCD(am)); + out.mode1_asecs = htons(BCD(as)); + out.mode1_afrac = htons(BCD(af)); + out.mode1_crc0 = htons(0xff); + out.mode1_crc1 = htons(0xff); + } + + uint16_t crc_accum = 0; + uint8_t *crc = reinterpret_cast(&out); + for (int i = 0; i < 12; i++) + crc_accum = CRC_CCITT_ROUND(crc_accum, crc[1 + i * 2]); + + out.mode1_crc0 = htons((crc_accum >> 8) & 0xff); + out.mode1_crc1 = htons(crc_accum & 0xff); +#if 0 + printf("subcode %d %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", lba, + ntohs(out.control), ntohs(out.track), ntohs(out.index), + ntohs(out.mode1_mins), ntohs(out.mode1_secs), ntohs(out.mode1_frac), ntohs(out.mode1_zero), + ntohs(out.mode1_amins), ntohs(out.mode1_asecs), ntohs(out.mode1_afrac), ntohs(out.mode1_crc0), + ntohs(out.mode1_crc1)); +#endif +} + void cdi_read_cd(uint8_t *buffer, int lba, int cnt) { - // printf("req lba=%d, cnt=%d\n", lba, cnt); + int calc_lba = lba; + uint8_t am, as, af; + am = calc_lba / (60 * 75); + calc_lba -= am * (60 * 75); + as = calc_lba / 75; + af = calc_lba % 75; + + printf("req lba=%d, cnt=%d %02d:%02d:%02d %d %d\n", lba, cnt, am, as, af, + toc.tracks[0].start, toc.tracks[0].pregap); while (cnt > 0) { - if (lba < toc.tracks[0].start || !toc.last) + if (lba < 0 || !toc.last) { memset(buffer, 0, CD_SECTOR_LEN); } @@ -371,36 +729,26 @@ void cdi_read_cd(uint8_t *buffer, int lba, int cnt) for (int i = 0; i < toc.last; i++) { - if (lba >= toc.tracks[i].start && lba <= toc.tracks[i].end) + if (lba >= (toc.tracks[i].start - toc.tracks[i].pregap) && lba <= toc.tracks[i].end) { if (!toc.chd_f) { if (toc.tracks[i].offset) { - FileSeek(&toc.tracks[0].f, toc.tracks[i].offset + ((lba - toc.tracks[i].start) * CD_SECTOR_LEN), SEEK_SET); + FileSeek(&toc.tracks[0].f, toc.tracks[i].offset + ((lba - toc.tracks[i].start + toc.tracks[i].pregap) * CD_SECTOR_LEN), SEEK_SET); } else { - FileSeek(&toc.tracks[i].f, (lba - toc.tracks[i].start) * CD_SECTOR_LEN, SEEK_SET); + FileSeek(&toc.tracks[i].f, (lba - toc.tracks[i].start + toc.tracks[i].pregap) * CD_SECTOR_LEN, SEEK_SET); } } + while (cnt) { - if (toc.tracks[i + 1].pregap && lba > (toc.tracks[i + 1].start - toc.tracks[i + 1].indexes[1])) + if (toc.chd_f) { - // The TOC is setup so that pregap sectors are actually part of the - // PREVIOUS track. If the pregap field is set the file doesn't contain - // this data, so we have to fake it. - // Check the next track's pregap and indexes[1] values to determine - // if we're reading pregap sectors - - memset(buffer, 0x0, CD_SECTOR_LEN); - } - else if (toc.chd_f) - { - // The "fake" 150 sector pregap moves all the LBAs up by 150, so adjust here to read where the core actually wants data from - int read_lba = lba - toc.tracks[0].indexes[1]; + int read_lba = lba - 150; if (mister_chd_read_sector(toc.chd_f, (read_lba + toc.tracks[i].offset), 0, 0, CD_SECTOR_LEN, buffer, chd_hunkbuf, &chd_hunknum) == CHDERR_NONE) { if (!toc.tracks[i].type) // CHD requires byteswap of audio data @@ -427,7 +775,11 @@ void cdi_read_cd(uint8_t *buffer, int lba, int cnt) } if ((lba + 1) > toc.tracks[i].end) break; + + check_scramble(lba, buffer); buffer += CD_SECTOR_LEN; + subcode_data(lba, *reinterpret_cast(buffer)); + buffer += sizeof(struct subcode); cnt--; lba++; } @@ -436,7 +788,10 @@ void cdi_read_cd(uint8_t *buffer, int lba, int cnt) } } + check_scramble(lba, buffer); buffer += CD_SECTOR_LEN; + subcode_data(lba, *reinterpret_cast(buffer)); + buffer += sizeof(struct subcode); cnt--; lba++; } @@ -461,6 +816,7 @@ void cdi_mount_cd(int s_index, const char *filename) if (load_cd_image(filename, &toc) && toc.last) { cdi_mount_save(filename); + prepare_toc_buffer(&toc); user_io_set_index(0); mount_cd(toc.end * CD_SECTOR_LEN, s_index); loaded = 1; diff --git a/user_io.cpp b/user_io.cpp index e7c5416..3224860 100644 --- a/user_io.cpp +++ b/user_io.cpp @@ -3024,8 +3024,10 @@ void user_io_poll() lba = spi_w(0); lba = (lba & 0xFFFF) | (((uint32_t)spi_w(0)) << 16); blks = ((c >> 9) & 0x3F) + 1; - if ((disk == 0 && is_cdi()) || (disk == 1 && is_psx())) + if (disk == 1 && is_psx()) blksz = 2352; + else if (disk == 0 && is_cdi()) + blksz = (2352 + 24); else blksz = 128 << ((c >> 6) & 7); @@ -3156,7 +3158,7 @@ void user_io_poll() unsigned int psx_blksz = psx_chd_hunksize(); if (psx_blksz && psx_blksz <= sizeof(buffer[0])) buf_n = psx_blksz / blksz; } - else if (is_cdi() && blksz == 2352) + else if (is_cdi() && blksz == (2352 + 24)) { //returns 0 if the mounted disk is not a chd, otherwise returns the chd hunksize in bytes unsigned int psx_blksz = cdi_chd_hunksize(); @@ -3177,7 +3179,7 @@ void user_io_poll() done = 1; buffer_lba[disk] = lba; } - else if (blksz == 2352 && is_cdi()) + else if (blksz == (2352 + 24) && is_cdi()) { diskled_on(); cdi_read_cd(buffer[disk], lba, buf_n); @@ -3261,7 +3263,7 @@ void user_io_poll() psx_read_cd(buffer[disk], lba, buf_n); buffer_lba[disk] = lba; } - else if (blksz == 2352 && is_cdi()) + else if (blksz == (2352 + 24) && is_cdi()) { cdi_read_cd(buffer[disk], lba, buf_n); buffer_lba[disk] = lba;