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