comparison lc8951.c @ 2342:9f0c67e5c50a

Implement CD-ROM data sector scrambling/descrambling
author Michael Pavone <pavone@retrodev.com>
date Sun, 01 Oct 2023 23:39:48 -0700
parents 9ead0fe69d9b
children f8b5142c06aa
comparison
equal deleted inserted replaced
2341:e81c6a44274c 2342:9f0c67e5c50a
1 #include "lc8951.h" 1 #include "lc8951.h"
2 #include "backend.h" 2 #include "backend.h"
3 #include "cdimage.h"
3 4
4 enum { 5 enum {
5 COMIN, 6 COMIN,
6 IFSTAT, 7 IFSTAT,
7 DBCL, 8 DBCL,
60 #define BIT_PRQ 0x01 61 #define BIT_PRQ 0x01
61 62
62 //CTRL1 63 //CTRL1
63 #define BIT_SYIEN 0x80 64 #define BIT_SYIEN 0x80
64 #define BIT_SYDEN 0x40 65 #define BIT_SYDEN 0x40
66 #define BIT_DSCREN 0x20
65 67
66 //STAT0 68 //STAT0
67 #define BIT_CRCOK 0x80 69 #define BIT_CRCOK 0x80
68 #define BIT_ILSYNC 0x40 70 #define BIT_ILSYNC 0x40
69 #define BIT_NOSYNC 0x20 71 #define BIT_NOSYNC 0x20
313 lc8951_run(context, cycle); 315 lc8951_run(context, cycle);
314 uint16_t current_write_addr = context->regs[WAL] | (context->regs[WAH] << 8); 316 uint16_t current_write_addr = context->regs[WAL] | (context->regs[WAH] << 8);
315 317
316 uint8_t sync_detected = 0, sync_ignored = 0; 318 uint8_t sync_detected = 0, sync_ignored = 0;
317 if (byte == 0) { 319 if (byte == 0) {
318 // HACK!: The (sector_offset < 0x10) check is not correct, but without it Thunderhawk gets stuck 320 if (context->sync_counter == 11) {
319 // It has a sector that contains the sync pattern in the main data area
320 // From the LC8951 datasheet, I would expect tohis to trigger a short block, but either
321 // it's sync detection is fancier than I thought or I have a bug that is confusing the BIOS
322 if (context->sync_counter == 11 && ((sector_offset & 3) == 3) && (sector_offset < 0x10)) {
323 if (context->ctrl1 & BIT_SYDEN) { 321 if (context->ctrl1 & BIT_SYDEN) {
324 sync_detected = 1; 322 sync_detected = 1;
325 } else { 323 } else {
326 sync_ignored = 1; 324 sync_ignored = 1;
327 } 325 }
333 context->sync_counter++; 331 context->sync_counter++;
334 } else { 332 } else {
335 context->sync_counter = 0; 333 context->sync_counter = 0;
336 } 334 }
337 335
336 //TODO: figure out if chip tries to avoid descrambling sync signal
337 if (context->ctrl1 & BIT_DSCREN) {
338 byte = cdrom_scramble(&context->scrambler_lsfr, byte);
339 }
340
338 uint8_t sync_inserted = 0; 341 uint8_t sync_inserted = 0;
339 if (context->ctrl1 & BIT_SYIEN && context->sector_counter == 2351) { 342 if (context->ctrl1 & BIT_SYIEN && context->sector_counter == 2351) {
340 sync_inserted = 1; 343 sync_inserted = 1;
341 } 344 }
342 345
357 } 360 }
358 if (sync_detected && context->sector_counter != 2351) { 361 if (sync_detected && context->sector_counter != 2351) {
359 context->regs[STAT0] |= BIT_ILSYNC; 362 context->regs[STAT0] |= BIT_ILSYNC;
360 } 363 }
361 context->sector_counter = 0; 364 context->sector_counter = 0;
365 context->scrambler_lsfr = 1;
362 366
363 //header/status regs no longer considered "valid" 367 //header/status regs no longer considered "valid"
364 context->regs[STAT3] |= BIT_VALST; 368 context->regs[STAT3] |= BIT_VALST;
365 //!DECI is set inactive at the same time as !VALST 369 //!DECI is set inactive at the same time as !VALST
366 context->regs[IFSTAT] |= BIT_DECI; 370 context->regs[IFSTAT] |= BIT_DECI;
371 if (context->ctrl0 & BIT_WRRQ) { 375 if (context->ctrl0 & BIT_WRRQ) {
372 uint16_t block_start = current_write_addr + 1 - 2352; 376 uint16_t block_start = current_write_addr + 1 - 2352;
373 context->regs[PTL] = block_start; 377 context->regs[PTL] = block_start;
374 context->regs[PTH] = block_start >> 8; 378 context->regs[PTH] = block_start >> 8;
375 } 379 }
376 printf("Decoding block starting at %X (WRRQ: %d)\n", context->regs[PTL] | (context->regs[PTH] << 8), !!(context->ctrl0 & BIT_WRRQ)); 380 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);
377 //Based on measurements of a Wondermega M1 (LC8951) with SYDEN, SYIEN and DECEN only 381 //Based on measurements of a Wondermega M1 (LC8951) with SYDEN, SYIEN and DECEN only
378 context->decode_end = context->cycle + 22030 * context->clock_step; 382 context->decode_end = context->cycle + 22030 * context->clock_step;
379 } 383 }
380 } else { 384 } else {
381 context->sector_counter++; 385 context->sector_counter++;