# HG changeset patch # User Michael Pavone # Date 1696228788 25200 # Node ID 9f0c67e5c50ab617f890d31158502283cb3e2333 # Parent e81c6a44274cf2c3eac665dffbf016c4b538621b Implement CD-ROM data sector scrambling/descrambling diff -r e81c6a44274c -r 9f0c67e5c50a cdimage.c --- a/cdimage.c Sun Sep 17 23:03:28 2023 -0700 +++ b/cdimage.c Sun Oct 01 23:39:48 2023 -0700 @@ -6,6 +6,16 @@ #include "util.h" #include "wave.h" +uint8_t cdrom_scramble(uint16_t *lsfr, uint8_t data) +{ + data ^= *lsfr; + uint16_t new_bit = *lsfr; + *lsfr >>= 1; + new_bit = (new_bit ^ *lsfr) & 1; + *lsfr |= new_bit << 14; + return data; +} + static char* cmd_start(char *cur) { while (*cur && isblank(*cur)) @@ -127,6 +137,9 @@ fseek(media->tracks[track].f, media->tracks[track].file_offset + lba * media->tracks[track].sector_bytes, SEEK_SET); } } + if (media->tracks[track].type == TRACK_DATA) { + media->cdrom_scramble_lsfr = 1; + } } return track; } @@ -154,32 +167,38 @@ static uint8_t bin_read(system_media *media, uint32_t offset) { + uint8_t retval; if (media->in_fake_pregap == FAKE_DATA) { - return fake_read(media->cur_sector, offset); + retval = fake_read(media->cur_sector, offset); } else if (media->in_fake_pregap == FAKE_AUDIO) { - return 0; + retval = 0; } else if ((media->tracks[media->cur_track].sector_bytes < 2352 && offset < 16) || offset > (media->tracks[media->cur_track].sector_bytes + 16)) { - return fake_read(media->cur_sector, offset); + retval = fake_read(media->cur_sector, offset); } else if (media->tracks[media->cur_track].flac) { if (offset & 3) { - return media->byte_storage[(offset & 3) - 1]; + retval = media->byte_storage[(offset & 3) - 1]; } else { int16_t samples[2]; flac_get_sample(media->tracks[media->cur_track].flac, samples, 2); media->byte_storage[0] = samples[0] >> 8; media->byte_storage[1] = samples[1]; media->byte_storage[2] = samples[1] >> 8; - return samples[0]; + retval = samples[0]; } } else { if (media->tracks[media->cur_track].need_swap) { if (offset & 1) { - return media->byte_storage[0]; + retval = media->byte_storage[0]; } media->byte_storage[0] = fgetc(media->tracks[media->cur_track].f); + } else { + retval = fgetc(media->tracks[media->cur_track].f); } - return fgetc(media->tracks[media->cur_track].f); } + if (offset >= 12 && media->tracks[media->cur_track].type == TRACK_DATA) { + retval = cdrom_scramble(&media->cdrom_scramble_lsfr, retval); + } + return retval; } static uint8_t bin_subcode_read(system_media *media, uint32_t offset) diff -r e81c6a44274c -r 9f0c67e5c50a cdimage.h --- a/cdimage.h Sun Sep 17 23:03:28 2023 -0700 +++ b/cdimage.h Sun Oct 01 23:39:48 2023 -0700 @@ -6,5 +6,6 @@ uint32_t make_iso_media(system_media *media, const char *filename); void cdimage_serialize(system_media *media, serialize_buffer *buf); void cdimage_deserialize(deserialize_buffer *buf, void *vmedia); +uint8_t cdrom_scramble(uint16_t *lsfr, uint8_t data); #endif //CUE_H_ diff -r e81c6a44274c -r 9f0c67e5c50a lc8951.c --- a/lc8951.c Sun Sep 17 23:03:28 2023 -0700 +++ b/lc8951.c Sun Oct 01 23:39:48 2023 -0700 @@ -1,5 +1,6 @@ #include "lc8951.h" #include "backend.h" +#include "cdimage.h" enum { COMIN, @@ -62,6 +63,7 @@ //CTRL1 #define BIT_SYIEN 0x80 #define BIT_SYDEN 0x40 +#define BIT_DSCREN 0x20 //STAT0 #define BIT_CRCOK 0x80 @@ -315,11 +317,7 @@ uint8_t sync_detected = 0, sync_ignored = 0; if (byte == 0) { - // HACK!: The (sector_offset < 0x10) check is not correct, but without it Thunderhawk gets stuck - // It has a sector that contains the sync pattern in the main data area - // From the LC8951 datasheet, I would expect tohis to trigger a short block, but either - // it's sync detection is fancier than I thought or I have a bug that is confusing the BIOS - if (context->sync_counter == 11 && ((sector_offset & 3) == 3) && (sector_offset < 0x10)) { + if (context->sync_counter == 11) { if (context->ctrl1 & BIT_SYDEN) { sync_detected = 1; } else { @@ -335,6 +333,11 @@ context->sync_counter = 0; } + //TODO: figure out if chip tries to avoid descrambling sync signal + if (context->ctrl1 & BIT_DSCREN) { + byte = cdrom_scramble(&context->scrambler_lsfr, byte); + } + uint8_t sync_inserted = 0; if (context->ctrl1 & BIT_SYIEN && context->sector_counter == 2351) { sync_inserted = 1; @@ -359,6 +362,7 @@ context->regs[STAT0] |= BIT_ILSYNC; } context->sector_counter = 0; + context->scrambler_lsfr = 1; //header/status regs no longer considered "valid" context->regs[STAT3] |= BIT_VALST; @@ -373,7 +377,7 @@ context->regs[PTL] = block_start; context->regs[PTH] = block_start >> 8; } - printf("Decoding block starting at %X (WRRQ: %d)\n", context->regs[PTL] | (context->regs[PTH] << 8), !!(context->ctrl0 & BIT_WRRQ)); + printf("Decoding block starting at %X (WRRQ: %d, sector_offset: %X)\n", context->regs[PTL] | (context->regs[PTH] << 8), !!(context->ctrl0 & BIT_WRRQ), sector_offset); //Based on measurements of a Wondermega M1 (LC8951) with SYDEN, SYIEN and DECEN only context->decode_end = context->cycle + 22030 * context->clock_step; } diff -r e81c6a44274c -r 9f0c67e5c50a lc8951.h --- a/lc8951.h Sun Sep 17 23:03:28 2023 -0700 +++ b/lc8951.h Sun Oct 01 23:39:48 2023 -0700 @@ -23,6 +23,7 @@ uint8_t comin[8]; uint16_t dac; + uint16_t scrambler_lsfr; uint8_t comin_write; uint8_t comin_count; uint8_t ifctrl; diff -r e81c6a44274c -r 9f0c67e5c50a system.h --- a/system.h Sun Sep 17 23:03:28 2023 -0700 +++ b/system.h Sun Oct 01 23:39:48 2023 -0700 @@ -142,6 +142,7 @@ uint32_t cur_track; uint32_t size; uint32_t cur_sector; + uint16_t cdrom_scramble_lsfr; media_type type; uint8_t in_fake_pregap; uint8_t byte_storage[3];