Mercurial > repos > blastem
comparison segacd.c @ 2062:07ed42bd7b4c segacd
Some progress on CDC and CDD emulation. Now passes first 3 "CDC INIT" tests in mcd-verificator
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 28 Jan 2022 00:50:17 -0800 |
parents | 7c1760b5b3e5 |
children | 02a9846668d1 |
comparison
equal
deleted
inserted
replaced
2061:7c1760b5b3e5 | 2062:07ed42bd7b4c |
---|---|
290 cd->timer_pending = 1; | 290 cd->timer_pending = 1; |
291 } | 291 } |
292 } | 292 } |
293 } | 293 } |
294 | 294 |
295 static void cdd_run(segacd_context *cd, uint32_t cycle) | |
296 { | |
297 cdd_mcu_run(&cd->cdd, cycle, cd->gate_array + GA_CDD_CTRL, &cd->cdc); | |
298 lc8951_run(&cd->cdc, cycle); | |
299 } | |
300 | |
295 static uint32_t next_timer_int(segacd_context *cd) | 301 static uint32_t next_timer_int(segacd_context *cd) |
296 { | 302 { |
297 if (cd->timer_pending) { | 303 if (cd->timer_pending) { |
298 return cd->stopwatch_cycle; | 304 return cd->stopwatch_cycle; |
299 } | 305 } |
309 static void calculate_target_cycle(m68k_context * context) | 315 static void calculate_target_cycle(m68k_context * context) |
310 { | 316 { |
311 segacd_context *cd = context->system; | 317 segacd_context *cd = context->system; |
312 context->int_cycle = CYCLE_NEVER; | 318 context->int_cycle = CYCLE_NEVER; |
313 uint8_t mask = context->status & 0x7; | 319 uint8_t mask = context->status & 0x7; |
314 if (mask < 4) { | 320 if (mask < 5) { |
315 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN4) { | 321 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN5) { |
316 uint32_t cdd_cycle = cd->cdd.int_pending ? context->current_cycle : cd->cdd.next_int_cycle; | 322 uint32_t cdc_cycle = lc8951_next_interrupt(&cd->cdc); |
317 if (cdd_cycle < context->int_cycle) { | 323 if (cdc_cycle < context->int_cycle) { |
318 context->int_cycle = cdd_cycle; | 324 context->int_cycle = cdc_cycle; |
319 context->int_num = 4; | 325 context->int_num = 5; |
320 } | 326 } |
321 } | 327 } |
322 if (mask < 3) { | 328 if (mask < 4) { |
323 uint32_t next_timer; | 329 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN4) { |
324 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN3) { | 330 uint32_t cdd_cycle = cd->cdd.int_pending ? context->current_cycle : cd->cdd.next_int_cycle; |
325 uint32_t next_timer_cycle = next_timer_int(cd); | 331 if (cdd_cycle < context->int_cycle) { |
326 if (next_timer_cycle < context->int_cycle) { | 332 context->int_cycle = cdd_cycle; |
327 context->int_cycle = next_timer_cycle; | 333 context->int_num = 4; |
328 context->int_num = 3; | |
329 } | 334 } |
330 } | 335 } |
331 if (mask < 2) { | 336 if (mask < 3) { |
332 if (cd->int2_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN2)) { | 337 uint32_t next_timer; |
333 context->int_cycle = cd->int2_cycle; | 338 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN3) { |
334 context->int_num = 2; | 339 uint32_t next_timer_cycle = next_timer_int(cd); |
340 if (next_timer_cycle < context->int_cycle) { | |
341 context->int_cycle = next_timer_cycle; | |
342 context->int_num = 3; | |
343 } | |
344 } | |
345 if (mask < 2) { | |
346 if (cd->int2_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN2)) { | |
347 context->int_cycle = cd->int2_cycle; | |
348 context->int_num = 2; | |
349 } | |
335 } | 350 } |
336 } | 351 } |
337 } | 352 } |
338 } | 353 } |
339 if (context->int_cycle > context->current_cycle && context->int_pending == INT_PENDING_SR_CHANGE) { | 354 if (context->int_cycle > context->current_cycle && context->int_pending == INT_PENDING_SR_CHANGE) { |
368 case GA_MEM_MODE: | 383 case GA_MEM_MODE: |
369 return cd->gate_array[reg] & 0xFF1F; | 384 return cd->gate_array[reg] & 0xFF1F; |
370 case GA_CDC_CTRL: | 385 case GA_CDC_CTRL: |
371 return cd->gate_array[reg] | cd->cdc.ar; | 386 return cd->gate_array[reg] | cd->cdc.ar; |
372 case GA_CDC_REG_DATA: | 387 case GA_CDC_REG_DATA: |
388 cdd_run(cd, m68k->current_cycle); | |
373 return lc8951_reg_read(&cd->cdc); | 389 return lc8951_reg_read(&cd->cdc); |
374 case GA_STOP_WATCH: | 390 case GA_STOP_WATCH: |
375 case GA_TIMER: | 391 case GA_TIMER: |
376 timers_run(cd, m68k->current_cycle); | 392 timers_run(cd, m68k->current_cycle); |
377 return cd->gate_array[reg]; | 393 return cd->gate_array[reg]; |
378 case GA_CDD_STATUS0: | 394 case GA_CDD_STATUS0: |
379 case GA_CDD_STATUS1: | 395 case GA_CDD_STATUS1: |
380 case GA_CDD_STATUS2: | 396 case GA_CDD_STATUS2: |
381 case GA_CDD_STATUS3: | 397 case GA_CDD_STATUS3: |
382 case GA_CDD_STATUS4: | 398 case GA_CDD_STATUS4: |
383 cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL); | 399 cdd_run(cd, m68k->current_cycle); |
384 return cd->gate_array[reg]; | 400 return cd->gate_array[reg]; |
385 break; | 401 break; |
386 case GA_FONT_DATA0: | 402 case GA_FONT_DATA0: |
387 case GA_FONT_DATA1: | 403 case GA_FONT_DATA1: |
388 case GA_FONT_DATA2: | 404 case GA_FONT_DATA2: |
480 cd->gate_array[reg] &= 0xFFC2; | 496 cd->gate_array[reg] &= 0xFFC2; |
481 cd->gate_array[reg] |= value & (BIT_RET|BIT_MEM_MODE|MASK_PRIORITY); | 497 cd->gate_array[reg] |= value & (BIT_RET|BIT_MEM_MODE|MASK_PRIORITY); |
482 break; | 498 break; |
483 } | 499 } |
484 case GA_CDC_CTRL: | 500 case GA_CDC_CTRL: |
501 cdd_run(cd, m68k->current_cycle); | |
485 lc8951_ar_write(&cd->cdc, value); | 502 lc8951_ar_write(&cd->cdc, value); |
486 cd->gate_array[reg] &= 0xC000; | 503 cd->gate_array[reg] &= 0xC000; |
487 cd->gate_array[reg] = value & 0x0700; | 504 cd->gate_array[reg] = value & 0x0700; |
488 break; | 505 break; |
489 case GA_CDC_REG_DATA: | 506 case GA_CDC_REG_DATA: |
507 cdd_run(cd, m68k->current_cycle); | |
490 lc8951_reg_write(&cd->cdc, value); | 508 lc8951_reg_write(&cd->cdc, value); |
509 calculate_target_cycle(m68k); | |
491 break; | 510 break; |
492 case GA_STOP_WATCH: | 511 case GA_STOP_WATCH: |
493 //docs say you should only write zero to reset | 512 //docs say you should only write zero to reset |
494 //mcd-verificator comments suggest any value will reset | 513 //mcd-verificator comments suggest any value will reset |
495 timers_run(cd, m68k->current_cycle); | 514 timers_run(cd, m68k->current_cycle); |
518 case GA_INT_MASK: | 537 case GA_INT_MASK: |
519 cd->gate_array[reg] = value & (BIT_MASK_IEN6|BIT_MASK_IEN5|BIT_MASK_IEN4|BIT_MASK_IEN3|BIT_MASK_IEN2|BIT_MASK_IEN1); | 538 cd->gate_array[reg] = value & (BIT_MASK_IEN6|BIT_MASK_IEN5|BIT_MASK_IEN4|BIT_MASK_IEN3|BIT_MASK_IEN2|BIT_MASK_IEN1); |
520 calculate_target_cycle(m68k); | 539 calculate_target_cycle(m68k); |
521 break; | 540 break; |
522 case GA_CDD_CTRL: { | 541 case GA_CDD_CTRL: { |
523 cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL); | 542 cdd_run(cd, m68k->current_cycle); |
524 uint16_t changed = cd->gate_array[reg] ^ value; | 543 uint16_t changed = cd->gate_array[reg] ^ value; |
525 cd->gate_array[reg] &= ~BIT_HOCK; | 544 cd->gate_array[reg] &= ~BIT_HOCK; |
526 cd->gate_array[reg] |= value & BIT_HOCK; | 545 cd->gate_array[reg] |= value & BIT_HOCK; |
527 if (changed & BIT_HOCK) { | 546 if (changed & BIT_HOCK) { |
528 if (value & BIT_HOCK) { | 547 if (value & BIT_HOCK) { |
536 } | 555 } |
537 case GA_CDD_CMD0: | 556 case GA_CDD_CMD0: |
538 case GA_CDD_CMD1: | 557 case GA_CDD_CMD1: |
539 case GA_CDD_CMD2: | 558 case GA_CDD_CMD2: |
540 case GA_CDD_CMD3: | 559 case GA_CDD_CMD3: |
541 cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL); | 560 cdd_run(cd, m68k->current_cycle); |
542 cd->gate_array[reg] = value & 0x0F0F; | 561 cd->gate_array[reg] = value & 0x0F0F; |
543 break; | 562 break; |
544 case GA_CDD_CMD4: | 563 case GA_CDD_CMD4: |
545 cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL); | 564 cdd_run(cd, m68k->current_cycle); |
546 cd->gate_array[reg] = value & 0x0F0F; | 565 cd->gate_array[reg] = value & 0x0F0F; |
547 cdd_mcu_start_cmd_recv(&cd->cdd, cd->gate_array + GA_CDD_CTRL); | 566 cdd_mcu_start_cmd_recv(&cd->cdd, cd->gate_array + GA_CDD_CTRL); |
548 break; | 567 break; |
549 case GA_FONT_COLOR: | 568 case GA_FONT_COLOR: |
550 cd->gate_array[reg] = value & 0xFF; | 569 cd->gate_array[reg] = value & 0xFF; |
584 } | 603 } |
585 return vcontext; | 604 return vcontext; |
586 case GA_CDD_CMD4: | 605 case GA_CDD_CMD4: |
587 if (!address) { | 606 if (!address) { |
588 //byte write to $FF804A should not trigger transfer | 607 //byte write to $FF804A should not trigger transfer |
589 cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL); | 608 cdd_run(cd, m68k->current_cycle); |
590 cd->gate_array[reg] &= 0x0F; | 609 cd->gate_array[reg] &= 0x0F; |
591 cd->gate_array[reg] |= (value << 8 & 0x0F00); | 610 cd->gate_array[reg] |= (value << 8 & 0x0F00); |
592 return vcontext; | 611 return vcontext; |
593 } | 612 } |
594 //intentional fallthrough for $FF804B | 613 //intentional fallthrough for $FF804B |
609 } | 628 } |
610 | 629 |
611 static void scd_peripherals_run(segacd_context *cd, uint32_t cycle) | 630 static void scd_peripherals_run(segacd_context *cd, uint32_t cycle) |
612 { | 631 { |
613 timers_run(cd, cycle); | 632 timers_run(cd, cycle); |
614 cdd_mcu_run(&cd->cdd, cycle, cd->gate_array + GA_CDD_CTRL); | 633 cdd_run(cd, cycle); |
615 } | 634 } |
616 | 635 |
617 static m68k_context *sync_components(m68k_context * context, uint32_t address) | 636 static m68k_context *sync_components(m68k_context * context, uint32_t address) |
618 { | 637 { |
619 segacd_context *cd = context->system; | 638 segacd_context *cd = context->system; |