core, implement ym2612 busy flag
authorkub <derkub@gmail.com>
Sun, 3 Mar 2024 21:57:58 +0000 (22:57 +0100)
committerkub <derkub@gmail.com>
Mon, 4 Mar 2024 20:59:52 +0000 (21:59 +0100)
pico/memory.c
pico/pico_int.h

index fc8e33d..e9232d1 100644 (file)
@@ -1066,6 +1066,8 @@ static int get_scanline(int is_from_z80)
 }\r
 \r
 #define ym2612_update_status(xcycles) \\r
+  ym2612.OPN.ST.status &= ~0x80; \\r
+  ym2612.OPN.ST.status |= (xcycles < Pico.t.ym2612_busy) * 0x80; \\r
   if (xcycles >= Pico.t.timer_a_next_oflow) \\r
     ym2612.OPN.ST.status |= (ym2612.OPN.ST.mode >> 2) & 1; \\r
   if (xcycles >= Pico.t.timer_b_next_oflow) \\r
@@ -1131,6 +1133,7 @@ void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new)
 // ym2612 DAC and timer I/O handlers for z80\r
 static int ym2612_write_local(u32 a, u32 d, int is_from_z80)\r
 {\r
+  int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k();\r
   int addr;\r
 \r
   a &= 3;\r
@@ -1150,6 +1153,10 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80)
       addr = ym2612.OPN.ST.address | ((int)ym2612.addr_A1 << 8);\r
       ym2612.REGS[addr] = d;\r
 \r
+      // the busy flag in the YM2612 status is actually a 32 cycle timer\r
+      // (89.6 Z80 cycles), triggered by any write to the data port.\r
+      Pico.t.ym2612_busy = (cycles + 90) << 8; // Q8 for convenience\r
+\r
       switch (addr)\r
       {\r
         case 0x24: // timer A High 8\r
@@ -1158,7 +1165,6 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80)
                                      : ((ym2612.OPN.ST.TA & 0x3fc)|(d&3));\r
           if (ym2612.OPN.ST.TA != TAnew)\r
           {\r
-            int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k();\r
             ym2612_sync_timers(cycles, ym2612.OPN.ST.mode, ym2612.OPN.ST.mode);\r
             //elprintf(EL_STATUS, "timer a set %i", TAnew);\r
             ym2612.OPN.ST.TA = TAnew;\r
@@ -1171,7 +1177,6 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80)
         }\r
         case 0x26: // timer B\r
           if (ym2612.OPN.ST.TB != d) {\r
-            int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k();\r
             ym2612_sync_timers(cycles, ym2612.OPN.ST.mode, ym2612.OPN.ST.mode);\r
             //elprintf(EL_STATUS, "timer b set %i", d);\r
             ym2612.OPN.ST.TB = d;\r
@@ -1183,7 +1188,6 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80)
           return 0;\r
         case 0x27: { /* mode, timer control */\r
           int old_mode = ym2612.OPN.ST.mode;\r
-          int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k();\r
 \r
           elprintf(EL_YMTIMER, "st mode %02x", d);\r
           ym2612_sync_timers(cycles, old_mode, d);\r
@@ -1208,7 +1212,6 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80)
           return 0;\r
         }\r
         case 0x2a: { /* DAC data */\r
-          int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k();\r
           //elprintf(EL_STATUS, "%03i dac w %08x z80 %i", cycles, d, is_from_z80);\r
           if (ym2612.dacen)\r
             PsndDoDAC(cycles);\r
@@ -1230,7 +1233,7 @@ static int ym2612_write_local(u32 a, u32 d, int is_from_z80)
   if (PicoIn.opt & POPT_EXT_FM)\r
     return YM2612Write_940(a, d, get_scanline(is_from_z80));\r
 #endif\r
-  PsndDoFM(is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k());\r
+  PsndDoFM(cycles);\r
   return YM2612Write_(a, d);\r
 }\r
 \r
index a3c8756..80c00fb 100644 (file)
@@ -457,6 +457,7 @@ struct PicoTiming
 \r
   int timer_a_next_oflow, timer_a_step; // in z80 cycles\r
   int timer_b_next_oflow, timer_b_step;\r
+  int ym2612_busy;\r
 \r
   int vcnt_wrap, vcnt_adj;\r
 };\r
@@ -897,6 +898,8 @@ void ym2612_unpack_state(void);
 #define TIMER_B_TICK_ZCYCLES cycles_68k_to_z80(256LL*16*72*2) // Q8\r
 \r
 #define timers_cycle(ticks) \\r
+  if (Pico.t.ym2612_busy > 0) \\r
+    Pico.t.ym2612_busy -= ticks << 8; \\r
   if (Pico.t.timer_a_next_oflow < TIMER_NO_OFLOW) \\r
     Pico.t.timer_a_next_oflow -= ticks << 8; \\r
   if (Pico.t.timer_b_next_oflow < TIMER_NO_OFLOW) \\r
@@ -904,6 +907,7 @@ void ym2612_unpack_state(void);
   ym2612_sync_timers(0, ym2612.OPN.ST.mode, ym2612.OPN.ST.mode);\r
 \r
 #define timers_reset() \\r
+  Pico.t.ym2612_busy = 0; \\r
   Pico.t.timer_a_next_oflow = Pico.t.timer_b_next_oflow = TIMER_NO_OFLOW; \\r
   Pico.t.timer_a_step = TIMER_A_TICK_ZCYCLES * 1024; \\r
   Pico.t.timer_b_step = TIMER_B_TICK_ZCYCLES * 256; \\r