Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. // DGen/SDL v1.29+
  2. // Megadrive 1 Frame module
  3. // Many, many thanks to John Stiles for the new structure of this module! :)
  4. // And kudos to Gens (Gens/GS) and Genplus (GX) authors -- zamaz
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <unistd.h>
  9. #include <string.h>
  10. #include <limits.h>
  11. #include <assert.h>
  12. #ifdef HAVE_MEMCPY_H
  13. #include "memcpy.h"
  14. #endif
  15. #include "md.h"
  16. #include "debug.h"
  17. #include "rc-vars.h"
  18.  
  19. // Set and unset contexts (Musashi, StarScream, MZ80)
  20.  
  21. #ifdef WITH_MUSA
  22. class md* md::md_musa(0);
  23.  
  24. bool md::md_set_musa(bool set)
  25. {
  26.         if (set) {
  27.                 ++md_musa_ref;
  28.                 if (md_musa == this)
  29.                         return true;
  30.                 md_musa_prev = md_musa;
  31.                 md_musa = this;
  32.                 md_set_musa_sync(true);
  33.                 return false;
  34.         }
  35.         else {
  36.                 if (md_musa != this)
  37.                         abort();
  38.                 if (--md_musa_ref != 0)
  39.                         return true;
  40.                 md_set_musa_sync(false);
  41.                 md_musa = md_musa_prev;
  42.                 md_musa_prev = 0;
  43.                 return true;
  44.         }
  45. }
  46.  
  47. void md::md_set_musa_sync(bool push)
  48. {
  49.         unsigned int i, j;
  50.  
  51.         if (push) {
  52.                 m68k_set_context(ctx_musa);
  53.                 for (i = M68K_REG_D0, j = 0; (i <= M68K_REG_D7); ++i, ++j)
  54.                         m68k_set_reg((m68k_register_t)i,
  55.                                      le2h32(m68k_state.d[j]));
  56.                 for (i = M68K_REG_A0, j = 0; (i <= M68K_REG_A7); ++i, ++j)
  57.                         m68k_set_reg((m68k_register_t)i,
  58.                                      le2h32(m68k_state.a[j]));
  59.                 m68k_set_reg(M68K_REG_PC, le2h32(m68k_state.pc));
  60.                 m68k_set_reg(M68K_REG_SR, le2h16(m68k_state.sr));
  61.         }
  62.         else {
  63.                 for (i = M68K_REG_D0, j = 0; (i <= M68K_REG_D7); ++i, ++j)
  64.                         m68k_state.d[j] =
  65.                                 h2le32(m68k_get_reg(NULL, (m68k_register_t)i));
  66.                 for (i = M68K_REG_A0, j = 0; (i <= M68K_REG_A7); ++i, ++j)
  67.                         m68k_state.a[j] =
  68.                                 h2le32(m68k_get_reg(NULL, (m68k_register_t)i));
  69.                 m68k_state.pc = h2le32(m68k_get_reg(NULL, M68K_REG_PC));
  70.                 m68k_state.sr = h2le16(m68k_get_reg(NULL, M68K_REG_SR));
  71.                 m68k_get_context(ctx_musa);
  72.         }
  73. }
  74. #endif // WITH_MUSA
  75.  
  76. #ifdef WITH_STAR
  77. class md* md::md_star(0);
  78.  
  79. bool md::md_set_star(bool set)
  80. {
  81.         if (set) {
  82.                 ++md_star_ref;
  83.                 if (md_star == this)
  84.                         return true;
  85.                 md_star_prev = md_star;
  86.                 md_star = this;
  87.                 md_set_star_sync(true);
  88.                 return false;
  89.         }
  90.         else {
  91.                 if (md_star != this)
  92.                         abort();
  93.                 if (--md_star_ref != 0)
  94.                         return true;
  95.                 md_set_star_sync(false);
  96.                 md_star = md_star_prev;
  97.                 md_star_prev = 0;
  98.                 return true;
  99.         }
  100. }
  101.  
  102. void md::md_set_star_sync(bool push)
  103. {
  104.         unsigned int i;
  105.  
  106.         if (push) {
  107.                 for (i = 0; (i < 8); ++i) {
  108.                         cpu.dreg[i] = le2h32(m68k_state.d[i]);
  109.                         cpu.areg[i] = le2h32(m68k_state.a[i]);
  110.                 }
  111.                 cpu.pc = le2h32(m68k_state.pc);
  112.                 cpu.sr = le2h16(m68k_state.sr);
  113.                 s68000SetContext(&cpu);
  114.         }
  115.         else {
  116.                 s68000GetContext(&cpu);
  117.                 for (i = 0; (i < 8); ++i) {
  118.                         m68k_state.d[i] = h2le32(cpu.dreg[i]);
  119.                         m68k_state.a[i] = h2le32(cpu.areg[i]);
  120.                 }
  121.                 m68k_state.pc = h2le32(cpu.pc);
  122.                 m68k_state.sr = h2le16(cpu.sr);
  123.         }
  124. }
  125. #endif // WITH_STAR
  126.  
  127. #ifdef WITH_CYCLONE
  128. class md* md::md_cyclone(0);
  129.  
  130. bool md::md_set_cyclone(bool set)
  131. {
  132.         if (set) {
  133.                 ++md_cyclone_ref;
  134.                 if (md_cyclone == this)
  135.                         return true;
  136.                 md_cyclone_prev = md_cyclone;
  137.                 md_cyclone = this;
  138.                 md_set_cyclone_sync(true);
  139.                 return false;
  140.         }
  141.         else {
  142.                 if (md_cyclone != this)
  143.                         abort();
  144.                 if (--md_cyclone_ref != 0)
  145.                         return true;
  146.                 md_set_cyclone_sync(false);
  147.                 md_cyclone = md_cyclone_prev;
  148.                 md_cyclone_prev = 0;
  149.                 return true;
  150.         }
  151. }
  152.  
  153. void md::md_set_cyclone_sync(bool push)
  154. {
  155.         unsigned int i;
  156.  
  157.         if (push) {
  158.                 for (i = 0; (i < 8); ++i) {
  159.                         cyclonecpu.d[i] = le2h32(m68k_state.d[i]);
  160.                         cyclonecpu.a[i] = le2h32(m68k_state.a[i]);
  161.                 }
  162.                 cyclonecpu.membase = 0;
  163.                 cyclonecpu.pc = cyclonecpu.checkpc(le2h32(m68k_state.pc));
  164.                 CycloneSetSr(&cyclonecpu, le2h16(m68k_state.sr));
  165.         }
  166.         else {
  167.                 for (i = 0; (i < 8); ++i) {
  168.                         m68k_state.d[i] = h2le32(cyclonecpu.d[i]);
  169.                         m68k_state.a[i] = h2le32(cyclonecpu.a[i]);
  170.                 }
  171.                 m68k_state.pc = h2le32(cyclonecpu.pc-cyclonecpu.membase);
  172.                 m68k_state.sr = h2le16(CycloneGetSr(&cyclonecpu));
  173.         }
  174. }
  175. #endif // WITH_CYCLONE
  176.  
  177. #ifdef WITH_CZ80
  178. bool md::md_set_cz80(bool set)
  179. {
  180.         if (set) {
  181.                 if (md_cz80_ref++)
  182.                         return true;
  183.                 md_set_cz80_sync(true);
  184.                 return false;
  185.         }
  186.         else {
  187.                 if (md_cz80_ref == 0)
  188.                         abort();
  189.                 if (--md_cz80_ref)
  190.                         return true;
  191.                 md_set_cz80_sync(false);
  192.                 return true;
  193.         }
  194. }
  195.  
  196. void md::md_set_cz80_sync(bool push)
  197. {
  198.         if (push) {
  199.                 Cz80_Set_AF(&cz80, le2h16(z80_state.alt[0].fa));
  200.                 Cz80_Set_BC(&cz80, le2h16(z80_state.alt[0].cb));
  201.                 Cz80_Set_DE(&cz80, le2h16(z80_state.alt[0].ed));
  202.                 Cz80_Set_HL(&cz80, le2h16(z80_state.alt[0].lh));
  203.                 Cz80_Set_AF2(&cz80, le2h16(z80_state.alt[1].fa));
  204.                 Cz80_Set_BC2(&cz80, le2h16(z80_state.alt[1].cb));
  205.                 Cz80_Set_DE2(&cz80, le2h16(z80_state.alt[1].ed));
  206.                 Cz80_Set_HL2(&cz80, le2h16(z80_state.alt[1].lh));
  207.                 Cz80_Set_IX(&cz80, le2h16(z80_state.ix));
  208.                 Cz80_Set_IY(&cz80, le2h16(z80_state.iy));
  209.                 Cz80_Set_SP(&cz80, le2h16(z80_state.sp));
  210.                 Cz80_Set_PC(&cz80, le2h16(z80_state.pc));
  211.                 Cz80_Set_R(&cz80, z80_state.r);
  212.                 Cz80_Set_I(&cz80, z80_state.i);
  213.                 Cz80_Set_IFF(&cz80, z80_state.iff);
  214.                 Cz80_Set_IM(&cz80, z80_state.im);
  215.         }
  216.         else {
  217.                 z80_state.alt[0].fa = h2le16(Cz80_Get_AF(&cz80));
  218.                 z80_state.alt[0].cb = h2le16(Cz80_Get_BC(&cz80));
  219.                 z80_state.alt[0].ed = h2le16(Cz80_Get_DE(&cz80));
  220.                 z80_state.alt[0].lh = h2le16(Cz80_Get_HL(&cz80));
  221.                 z80_state.alt[1].fa = h2le16(Cz80_Get_AF2(&cz80));
  222.                 z80_state.alt[1].cb = h2le16(Cz80_Get_BC2(&cz80));
  223.                 z80_state.alt[1].ed = h2le16(Cz80_Get_DE2(&cz80));
  224.                 z80_state.alt[1].lh = h2le16(Cz80_Get_HL2(&cz80));
  225.                 z80_state.ix = h2le16(Cz80_Get_IX(&cz80));
  226.                 z80_state.iy = h2le16(Cz80_Get_IY(&cz80));
  227.                 z80_state.sp = h2le16(Cz80_Get_SP(&cz80));
  228.                 z80_state.pc = h2le16(Cz80_Get_PC(&cz80));
  229.                 z80_state.r = Cz80_Get_R(&cz80);
  230.                 z80_state.i = Cz80_Get_I(&cz80);
  231.                 z80_state.iff = Cz80_Get_IFF(&cz80);
  232.                 z80_state.im = Cz80_Get_IM(&cz80);
  233.         }
  234. }
  235. #endif // WITH_CZ80
  236.  
  237. #ifdef WITH_MZ80
  238. class md* md::md_mz80(0);
  239.  
  240. bool md::md_set_mz80(bool set)
  241. {
  242.         if (set) {
  243.                 ++md_mz80_ref;
  244.                 if (md_mz80 == this)
  245.                         return true;
  246.                 md_mz80_prev = md_mz80;
  247.                 md_mz80 = this;
  248.                 md_set_mz80_sync(true);
  249.                 return false;
  250.         }
  251.         else {
  252.                 if (md_mz80 != this)
  253.                         abort();
  254.                 if (--md_mz80_ref != 0)
  255.                         return true;
  256.                 md_set_mz80_sync(false);
  257.                 md_mz80 = md_mz80_prev;
  258.                 md_mz80_prev = 0;
  259.                 return true;
  260.         }
  261. }
  262.  
  263. void md::md_set_mz80_sync(bool push)
  264. {
  265.         if (push) {
  266.                 z80.z80AF = le2h16(z80_state.alt[0].fa);
  267.                 z80.z80BC = le2h16(z80_state.alt[0].cb);
  268.                 z80.z80DE = le2h16(z80_state.alt[0].ed);
  269.                 z80.z80HL = le2h16(z80_state.alt[0].lh);
  270.                 z80.z80afprime = le2h16(z80_state.alt[1].fa);
  271.                 z80.z80bcprime = le2h16(z80_state.alt[1].cb);
  272.                 z80.z80deprime = le2h16(z80_state.alt[1].ed);
  273.                 z80.z80hlprime = le2h16(z80_state.alt[1].lh);
  274.                 z80.z80IX = le2h16(z80_state.ix);
  275.                 z80.z80IY = le2h16(z80_state.iy);
  276.                 z80.z80sp = le2h16(z80_state.sp);
  277.                 z80.z80pc = le2h16(z80_state.pc);
  278.                 z80.z80r = z80_state.r;
  279.                 z80.z80i = z80_state.i;
  280.                 z80.z80iff = z80_state.iff;
  281.                 z80.z80interruptMode = z80_state.im;
  282.                 mz80SetContext(&z80);
  283.         }
  284.         else {
  285.                 mz80GetContext(&z80);
  286.                 z80_state.alt[0].fa = h2le16(z80.z80AF);
  287.                 z80_state.alt[0].cb = h2le16(z80.z80BC);
  288.                 z80_state.alt[0].ed = h2le16(z80.z80DE);
  289.                 z80_state.alt[0].lh = h2le16(z80.z80HL);
  290.                 z80_state.alt[1].fa = h2le16(z80.z80afprime);
  291.                 z80_state.alt[1].cb = h2le16(z80.z80bcprime);
  292.                 z80_state.alt[1].ed = h2le16(z80.z80deprime);
  293.                 z80_state.alt[1].lh = h2le16(z80.z80hlprime);
  294.                 z80_state.ix = h2le16(z80.z80IX);
  295.                 z80_state.iy = h2le16(z80.z80IY);
  296.                 z80_state.sp = h2le16(z80.z80sp);
  297.                 z80_state.pc = h2le16(z80.z80pc);
  298.                 z80_state.r = z80.z80r;
  299.                 z80_state.i = z80.z80i;
  300.                 z80_state.iff = z80.z80iff;
  301.                 z80_state.im = z80.z80interruptMode;
  302.         }
  303. }
  304. #endif // WITH_MZ80
  305.  
  306. #ifdef WITH_DRZ80
  307. class md* md::md_drz80(0);
  308.  
  309. bool md::md_set_drz80(bool set)
  310. {
  311.         if (set) {
  312.                 ++md_drz80_ref;
  313.                 if (md_drz80 == this)
  314.                         return true;
  315.                 md_drz80_prev = md_drz80;
  316.                 md_drz80 = this;
  317.                 md_set_drz80_sync(true);
  318.                 return false;
  319.         }
  320.         else {
  321.                 if (md_drz80 != this)
  322.                         abort();
  323.                 if (--md_drz80_ref != 0)
  324.                         return true;
  325.                 md_set_drz80_sync(false);
  326.                 md_drz80 = md_drz80_prev;
  327.                 md_drz80_prev = 0;
  328.                 return true;
  329.         }
  330. }
  331.  
  332. void md::md_set_drz80_sync(bool push)
  333. {
  334.         if (push) {
  335.                 drz80.Z80A = ((le2h16(z80_state.alt[0].fa) & 0xff00) << 16);
  336.                 drz80.Z80F = (le2h16(z80_state.alt[0].fa) & 0x00ff);
  337.                 drz80.Z80BC = (le2h16(z80_state.alt[0].cb) << 16);
  338.                 drz80.Z80DE = (le2h16(z80_state.alt[0].ed) << 16);
  339.                 drz80.Z80HL = (le2h16(z80_state.alt[0].lh) << 16);
  340.                 drz80.Z80A2 = ((le2h16(z80_state.alt[1].fa) & 0xff00) << 16);
  341.                 drz80.Z80F2 = ((le2h16(z80_state.alt[1].fa) & 0x00ff) << 24);
  342.                 drz80.Z80BC2 = (le2h16(z80_state.alt[1].cb) << 16);
  343.                 drz80.Z80DE2 = (le2h16(z80_state.alt[1].ed) << 16);
  344.                 drz80.Z80HL2 = (le2h16(z80_state.alt[1].lh) << 16);
  345.                 drz80.Z80IX = (le2h16(z80_state.ix) << 16);
  346.                 drz80.Z80IY = (le2h16(z80_state.iy) << 16);
  347.                 drz80.Z80SP_BASE = (uintptr_t)z80ram;
  348.                 drz80.Z80PC_BASE = (uintptr_t)z80ram;
  349.                 drz80.Z80SP = (drz80.Z80SP_BASE + le2h16(z80_state.sp));
  350.                 drz80.Z80PC = (drz80.Z80PC_BASE + le2h16(z80_state.pc));
  351.                 drz80.Z80R = z80_state.r;
  352.                 drz80.Z80I = z80_state.i;
  353.                 drz80.Z80IF = z80_state.iff;
  354.                 drz80.Z80IM = z80_state.im;
  355.         }
  356.         else {
  357.                 z80_state.alt[0].fa = h2le16(((drz80.Z80A >> 16) & 0xff00) |
  358.                                              (drz80.Z80F & 0x00ff));
  359.                 z80_state.alt[0].cb = h2le16(drz80.Z80BC >> 16);
  360.                 z80_state.alt[0].ed = h2le16(drz80.Z80DE >> 16);
  361.                 z80_state.alt[0].lh = h2le16(drz80.Z80HL >> 16);
  362.                 z80_state.alt[1].fa = h2le16(((drz80.Z80A2 >> 16) & 0xff00) |
  363.                                              ((drz80.Z80F2 >> 24) & 0x00ff));
  364.                 z80_state.alt[1].cb = h2le16(drz80.Z80BC2 >> 16);
  365.                 z80_state.alt[1].ed = h2le16(drz80.Z80DE2 >> 16);
  366.                 z80_state.alt[1].lh = h2le16(drz80.Z80HL2 >> 16);
  367.                 z80_state.ix = h2le16(drz80.Z80IX >> 16);
  368.                 z80_state.iy = h2le16(drz80.Z80IY >> 16);
  369.                 z80_state.sp = h2le16(drz80.Z80SP - drz80.Z80SP_BASE);
  370.                 z80_state.pc = h2le16(drz80.Z80PC - drz80.Z80PC_BASE);
  371.                 z80_state.r = drz80.Z80R;
  372.                 z80_state.i = drz80.Z80I;
  373.                 z80_state.iff = drz80.Z80IF;
  374.                 z80_state.im = drz80.Z80IM;
  375.         }
  376. }
  377. #endif // WITH_DRZ80
  378.  
  379. // Set/unset contexts
  380. void md::md_set(bool set)
  381. {
  382. #ifdef WITH_MUSA
  383.         if (cpu_emu == CPU_EMU_MUSA)
  384.                 md_set_musa(set);
  385.         else
  386. #endif
  387. #ifdef WITH_CYCLONE
  388.         if (cpu_emu == CPU_EMU_CYCLONE)
  389.                 md_set_cyclone(set);
  390.         else
  391. #endif
  392. #ifdef WITH_STAR
  393.         if (cpu_emu == CPU_EMU_STAR)
  394.                 md_set_star(set);
  395.         else
  396. #endif
  397.                 (void)0;
  398. #ifdef WITH_CZ80
  399.         if (z80_core == Z80_CORE_CZ80)
  400.                 md_set_cz80(set);
  401.         else
  402. #endif
  403. #ifdef WITH_MZ80
  404.         if (z80_core == Z80_CORE_MZ80)
  405.                 md_set_mz80(set);
  406.         else
  407. #endif
  408. #ifdef WITH_DRZ80
  409.         if (z80_core == Z80_CORE_DRZ80)
  410.                 md_set_drz80(set);
  411.         else
  412. #endif
  413.                 (void)0;
  414. }
  415.  
  416. // Return PC data.
  417. unsigned int md::m68k_read_pc()
  418. {
  419.         static bool rec = false;
  420.         unsigned int pc;
  421.  
  422.         // Forbid recursion.
  423.         if (rec)
  424.                 return h2be16(0xdead);
  425.         rec = true;
  426. #ifdef WITH_MUSA
  427.         if (cpu_emu == CPU_EMU_MUSA) {
  428.                 md_set_musa(1);
  429.                 pc = m68k_get_reg(NULL, M68K_REG_PC);
  430.                 md_set_musa(0);
  431.         }
  432.         else
  433. #endif
  434. #ifdef WITH_CYCLONE
  435.         if (cpu_emu == CPU_EMU_CYCLONE) {
  436.                 md_set_cyclone(1);
  437.                 pc = (cyclonecpu.pc - cyclonecpu.membase);
  438.                 md_set_cyclone(0);
  439.         }
  440.         else
  441. #endif
  442. #ifdef WITH_STAR
  443.         if (cpu_emu == CPU_EMU_STAR) {
  444.                 md_set_star(1);
  445.                 pc = cpu.pc;
  446.                 md_set_star(0);
  447.         }
  448.         else
  449. #endif
  450.                 pc = 0;
  451.         pc = misc_readword(pc & 0xffffff);
  452.         rec = false;
  453.         return pc;
  454. }
  455.  
  456. // Return current M68K odometer
  457. int md::m68k_odo()
  458. {
  459.         if (m68k_st_running) {
  460. #ifdef WITH_MUSA
  461.                 if (cpu_emu == CPU_EMU_MUSA)
  462.                         return (odo.m68k + m68k_cycles_run());
  463. #endif
  464. #ifdef WITH_CYCLONE
  465.                 if (cpu_emu == CPU_EMU_CYCLONE)
  466.                         return (odo.m68k +
  467.                                 ((odo.m68k_max - odo.m68k) -
  468.                                  cyclonecpu.cycles));
  469. #endif
  470. #ifdef WITH_STAR
  471.                 if (cpu_emu == CPU_EMU_STAR)
  472.                         return (odo.m68k + s68000readOdometer());
  473. #endif
  474.         }
  475.         return odo.m68k;
  476. }
  477.  
  478. // Run M68K to odo.m68k_max
  479. void md::m68k_run()
  480. {
  481.         int cycles = (odo.m68k_max - odo.m68k);
  482. #ifdef WITH_DEBUGGER
  483.         int cycles_to_debug = 0;
  484.         int prev_odo = 0;
  485.         bool debug_m68k;
  486. #endif
  487.  
  488.         if (cycles <= 0)
  489.                 return;
  490.         m68k_st_running = 1;
  491. #ifdef WITH_DEBUGGER
  492.         if (debug_trap)
  493.                 goto cpu_stalled;
  494.         debug_m68k = (debug_step_m68k ||
  495.                       debug_trace_m68k ||
  496.                       debug_instr_count_enabled ||
  497.                       debug_is_m68k_bp_set() ||
  498.                       debug_is_m68k_wp_set());
  499.         if (debug_m68k) {
  500.                 prev_odo = odo.m68k;
  501.                 cycles_to_debug = cycles;
  502.                 cycles = 1;
  503.         debug_next_instruction:
  504.                 if (debug_m68k_check_bps())
  505.                         goto cpu_stalled;
  506.         }
  507. #endif
  508. #ifdef WITH_MUSA
  509.         if (cpu_emu == CPU_EMU_MUSA)
  510.                 odo.m68k += m68k_execute(cycles);
  511.         else
  512. #endif
  513. #ifdef WITH_STAR
  514.         if (cpu_emu == CPU_EMU_STAR) {
  515.                 s68000tripOdometer();
  516.                 s68000exec(cycles);
  517.                 odo.m68k += s68000readOdometer();
  518.         }
  519.         else
  520. #endif
  521. #ifdef WITH_CYCLONE
  522.         if (cpu_emu == CPU_EMU_CYCLONE) {
  523.                 cyclonecpu.cycles = cycles;
  524.                 CycloneRun(&cyclonecpu);
  525.                 odo.m68k += (cycles - cyclonecpu.cycles);
  526.         }
  527.         else
  528. #endif
  529.                 odo.m68k += cycles;
  530. #ifdef WITH_DEBUGGER
  531.         if (debug_m68k) {
  532.                 ++debug_m68k_instr_count;
  533.                 if (debug_m68k_check_wps())
  534.                         goto cpu_stalled;
  535.                 cycles_to_debug -= (odo.m68k - prev_odo);
  536.                 if (cycles_to_debug > 0) {
  537.                         prev_odo = odo.m68k;
  538.                         goto debug_next_instruction;
  539.                 }
  540.         }
  541. cpu_stalled:
  542. #endif
  543.         m68k_st_running = 0;
  544. }
  545.  
  546. // Issue BUSREQ
  547. void md::m68k_busreq_request()
  548. {
  549.         if (z80_st_busreq)
  550.                 return;
  551.         z80_st_busreq = 1;
  552.         if (z80_st_reset)
  553.                 return;
  554.         z80_sync(0);
  555. }
  556.  
  557. // Cancel BUSREQ
  558. void md::m68k_busreq_cancel()
  559. {
  560.         if (!z80_st_busreq)
  561.                 return;
  562.         z80_st_busreq = 0;
  563.         z80_sync(1);
  564. }
  565.  
  566. // Trigger M68K IRQ
  567. void md::m68k_irq(int i)
  568. {
  569. #ifdef WITH_DEBUGGER
  570.         // Ignore interrupts while debugger is active or stepping by a
  571.         // small amount (XXX should be configurable).
  572.         if (debug_trap || (debug_step_m68k && debug_step_m68k < 10000))
  573.                 return;
  574. #endif
  575. #ifdef WITH_MUSA
  576.         if (cpu_emu == CPU_EMU_MUSA)
  577.                 m68k_set_irq(i);
  578.         else
  579. #endif
  580. #ifdef WITH_CYCLONE
  581.         if (cpu_emu == CPU_EMU_CYCLONE)
  582.                 cyclonecpu.irq = i;
  583.         else
  584. #endif
  585. #ifdef WITH_STAR
  586.         if (cpu_emu == CPU_EMU_STAR) {
  587.                 if (i)
  588.                         s68000interrupt(i, -1);
  589.                 else {
  590.                         s68000GetContext(&cpu);
  591.                         memset(cpu.interrupts, 0, sizeof(cpu.interrupts));
  592.                         s68000SetContext(&cpu);
  593.                 }
  594.         }
  595.         else
  596. #endif
  597.                 (void)i;
  598. }
  599.  
  600. // Trigger M68K IRQ or disable them according to VDP status.
  601. void md::m68k_vdp_irq_trigger()
  602. {
  603.         if ((vdp.vint_pending) && (vdp.reg[1] & 0x20))
  604.                 m68k_irq(6);
  605.         else if ((vdp.hint_pending) && (vdp.reg[0] & 0x10))
  606.                 m68k_irq(4);
  607.         else
  608.                 m68k_irq(0);
  609. }
  610.  
  611. // Called whenever M68K acknowledges an interrupt.
  612. void md::m68k_vdp_irq_handler()
  613. {
  614.         if ((vdp.vint_pending) && (vdp.reg[1] & 0x20)) {
  615.                 vdp.vint_pending = false;
  616.                 coo5 &= ~0x80;
  617.                 if ((vdp.hint_pending) && (vdp.reg[0] & 0x10))
  618.                         m68k_irq(4);
  619.                 else {
  620.                         vdp.hint_pending = false;
  621.                         m68k_irq(0);
  622.                 }
  623.         }
  624.         else {
  625.                 vdp.hint_pending = false;
  626.                 m68k_irq(0);
  627.         }
  628. }
  629.  
  630. // Return current Z80 odometer
  631. int md::z80_odo()
  632. {
  633.         if (z80_st_running) {
  634. #ifdef WITH_CZ80
  635.                 if (z80_core == Z80_CORE_CZ80)
  636.                         return (odo.z80 + Cz80_Get_CycleRemaining(&cz80));
  637. #endif
  638. #ifdef WITH_MZ80
  639.                 if (z80_core == Z80_CORE_MZ80)
  640.                         return (odo.z80 + mz80GetElapsedTicks(0));
  641. #endif
  642. #ifdef WITH_DRZ80
  643.                 if (z80_core == Z80_CORE_DRZ80)
  644.                         return (odo.z80 +
  645.                                 ((odo.z80_max - odo.z80) - drz80.cycles));
  646. #endif
  647.         }
  648.         return odo.z80;
  649. }
  650.  
  651. // Run Z80 to odo.z80_max
  652. void md::z80_run()
  653. {
  654.         int cycles = (odo.z80_max - odo.z80);
  655. #ifdef WITH_DEBUGGER
  656.         int cycles_to_debug = 0;
  657.         int prev_odo = 0;
  658.         bool debug_z80;
  659. #endif
  660.  
  661.         if (cycles <= 0)
  662.                 return;
  663.         z80_st_running = 1;
  664. #ifdef WITH_DEBUGGER
  665.         if (debug_trap)
  666.                 goto cpu_stalled;
  667.         debug_z80 = (debug_step_z80 ||
  668.                      debug_trace_z80 ||
  669.                      debug_instr_count_enabled ||
  670.                      debug_is_z80_bp_set() ||
  671.                      debug_is_z80_wp_set());
  672.         if (debug_z80) {
  673.                 prev_odo = odo.z80;
  674.                 cycles_to_debug = cycles;
  675.                 cycles = 1;
  676.         debug_next_instruction:
  677.                 if (debug_z80_check_bps())
  678.                         goto cpu_stalled;
  679.         }
  680. #endif
  681.         if (z80_st_busreq | z80_st_reset)
  682.                 odo.z80 += cycles;
  683.         else {
  684. #ifdef WITH_CZ80
  685.                 if (z80_core == Z80_CORE_CZ80)
  686.                         odo.z80 += Cz80_Exec(&cz80, cycles);
  687.                 else
  688. #endif
  689. #ifdef WITH_MZ80
  690.                 if (z80_core == Z80_CORE_MZ80) {
  691.                         mz80exec(cycles);
  692.                         odo.z80 += mz80GetElapsedTicks(1);
  693.                 }
  694.                 else
  695. #endif
  696. #ifdef WITH_DRZ80
  697.                 if (z80_core == Z80_CORE_DRZ80) {
  698.                         int rem = DrZ80Run(&drz80, cycles);
  699.  
  700.                         // drz80.cycles is the number of cycles remaining,
  701.                         // so it must be either 0 or a negative value.
  702.                         // z80_odo() relies on this.
  703.                         // This value is also returned by DrZ80Run().
  704.                         assert(drz80.cycles <= 0);
  705.                         assert(drz80.cycles == rem);
  706.                         odo.z80 += (cycles - rem);
  707.                 }
  708.                 else
  709. #endif
  710.                         odo.z80 += cycles;
  711.         }
  712. #ifdef WITH_DEBUGGER
  713.         if (debug_z80) {
  714.                 ++debug_z80_instr_count;
  715.                 if (debug_z80_check_wps())
  716.                         goto cpu_stalled;
  717.                 cycles_to_debug -= (odo.z80 - prev_odo);
  718.                 if (cycles_to_debug > 0) {
  719.                         prev_odo = odo.z80;
  720.                         goto debug_next_instruction;
  721.                 }
  722.         }
  723. cpu_stalled:
  724. #endif
  725.         z80_st_running = 0;
  726. }
  727.  
  728. // Synchronize Z80 with M68K, don't execute code if fake is nonzero
  729. void md::z80_sync(int fake)
  730. {
  731.         int cycles = (m68k_odo() >> 1);
  732. #ifdef WITH_DEBUGGER
  733.         int cycles_to_debug = 0;
  734.         int prev_odo = 0;
  735.         bool debug_z80;
  736. #endif
  737.  
  738.         if (cycles > odo.z80_max)
  739.                 cycles = odo.z80_max;
  740.         cycles -= odo.z80;
  741.         if (cycles <= 0)
  742.                 return;
  743.         z80_st_running = 1;
  744. #ifdef WITH_DEBUGGER
  745.         if (debug_trap)
  746.                 goto cpu_stalled;
  747.         debug_z80 = (debug_step_z80 ||
  748.                      debug_trace_z80 ||
  749.                      debug_instr_count_enabled ||
  750.                      debug_is_z80_bp_set() ||
  751.                      debug_is_z80_wp_set());
  752.         if (debug_z80) {
  753.                 prev_odo = odo.z80;
  754.                 cycles_to_debug = cycles;
  755.                 cycles = 1;
  756.         debug_next_instruction:
  757.                 if (debug_z80_check_bps())
  758.                         goto cpu_stalled;
  759.         }
  760. #endif
  761.         if (fake)
  762.                 odo.z80 += cycles;
  763.         else {
  764. #ifdef WITH_CZ80
  765.                 if (z80_core == Z80_CORE_CZ80)
  766.                         odo.z80 += Cz80_Exec(&cz80, cycles);
  767.                 else
  768. #endif
  769. #ifdef WITH_MZ80
  770.                 if (z80_core == Z80_CORE_MZ80) {
  771.                         mz80exec(cycles);
  772.                         odo.z80 += mz80GetElapsedTicks(1);
  773.                 }
  774.                 else
  775. #endif
  776. #ifdef WITH_DRZ80
  777.                 if (z80_core == Z80_CORE_DRZ80) {
  778.                         int rem = DrZ80Run(&drz80, cycles);
  779.  
  780.                         // drz80.cycles is the number of cycles remaining,
  781.                         // so it must be either 0 or a negative value.
  782.                         // z80_odo() relies on this.
  783.                         // This value is also returned by DrZ80Run().
  784.                         assert(drz80.cycles <= 0);
  785.                         assert(drz80.cycles == rem);
  786.                         odo.z80 += (cycles - rem);
  787.                 }
  788.                 else
  789. #endif
  790.                         odo.z80 += cycles;
  791.         }
  792. #ifdef WITH_DEBUGGER
  793.         if (debug_z80) {
  794.                 ++debug_z80_instr_count;
  795.                 if (debug_z80_check_wps())
  796.                         goto cpu_stalled;
  797.                 cycles_to_debug -= (odo.z80 - prev_odo);
  798.                 if (cycles_to_debug > 0) {
  799.                         prev_odo = odo.z80;
  800.                         goto debug_next_instruction;
  801.                 }
  802.         }
  803. cpu_stalled:
  804. #endif
  805.         z80_st_running = 0;
  806. }
  807.  
  808. // Trigger Z80 IRQ
  809. void md::z80_irq(int vector)
  810. {
  811. #ifdef WITH_DEBUGGER
  812.         // Ignore interrupts while debugger is active or stepping by a
  813.         // small amount (XXX should be configurable).
  814.         if (debug_trap || (debug_step_z80 && debug_step_z80 < 1000))
  815.                 return;
  816. #endif
  817.         z80_st_irq = 1;
  818.         z80_irq_vector = vector;
  819. #ifdef WITH_CZ80
  820.         if (z80_core == Z80_CORE_CZ80)
  821.                 Cz80_Set_IRQ(&cz80, vector);
  822.         else
  823. #endif
  824. #ifdef WITH_MZ80
  825.         if (z80_core == Z80_CORE_MZ80)
  826.                 mz80int(vector);
  827.         else
  828. #endif
  829. #ifdef WITH_DRZ80
  830.         if (z80_core == Z80_CORE_DRZ80) {
  831.                 drz80.z80irqvector = vector;
  832.                 drz80.Z80_IRQ = 1;
  833.         }
  834.         else
  835. #endif
  836.                 (void)0;
  837. }
  838.  
  839. // Clear Z80 IRQ
  840. void md::z80_irq_clear()
  841. {
  842.         z80_st_irq = 0;
  843.         z80_irq_vector = 0;
  844. #ifdef WITH_CZ80
  845.         if (z80_core == Z80_CORE_CZ80)
  846.                 Cz80_Clear_IRQ(&cz80);
  847.         else
  848. #endif
  849. #ifdef WITH_MZ80
  850.         if (z80_core == Z80_CORE_MZ80)
  851.                 mz80ClearPendingInterrupt();
  852.         else
  853. #endif
  854. #ifdef WITH_DRZ80
  855.         if (z80_core == Z80_CORE_DRZ80) {
  856.                 drz80.z80irqvector = 0x00;
  857.                 drz80.Z80_IRQ = 0x00;
  858.         }
  859.         else
  860. #endif
  861.                 (void)0;
  862. }
  863.  
  864. // Return the number of microseconds spent in current frame
  865. unsigned int md::frame_usecs()
  866. {
  867.         if (z80_st_running)
  868.                 return ((z80_odo() * 1000) / (clk0 / 1000));
  869.         return ((m68k_odo() * 1000) / (clk1 / 1000));
  870. }
  871.  
  872. // Return first line of vblank
  873. unsigned int md::vblank()
  874. {
  875.         return (((pal) && (vdp.reg[1] & 0x08)) ? PAL_VBLANK : NTSC_VBLANK);
  876. }
  877.  
  878. // 6-button pad status update. Should be called once per displayed line.
  879. void md::pad_update()
  880. {
  881.         // The following code was originally in DGen until at least DGen v1.21
  882.         // (Win32 version) but wasn't in DGen/SDL v1.23, preventing 6-button
  883.         // emulation from working at all until now (v1.31 included).
  884.         // This broke some games (no input at all).
  885.  
  886.         // Reset 6-button pad toggle after 26? lines
  887.         if (aoo3_six_timeout > 25)
  888.                 aoo3_six = 0;
  889.         else
  890.                 ++aoo3_six_timeout;
  891.         if (aoo5_six_timeout > 25)
  892.                 aoo5_six = 0;
  893.         else
  894.                 ++aoo5_six_timeout;
  895. }
  896.  
  897. // Generate one frame
  898. int md::one_frame(struct bmap *bm, unsigned char retpal[256],
  899.                   struct sndinfo *sndi)
  900. {
  901.         int hints;
  902.         int m68k_max, z80_max;
  903.         unsigned int vblank = md::vblank();
  904.  
  905. #ifdef WITH_DEBUGGER
  906.         if (debug_trap)
  907.                 return 0;
  908. #endif
  909. #ifdef WITH_DEBUG_VDP
  910.         /*
  911.          * If the user is disabling planes for debugging, then we
  912.          * paint the screen black before blitting a new frame. This
  913.          * stops crap from earlier frames from junking up the display.
  914.          */
  915.         if ((bm != NULL) &&
  916.             (dgen_vdp_hide_plane_b | dgen_vdp_hide_plane_a |
  917.              dgen_vdp_hide_plane_w | dgen_vdp_hide_sprites))
  918.                 memset(bm->data, 0, (bm->pitch * bm->h));
  919. #endif
  920.         md_set(1);
  921.         // Reset odometers
  922.         memset(&odo, 0, sizeof(odo));
  923.         // Reset FM tickers
  924.         fm_ticker[1] = 0;
  925.         fm_ticker[3] = 0;
  926.         // Raster zero causes special things to happen :)
  927.         // Init status register with fifo always empty (FIXME)
  928.         coo4 = (0x34 | 0x02); // 00110100b | 00000010b
  929.         if (vdp.reg[12] & 0x2)
  930.                 coo5 ^= 0x10; // Toggle odd/even for interlace
  931.         coo5 &= ~0x08; // Clear vblank
  932.         coo5 |= !!pal;
  933.         // Clear sprite overflow bit (d6).
  934.         coo5 &= ~0x40;
  935.         // Clear sprite collision bit (d5).
  936.         coo5 &= ~0x20;
  937.         // Is permanently set
  938.         hints = vdp.reg[10]; // Set hint counter
  939.         // Reset sprite overflow line
  940.         vdp.sprite_overflow_line = INT_MIN;
  941.         // Video display! :D
  942.         for (ras = 0; ((unsigned int)ras < vblank); ++ras) {
  943.                 pad_update(); // Update 6-button pads
  944.                 fm_timer_callback(); // Update sound timers
  945.                 if (--hints < 0) {
  946.                         // Trigger hint
  947.                         hints = vdp.reg[10];
  948.                         vdp.hint_pending = true;
  949.                         m68k_vdp_irq_trigger();
  950.                         may_want_to_get_pic(bm, retpal, 1);
  951.                 }
  952.                 else
  953.                         may_want_to_get_pic(bm, retpal, 0);
  954.                 // Enable h-blank
  955.                 coo5 |= 0x04;
  956.                 // H-blank comes before, about 36/209 of the whole scanline
  957.                 m68k_max = (odo.m68k_max + M68K_CYCLES_PER_LINE);
  958.                 odo.m68k_max += M68K_CYCLES_HBLANK;
  959.                 z80_max = (odo.z80_max + Z80_CYCLES_PER_LINE);
  960.                 odo.z80_max += Z80_CYCLES_HBLANK;
  961.                 m68k_run();
  962.                 z80_run();
  963.                 // Disable h-blank
  964.                 coo5 &= ~0x04;
  965.                 // Do hdisplay now
  966.                 odo.m68k_max = m68k_max;
  967.                 odo.z80_max = z80_max;
  968.                 m68k_run();
  969.                 z80_run();
  970.         }
  971.         // Now we're in vblank, more special things happen :)
  972.         // The following was roughly adapted from Genplus GX
  973.         // Enable v-blank
  974.         coo5 |= 0x08;
  975.         if (--hints < 0) {
  976.                 // Trigger hint
  977.                 vdp.hint_pending = true;
  978.                 m68k_vdp_irq_trigger();
  979.         }
  980.         // Save m68k_max and z80_max
  981.         m68k_max = (odo.m68k_max + M68K_CYCLES_PER_LINE);
  982.         z80_max = (odo.z80_max + Z80_CYCLES_PER_LINE);
  983.         // Delay between vint and vint flag
  984.         odo.m68k_max += M68K_CYCLES_HBLANK;
  985.         odo.z80_max += Z80_CYCLES_HBLANK;
  986.         // Enable h-blank
  987.         coo5 |= 0x04;
  988.         m68k_run();
  989.         z80_run();
  990.         // Disable h-blank
  991.         coo5 &= ~0x04;
  992.         // Toggle vint flag
  993.         coo5 |= 0x80;
  994.         // Delay between v-blank and vint
  995.         odo.m68k_max += (M68K_CYCLES_VDELAY - M68K_CYCLES_HBLANK);
  996.         odo.z80_max += (Z80_CYCLES_VDELAY - Z80_CYCLES_HBLANK);
  997.         m68k_run();
  998.         z80_run();
  999.         // Restore m68k_max and z80_max
  1000.         odo.m68k_max = m68k_max;
  1001.         odo.z80_max = z80_max;
  1002.         // Blank everything and trigger vint
  1003.         vdp.vint_pending = true;
  1004.         m68k_vdp_irq_trigger();
  1005.         if (!z80_st_reset)
  1006.                 z80_irq(0);
  1007.         fm_timer_callback();
  1008.         // Run remaining cycles
  1009.         m68k_run();
  1010.         z80_run();
  1011.         ++ras;
  1012.         // Run the course of vblank
  1013.         pad_update();
  1014.         fm_timer_callback();
  1015.         // Usual h-blank stuff
  1016.         coo5 |= 0x04;
  1017.         m68k_max = (odo.m68k_max + M68K_CYCLES_PER_LINE);
  1018.         odo.m68k_max += M68K_CYCLES_HBLANK;
  1019.         z80_max = (odo.z80_max + Z80_CYCLES_PER_LINE);
  1020.         odo.z80_max += Z80_CYCLES_HBLANK;
  1021.         m68k_run();
  1022.         z80_run();
  1023.         coo5 &= ~0x04;
  1024.         odo.m68k_max = m68k_max;
  1025.         odo.z80_max = z80_max;
  1026.         m68k_run();
  1027.         z80_run();
  1028.         // Clear Z80 interrupt
  1029.         if (z80_st_irq)
  1030.                 z80_irq_clear();
  1031.         ++ras;
  1032.         // Remaining lines
  1033.         while ((unsigned int)ras < lines) {
  1034.                 pad_update();
  1035.                 fm_timer_callback();
  1036.                 // Enable h-blank
  1037.                 coo5 |= 0x04;
  1038.                 m68k_max = (odo.m68k_max + M68K_CYCLES_PER_LINE);
  1039.                 odo.m68k_max += M68K_CYCLES_HBLANK;
  1040.                 z80_max = (odo.z80_max + Z80_CYCLES_PER_LINE);
  1041.                 odo.z80_max += Z80_CYCLES_HBLANK;
  1042.                 m68k_run();
  1043.                 z80_run();
  1044.                 // Disable h-blank
  1045.                 coo5 &= ~0x04;
  1046.                 odo.m68k_max = m68k_max;
  1047.                 odo.z80_max = z80_max;
  1048.                 m68k_run();
  1049.                 z80_run();
  1050.                 ++ras;
  1051.         }
  1052.         // Fill the sound buffers
  1053.         if (sndi)
  1054.                 may_want_to_get_sound(sndi);
  1055.         fm_timer_callback();
  1056.         md_set(0);
  1057. #ifdef WITH_VGMDUMP
  1058.         vgm_dump_frame();
  1059. #endif
  1060.         return 0;
  1061. }
  1062.  
  1063. // Return V counter (Gens/GS style)
  1064. uint8_t md::calculate_coo8()
  1065. {
  1066.         unsigned int id;
  1067.         unsigned int hc, vc;
  1068.         uint8_t bl, bh;
  1069.  
  1070.         id = m68k_odo();
  1071.         /*
  1072.           FIXME
  1073.           Using "(ras - 1)" instead of "ras" here seems to solve horizon
  1074.           issues in Road Rash and Mickey Mania (Moose Chase level).
  1075.         */
  1076.         if (ras)
  1077.                 id -= ((ras - 1) * M68K_CYCLES_PER_LINE);
  1078.         id &= 0x1ff;
  1079.         if (vdp.reg[4] & 0x81) {
  1080.                 hc = hc_table[id][1];
  1081.                 bl = 0xa4;
  1082.         }
  1083.         else {
  1084.                 hc = hc_table[id][0];
  1085.                 bl = 0x84;
  1086.         }
  1087.         bh = (hc <= 0xe0);
  1088.         bl = (hc >= bl);
  1089.         bl &= bh;
  1090.         vc = ras;
  1091.         vc += (bl != 0);
  1092.         if (pal) {
  1093.                 if (vc >= 0x103)
  1094.                         vc -= 56;
  1095.         }
  1096.         else {
  1097.                 if (vc >= 0xeb)
  1098.                         vc -= 6;
  1099.         }
  1100.         return vc;
  1101. }
  1102.  
  1103. // Return H counter (Gens/GS style)
  1104. uint8_t md::calculate_coo9()
  1105. {
  1106.         unsigned int id;
  1107.  
  1108.         id = m68k_odo();
  1109.         if (ras)
  1110.                 id -= ((ras - 1) * M68K_CYCLES_PER_LINE);
  1111.         id &= 0x1ff;
  1112.         if (vdp.reg[4] & 0x81)
  1113.                 return hc_table[id][1];
  1114.         return hc_table[id][0];
  1115. }
  1116.  
  1117. // *************************************
  1118. //       May want to get pic or sound
  1119. // *************************************
  1120.  
  1121. inline int md::may_want_to_get_pic(struct bmap *bm,unsigned char retpal[256],int/*mark*/)
  1122. {
  1123.   if (bm==NULL) return 0;
  1124.  
  1125.   if (ras>=0 && (unsigned int)ras<vblank())
  1126.     vdp.draw_scanline(bm, ras);
  1127.   if(retpal && ras == 100) get_md_palette(retpal, vdp.cram);
  1128.   return 0;
  1129. }
  1130.  
  1131. int md::may_want_to_get_sound(struct sndinfo *sndi)
  1132. {
  1133.   extern intptr_t dgen_volume;
  1134.   unsigned int i, len = sndi->len;
  1135.  
  1136.   // Get the PSG
  1137.   SN76496Update_16_2(0, sndi->lr, len);
  1138.  
  1139.         if (dac_len) {
  1140.                 unsigned int ratio = ((sndi->len << 10) / elemof(dac_data));
  1141.  
  1142.                 // Stretch the DAC to fit the real length.
  1143.                 for (i = 0; (i != sndi->len); ++i) {
  1144.                         unsigned int index = ((i << 10) / ratio);
  1145.                         uint16_t data;
  1146.  
  1147.                         if (index >= dac_len)
  1148.                                 data = dac_data[dac_len - 1];
  1149.                         else
  1150.                                 data = dac_data[index];
  1151.                         data = ((data - 0x80) << 6);
  1152.                         sndi->lr[i << 1] += data;
  1153.                         sndi->lr[(i << 1) ^ 1] += data;
  1154.                 }
  1155.                 // Clear the DAC for next frame.
  1156.                 dac_len = 0;
  1157. #ifndef NDEBUG
  1158.                 memset(dac_data, 0xff, sizeof(dac_data));
  1159. #endif
  1160.         }
  1161.  
  1162.   // Add in the stereo FM buffer
  1163.   YM2612UpdateOne(0, sndi->lr, len, dgen_volume, 1);
  1164.   if (dgen_mjazz) {
  1165.     YM2612UpdateOne(1, sndi->lr, len, dgen_volume, 0);
  1166.     YM2612UpdateOne(2, sndi->lr, len, dgen_volume, 0);
  1167.   }
  1168.   return 0;
  1169. }
  1170.  
  1171.