X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=Pico%2FMemory.c;h=e4a251b87af8384219f91bb1cc63d67f3aa6facd;hb=07abbab17a9baab5eeabe30767b0336326049994;hp=45d9fdf899bc84204f09008e78c8fd10f7a905f7;hpb=4b9c58882616c5205a5ad5c9350f20a3d22bd7e1;p=picodrive.git diff --git a/Pico/Memory.c b/Pico/Memory.c index 45d9fdf..e4a251b 100644 --- a/Pico/Memory.c +++ b/Pico/Memory.c @@ -706,6 +706,53 @@ static int get_scanline(int is_from_z80) return vcounts[SekCyclesDone()>>8]; } +/* probably not should be in this file, but it's near related code here */ +void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new) +{ + int xcycles = z80_cycles << 8; + + /* check for overflows */ + if ((mode_old & 4) && xcycles > timer_a_next_oflow) + ym2612.OPN.ST.status |= 1; + + if ((mode_old & 8) && xcycles > timer_b_next_oflow) + ym2612.OPN.ST.status |= 2; + + /* update timer a */ + if (mode_old & 1) + while (xcycles >= timer_a_next_oflow) + timer_a_next_oflow += timer_a_step; + + if ((mode_old ^ mode_new) & 1) // turning on/off + { + if (mode_old & 1) { + timer_a_offset = timer_a_next_oflow - xcycles; + timer_a_next_oflow = 0x70000000; + } + else + timer_a_next_oflow = xcycles + timer_a_offset; + } + if (mode_new & 1) + elprintf(EL_YMTIMER, "timer a upd to %i @ %i", timer_a_next_oflow>>8, z80_cycles); + + /* update timer b */ + if (mode_old & 2) + while (xcycles >= timer_b_next_oflow) + timer_b_next_oflow += timer_b_step; + + if ((mode_old ^ mode_new) & 2) + { + if (mode_old & 2) { + timer_b_offset = timer_b_next_oflow - xcycles; + timer_b_next_oflow = 0x70000000; + } + else + timer_b_next_oflow = xcycles + timer_b_offset; + } + if (mode_new & 2) + elprintf(EL_YMTIMER, "timer b upd to %i @ %i", timer_b_next_oflow>>8, z80_cycles); +} + // ym2612 DAC and timer I/O handlers for z80 int ym2612_write_local(u32 a, u32 d, int is_from_z80) { @@ -749,15 +796,15 @@ int ym2612_write_local(u32 a, u32 d, int is_from_z80) { //elprintf(EL_STATUS, "timer a set %i", TAnew); ym2612.OPN.ST.TA = TAnew; - //ym2612.OPN.ST.TAC = (1024-TAnew)*18; + ym2612.OPN.ST.TAC = (1024-TAnew)*18; //ym2612.OPN.ST.TAT = 0; // - timer_a_step = 16495 * (1024 - TAnew); - if ((ym2612.OPN.ST.mode & 5) == 5) { + timer_a_step = timer_a_offset = 16466 * (1024 - TAnew); + if (ym2612.OPN.ST.mode & 1) { int cycles = is_from_z80 ? z80_cyclesDone() : cycles_68k_to_z80(SekCyclesDone()); timer_a_next_oflow = (cycles << 8) + timer_a_step; - //elprintf(EL_STATUS, "set to %i @ %i", timer_a_next_oflow>>8, cycles); } + elprintf(EL_YMTIMER, "timer a set to %i, %i", 1024 - TAnew, timer_a_next_oflow>>8); } return 0; } @@ -765,39 +812,38 @@ int ym2612_write_local(u32 a, u32 d, int is_from_z80) if (ym2612.OPN.ST.TB != d) { //elprintf(EL_STATUS, "timer b set %i", d); ym2612.OPN.ST.TB = d; - //ym2612.OPN.ST.TBC = (256-d)<<4; - //ym2612.OPN.ST.TBC *= 18; + ym2612.OPN.ST.TBC = (256-d) * 288; //ym2612.OPN.ST.TBT = 0; + timer_b_step = timer_b_offset = 262800 * (256 - d); // 262881 + if (ym2612.OPN.ST.mode & 2) { + int cycles = is_from_z80 ? z80_cyclesDone() : cycles_68k_to_z80(SekCyclesDone()); + timer_b_next_oflow = (cycles << 8) + timer_b_step; + } + elprintf(EL_YMTIMER, "timer b set to %i, %i", 256 - d, timer_b_next_oflow>>8); } return 0; case 0x27: { /* mode, timer control */ int old_mode = ym2612.OPN.ST.mode; - int xcycles = is_from_z80 ? z80_cyclesDone() : cycles_68k_to_z80(SekCyclesDone()); - xcycles <<= 8; + int cycles = is_from_z80 ? z80_cyclesDone() : cycles_68k_to_z80(SekCyclesDone()); + ym2612.OPN.ST.mode = d; - //elprintf(EL_STATUS, "st mode %02x", d); + elprintf(EL_YMTIMER, "st mode %02x", d); + ym2612_sync_timers(cycles, old_mode, d); - if ((ym2612.OPN.ST.mode & 5) != 5 && (d & 5) == 5) { - timer_a_next_oflow = xcycles + timer_a_step; - //elprintf(EL_STATUS, "set to %i @ %i st", timer_a_next_oflow>>8, xcycles >> 8); - } + /* reset Timer a flag */ + if (d & 0x10) + ym2612.OPN.ST.status &= ~1; /* reset Timer b flag */ if (d & 0x20) ym2612.OPN.ST.status &= ~2; - /* reset Timer a flag */ - if (d & 0x10) { - if (ym2612.OPN.ST.status & 1) - while (xcycles > timer_a_next_oflow) - timer_a_next_oflow += timer_a_step; - ym2612.OPN.ST.status &= ~1; - } - if (!(d & 5)) timer_a_next_oflow = 0x80000000; - ym2612.OPN.ST.mode = d; + if ((d ^ old_mode) & 0xc0) { #ifdef __GP2X__ - if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, get_scanline(is_from_z80)); + if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, get_scanline(is_from_z80)); #endif + return 1; + } return 0; } case 0x2b: { /* DAC Sel (YM2612) */ @@ -836,19 +882,69 @@ int ym2612_write_local(u32 a, u32 d, int is_from_z80) return YM2612Write_(a, d); } -// TODO: timer b, 68k side + asm, savestates + +#define ym2612_read_local() \ + if (xcycles >= timer_a_next_oflow) \ + ym2612.OPN.ST.status |= (ym2612.OPN.ST.mode >> 2) & 1; \ + if (xcycles >= timer_b_next_oflow) \ + ym2612.OPN.ST.status |= (ym2612.OPN.ST.mode >> 2) & 2 + u32 ym2612_read_local_z80(void) { int xcycles = z80_cyclesDone() << 8; - if (timer_a_next_oflow != 0x80000000 && xcycles >= timer_a_next_oflow) { - ym2612.OPN.ST.status |= 1; - } - //elprintf(EL_STATUS, "timer %i, sched %i, @ %i|%i", ym2612.OPN.ST.status, timer_a_next_oflow>>8, - // xcycles >> 8, (xcycles >> 8) / 228); + ym2612_read_local(); + + elprintf(EL_YMTIMER, "timer z80 read %i, sched %i, %i @ %i|%i", ym2612.OPN.ST.status, + timer_a_next_oflow>>8, timer_b_next_oflow>>8, xcycles >> 8, (xcycles >> 8) / 228); return ym2612.OPN.ST.status; } +u32 ym2612_read_local_68k(void) +{ + int xcycles = cycles_68k_to_z80(SekCyclesDone()) << 8; + + ym2612_read_local(); + + elprintf(EL_YMTIMER, "timer 68k read %i, sched %i, %i @ %i|%i", ym2612.OPN.ST.status, + timer_a_next_oflow>>8, timer_b_next_oflow>>8, xcycles >> 8, (xcycles >> 8) / 228); + return ym2612.OPN.ST.status; +} + +void ym2612_pack_state(void) +{ + // TODO timers +#ifdef __GP2X__ + if (PicoOpt & POPT_EXT_FM) + /*YM2612PicoStateSave2_940(0, 0)*/; + else +#endif + YM2612PicoStateSave2(0, 0); +} + +void ym2612_unpack_state(void) +{ + int i, ret, tat, tbt; + YM2612PicoStateLoad(); + + // feed all the registers and update internal state + for (i = 0x20; i < 0xB8; i++) { + ym2612_write_local(0, i, 0); + ym2612_write_local(1, ym2612.REGS[i], 0); + } + for (i = 0x30; i < 0xB8; i++) { + ym2612_write_local(2, i, 0); + ym2612_write_local(3, ym2612.REGS[i|0x100], 0); + } + +#ifdef __GP2X__ + if (PicoOpt & POPT_EXT_FM) + /*ret = YM2612PicoStateLoad2_940(&tat, &tbt)*/; + else +#endif + ret = YM2612PicoStateLoad2(&tat, &tbt); +} + // ----------------------------------------------------------------- // z80 memhandlers @@ -869,13 +965,13 @@ PICO_INTERNAL unsigned char z80_read(unsigned short a) addr68k=Pico.m.z80_bank68k<<15; addr68k+=a&0x7fff; + if (addr68k < Pico.romsize) { ret = Pico.rom[addr68k^1]; goto bnkend; } + elprintf(EL_ANOMALY, "z80->68k upper read [%06x] %02x", addr68k, ret); if (PicoAHW & PAHW_MCD) ret = PicoReadM68k8(addr68k); else ret = PicoRead8(addr68k); - if (addr68k >= 0x400000) // not many games do this - { elprintf(EL_ANOMALY, "z80->68k upper read [%06x] %02x", addr68k, ret); } - else - { elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret); } +bnkend: + elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret); return ret; }