comparison lc8951.c @ 2142:d9151d0894c7

Fix some CD-ROM emulation issues
author Michael Pavone <pavone@retrodev.com>
date Thu, 24 Mar 2022 23:43:43 -0700
parents d90d92ce5cab
children 10e4439d8f13
comparison
equal deleted inserted replaced
2141:793715149f16 2142:d9151d0894c7
54 #define BIT_STEN 0x01 54 #define BIT_STEN 0x01
55 55
56 //CTRL0 56 //CTRL0
57 #define BIT_DECEN 0x80 57 #define BIT_DECEN 0x80
58 #define BIT_WRRQ 0x04 58 #define BIT_WRRQ 0x04
59 #define BIT_ORQ 0x02
60 #define BIT_PRQ 0x01
59 61
60 //CTRL1 62 //CTRL1
61 #define BIT_SYIEN 0x80 63 #define BIT_SYIEN 0x80
62 #define BIT_SYDEN 0x40 64 #define BIT_SYDEN 0x40
63 65
65 #define BIT_CRCOK 0x80 67 #define BIT_CRCOK 0x80
66 #define BIT_ILSYNC 0x40 68 #define BIT_ILSYNC 0x40
67 #define BIT_NOSYNC 0x20 69 #define BIT_NOSYNC 0x20
68 #define BIT_LBLK 0x10 70 #define BIT_LBLK 0x10
69 #define BIT_SBLK 0x04 71 #define BIT_SBLK 0x04
70 72 #define BIT_UCEBLK 0x01
71 73
72 //STAT3 74 //STAT3
73 #define BIT_VALST 0x80 75 #define BIT_VALST 0x80
76 #define BIT_WLONG 0x40
74 77
75 //datasheet timing info 78 //datasheet timing info
76 //3 cycles for memory operation 79 //3 cycles for memory operation
77 //6 cycles min for DMA-mode host transfer 80 //6 cycles min for DMA-mode host transfer
78 81
225 context->regs[reg] =context->buffer[block_start++]; 228 context->regs[reg] =context->buffer[block_start++];
226 block_start &= (sizeof(context->buffer)-1); 229 block_start &= (sizeof(context->buffer)-1);
227 } 230 }
228 } 231 }
229 printf("Decode done %X:%X:%X mode %X\n", context->regs[HEAD0], context->regs[HEAD1], context->regs[HEAD2], context->regs[HEAD3]); 232 printf("Decode done %X:%X:%X mode %X\n", context->regs[HEAD0], context->regs[HEAD1], context->regs[HEAD2], context->regs[HEAD3]);
230 context->regs[STAT0] |= BIT_CRCOK; 233 // This check is a hack until I properly implement error detection
234 if (context->regs[HEAD0] < 0x74 && (context->regs[HEAD0] & 0xF) < 0xA
235 && context->regs[HEAD1] < 0x60 && (context->regs[HEAD1] & 0xF) < 0xA
236 && context->regs[HEAD2] < 0x75 && (context->regs[HEAD2] & 0xF) < 0xA
237 && context->regs[HEAD3] < 3 && !(context->regs[STAT0] & (BIT_NOSYNC|BIT_ILSYNC))
238 ) {
239
240 if (context->ctrl0 & (BIT_ORQ|BIT_PRQ)) {
241 context->regs[STAT0] |= BIT_CRCOK;
242 }
243 context->regs[STAT1] = 0;
244 context->regs[STAT2] = 0x90;
245 } else {
246 if (context->ctrl0 & (BIT_ORQ|BIT_PRQ)) {
247 context->regs[STAT0] |= BIT_UCEBLK;
248 }
249 context->regs[STAT1] = 0xFF;
250 context->regs[STAT2] = 0xF2;
251 }
252 context->regs[STAT3] |= BIT_WLONG;
231 } 253 }
232 if (context->transfer_end != CYCLE_NEVER) { 254 if (context->transfer_end != CYCLE_NEVER) {
233 if (context->byte_handler(context->handler_data, context->buffer[context->dac & (sizeof(context->buffer)-1)])) { 255 if (context->byte_handler(context->handler_data, context->buffer[context->dac & (sizeof(context->buffer)-1)])) {
234 context->dac++; 256 context->dac++;
235 context->regs[DBCL]--; 257 context->regs[DBCL]--;
273 void lc8951_write_byte(lc8951 *context, uint32_t cycle, int sector_offset, uint8_t byte) 295 void lc8951_write_byte(lc8951 *context, uint32_t cycle, int sector_offset, uint8_t byte)
274 { 296 {
275 lc8951_run(context, cycle); 297 lc8951_run(context, cycle);
276 uint16_t current_write_addr = context->regs[WAL] | (context->regs[WAH] << 8); 298 uint16_t current_write_addr = context->regs[WAL] | (context->regs[WAH] << 8);
277 299
278 context->sector_counter++;
279 context->sector_counter &= 0xFFF;
280 uint8_t sync_detected = 0, sync_ignored = 0; 300 uint8_t sync_detected = 0, sync_ignored = 0;
281 if (byte == 0) { 301 if (byte == 0) {
282 if (context->sync_counter == 11 && ((sector_offset & 3) == 3)) { 302 if (context->sync_counter == 11 && ((sector_offset & 3) == 3)) {
283 if (context->ctrl1 & BIT_SYDEN) { 303 if (context->ctrl1 & BIT_SYDEN) {
284 sync_detected = 1; 304 sync_detected = 1;
294 } else { 314 } else {
295 context->sync_counter = 0; 315 context->sync_counter = 0;
296 } 316 }
297 317
298 uint8_t sync_inserted = 0; 318 uint8_t sync_inserted = 0;
299 if (context->ctrl1 & BIT_SYIEN && context->sector_counter == 2352) { 319 if (context->ctrl1 & BIT_SYIEN && context->sector_counter == 2351) {
300 sync_inserted = 1; 320 sync_inserted = 1;
321 }
322
323
324 if (context->sector_counter < 4) {
325 //TODO: Handle SHDREN = 1
326 if ((context->ctrl0 & (BIT_DECEN|BIT_WRRQ)) == (BIT_DECEN)) {
327 //monitor only mode
328 context->regs[HEAD0 + context->sector_counter] = byte;
329 }
301 } 330 }
302 331
303 if (sync_detected || sync_inserted) { 332 if (sync_detected || sync_inserted) {
304 //we've recevied the sync pattern for the next block 333 //we've recevied the sync pattern for the next block
305 context->regs[STAT0] &= ~(BIT_ILSYNC | BIT_NOSYNC | BIT_LBLK | BIT_SBLK); 334 context->regs[STAT0] &= ~(BIT_ILSYNC | BIT_NOSYNC | BIT_LBLK | BIT_SBLK);
306 if (sync_inserted && !(sync_detected || sync_ignored)) { 335 if (sync_inserted && !(sync_detected || sync_ignored)) {
307 context->regs[STAT0] |= BIT_NOSYNC; 336 context->regs[STAT0] |= BIT_NOSYNC;
308 } 337 }
309 if (sync_detected && context->sector_counter != 2352) { 338 if (sync_detected && context->sector_counter != 2351) {
310 context->regs[STAT0] |= BIT_ILSYNC; 339 context->regs[STAT0] |= BIT_ILSYNC;
311 } 340 }
312 context->sector_counter = 0; 341 context->sector_counter = 0;
313 342
314 //header/status regs no longer considered "valid" 343 //header/status regs no longer considered "valid"
315 context->regs[STAT3] |= BIT_VALST; 344 context->regs[STAT3] |= BIT_VALST;
316 //!DECI is set inactive at the same time as !VALST 345 //!DECI is set inactive at the same time as !VALST
317 context->regs[IFSTAT] |= BIT_DECI; 346 context->regs[IFSTAT] |= BIT_DECI;
347 //clear error detection status bits
348 context->regs[STAT0] &= ~(BIT_CRCOK|BIT_UCEBLK);
349 context->regs[STAT3] &= ~BIT_WLONG;
318 if (context->ctrl0 & BIT_DECEN) { 350 if (context->ctrl0 & BIT_DECEN) {
319 if (context->ctrl0 & BIT_WRRQ) { 351 if (context->ctrl0 & BIT_WRRQ) {
320 uint16_t block_start = current_write_addr + 1 - 2352; 352 uint16_t block_start = current_write_addr + 1 - 2352;
321 context->regs[PTL] = block_start; 353 context->regs[PTL] = block_start;
322 context->regs[PTH] = block_start >> 8; 354 context->regs[PTH] = block_start >> 8;
324 printf("Decoding block starting at %X (WRRQ: %d)\n", context->regs[PTL] | (context->regs[PTH] << 8), !!(context->ctrl0 & BIT_WRRQ)); 356 printf("Decoding block starting at %X (WRRQ: %d)\n", context->regs[PTL] | (context->regs[PTH] << 8), !!(context->ctrl0 & BIT_WRRQ));
325 //Based on measurements of a Wondermega M1 (LC8951) with SYDEN, SYIEN and DECEN only 357 //Based on measurements of a Wondermega M1 (LC8951) with SYDEN, SYIEN and DECEN only
326 context->decode_end = context->cycle + 22030 * context->clock_step; 358 context->decode_end = context->cycle + 22030 * context->clock_step;
327 } 359 }
328 } else { 360 } else {
361 context->sector_counter++;
362 context->sector_counter &= 0xFFF;
329 if (sync_ignored) { 363 if (sync_ignored) {
330 context->regs[STAT0] |= BIT_SBLK; 364 context->regs[STAT0] |= BIT_SBLK;
331 } 365 }
332 if (context->sector_counter == 2352) { 366 if (context->sector_counter == 2352) {
333 context->regs[STAT0] |= BIT_LBLK; 367 context->regs[STAT0] |= BIT_LBLK;
334 }
335 }
336 if (context->sector_counter < 4) {
337 //TODO: Handle SHDREN = 1
338 if ((context->ctrl0 & (BIT_DECEN|BIT_WRRQ)) == (BIT_DECEN)) {
339 //monitor only mode
340 context->regs[HEAD0 + sector_offset - 12] = byte;
341 } 368 }
342 } 369 }
343 if ((context->ctrl0 & (BIT_DECEN|BIT_WRRQ)) == (BIT_DECEN|BIT_WRRQ)) { 370 if ((context->ctrl0 & (BIT_DECEN|BIT_WRRQ)) == (BIT_DECEN|BIT_WRRQ)) {
344 context->buffer[current_write_addr & (sizeof(context->buffer)-1)] = byte; 371 context->buffer[current_write_addr & (sizeof(context->buffer)-1)] = byte;
345 context->regs[WAL]++; 372 context->regs[WAL]++;