Mercurial > repos > blastem
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++; |