X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=Pico%2FMemory.c;fp=Pico%2FMemory.c;h=0000000000000000000000000000000000000000;hb=efcba75f8a730340df6c1b679a207723f98d1ee6;hp=8975fa209b422b1877df01f8d7ec4b5646cfa909;hpb=6a13ef3f56a80ac698d463f5d00235ea2a090f52;p=picodrive.git diff --git a/Pico/Memory.c b/Pico/Memory.c deleted file mode 100644 index 8975fa2..0000000 --- a/Pico/Memory.c +++ /dev/null @@ -1,1071 +0,0 @@ -// This is part of Pico Library - -// (c) Copyright 2004 Dave, All rights reserved. -// (c) Copyright 2006,2007 notaz, All rights reserved. -// Free for non-commercial use. - -// For commercial use, separate licencing terms must be obtained. - - -#include "PicoInt.h" - -#include "sound/ym2612.h" -#include "sound/sn76496.h" - -#ifndef UTYPES_DEFINED -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -#define UTYPES_DEFINED -#endif - -extern unsigned int lastSSRamWrite; // used by serial SRAM code - -#ifdef _ASM_MEMORY_C -u32 PicoRead8(u32 a); -u32 PicoRead16(u32 a); -void PicoWrite8(u32 a,u8 d); -void PicoWriteRomHW_SSF2(u32 a,u32 d); -#endif - - -#ifdef EMU_CORE_DEBUG -u32 lastread_a, lastread_d[16]={0,}, lastwrite_cyc_d[16]={0,}, lastwrite_mus_d[16]={0,}; -int lrp_cyc=0, lrp_mus=0, lwp_cyc=0, lwp_mus=0; -extern unsigned int ppop; -#endif - -#ifdef IO_STATS -void log_io(unsigned int addr, int bits, int rw); -#elif defined(_MSC_VER) -#define log_io -#else -#define log_io(...) -#endif - -#if defined(EMU_C68K) -static __inline int PicoMemBase(u32 pc) -{ - int membase=0; - - if (pc>2; // ?0SA 0000 - return value; - } else if(phase == 3) { - if(data_reg&0x40) - value|=(pad&0x30)|((pad>>8)&0xf); // ?1CB MXYZ - else - value|=((pad&0xc0)>>2)|0x0f; // ?0SA 1111 - return value; - } - } - - if(data_reg&0x40) // TH - value|=(pad&0x3f); // ?1CB RLDU - else value|=((pad&0xc0)>>2)|(pad&3); // ?0SA 00DU - - return value; // will mirror later -} - - -#ifndef _ASM_MEMORY_C -static -#endif -u32 SRAMRead(u32 a) -{ - unsigned int sreg = Pico.m.sram_reg; - if (!(sreg & 0x10) && (sreg & 1) && a > 0x200001) { // not yet detected SRAM - elprintf(EL_SRAMIO, "normal sram detected."); - Pico.m.sram_reg|=0x10; // should be normal SRAM - } - if (sreg & 4) // EEPROM read - return SRAMReadEEPROM(); - else // if(sreg & 1) // (sreg&5) is one of prerequisites - return *(u8 *)(SRam.data-SRam.start+a); -} - -#ifndef _ASM_MEMORY_C -static -#endif -u32 SRAMRead16(u32 a) -{ - u32 d; - if (Pico.m.sram_reg & 4) { - d = SRAMReadEEPROM(); - d |= d << 8; - } else { - u8 *pm=(u8 *)(SRam.data-SRam.start+a); - d =*pm++ << 8; - d|=*pm++; - } - return d; -} - -static void SRAMWrite(u32 a, u32 d) -{ - unsigned int sreg = Pico.m.sram_reg; - if(!(sreg & 0x10)) { - // not detected SRAM - if((a&~1)==0x200000) { - elprintf(EL_SRAMIO, "eeprom detected."); - sreg|=4; // this should be a game with EEPROM (like NBA Jam) - SRam.start=0x200000; SRam.end=SRam.start+1; - } else - elprintf(EL_SRAMIO, "normal sram detected."); - sreg|=0x10; - Pico.m.sram_reg=sreg; - } - if(sreg & 4) { // EEPROM write - // this diff must be at most 16 for NBA Jam to work - if(SekCyclesDoneT()-lastSSRamWrite < 16) { - // just update pending state - elprintf(EL_EEPROM, "eeprom: skip because cycles=%i", SekCyclesDoneT()-lastSSRamWrite); - SRAMUpdPending(a, d); - } else { - int old=sreg; - SRAMWriteEEPROM(sreg>>6); // execute pending - SRAMUpdPending(a, d); - if ((old^Pico.m.sram_reg)&0xc0) // update time only if SDA/SCL changed - lastSSRamWrite = SekCyclesDoneT(); - } - } else if(!(sreg & 2)) { - u8 *pm=(u8 *)(SRam.data-SRam.start+a); - if(*pm != (u8)d) { - SRam.changed = 1; - *pm=(u8)d; - } - } -} - -// for nonstandard reads -static u32 OtherRead16End(u32 a, int realsize) -{ - u32 d=0; - - // 32x test -/* - if (a == 0xa130ec) { d = 0x4d41; goto end; } // MA - else if (a == 0xa130ee) { d = 0x5253; goto end; } // RS - else if (a == 0xa15100) { d = 0x0080; goto end; } - else -*/ - - // for games with simple protection devices, discovered by Haze - // some dumb detection is used, but that should be enough to make things work - if ((a>>22) == 1 && Pico.romsize >= 512*1024) { - if (*(int *)(Pico.rom+0x123e4) == 0x00550c39 && *(int *)(Pico.rom+0x123e8) == 0x00000040) { // Super Bubble Bobble (Unl) [!] - if (a == 0x400000) { d=0x55<<8; goto end; } - else if (a == 0x400002) { d=0x0f<<8; goto end; } - } - else if (*(int *)(Pico.rom+0x008c4) == 0x66240055 && *(int *)(Pico.rom+0x008c8) == 0x00404df9) { // Smart Mouse (Unl) - if (a == 0x400000) { d=0x55<<8; goto end; } - else if (a == 0x400002) { d=0x0f<<8; goto end; } - else if (a == 0x400004) { d=0xaa<<8; goto end; } - else if (a == 0x400006) { d=0xf0<<8; goto end; } - } - else if (*(int *)(Pico.rom+0x00404) == 0x00a90600 && *(int *)(Pico.rom+0x00408) == 0x6708b013) { // King of Fighters '98, The (Unl) [!] - if (a == 0x480000 || a == 0x4800e0 || a == 0x4824a0 || a == 0x488880) { d=0xaa<<8; goto end; } - else if (a == 0x4a8820) { d=0x0a<<8; goto end; } - // there is also a read @ 0x4F8820 which needs 0, but that is returned in default case - } - else if (*(int *)(Pico.rom+0x01b24) == 0x004013f9 && *(int *)(Pico.rom+0x01b28) == 0x00ff0000) { // Mahjong Lover (Unl) [!] - if (a == 0x400000) { d=0x90<<8; goto end; } - else if (a == 0x401000) { d=0xd3<<8; goto end; } // this one doesn't seem to be needed, the code does 2 comparisons and only then - // checks the result, which is of the above one. Left it just in case. - } - else if (*(int *)(Pico.rom+0x05254) == 0x0c3962d0 && *(int *)(Pico.rom+0x05258) == 0x00400055) { // Elf Wor (Unl) - if (a == 0x400000) { d=0x55<<8; goto end; } - else if (a == 0x400004) { d=0xc9<<8; goto end; } // this check is done if the above one fails - else if (a == 0x400002) { d=0x0f<<8; goto end; } - else if (a == 0x400006) { d=0x18<<8; goto end; } // similar to above - } - // our default behaviour is to return whatever was last written a 0x400000-0x7fffff range (used by Squirrel King (R) [!]) - // Lion King II, The (Unl) [!] writes @ 400000 and wants to get that val @ 400002 and wites another val - // @ 400004 which is expected @ 400006, so we really remember 2 values here - d = Pico.m.prot_bytes[(a>>2)&1]<<8; - } - else if (a == 0xa13000 && Pico.romsize >= 1024*1024) { - if (*(int *)(Pico.rom+0xc8af0) == 0x30133013 && *(int *)(Pico.rom+0xc8af4) == 0x000f0240) { // Rockman X3 (Unl) [!] - d=0x0c; goto end; - } - else if (*(int *)(Pico.rom+0x28888) == 0x07fc0000 && *(int *)(Pico.rom+0x2888c) == 0x4eb94e75) { // Bug's Life, A (Unl) [!] - d=0x28; goto end; // does the check from RAM - } - else if (*(int *)(Pico.rom+0xc8778) == 0x30133013 && *(int *)(Pico.rom+0xc877c) == 0x000f0240) { // Super Mario Bros. (Unl) [!] - d=0x0c; goto end; // seems to be the same code as in Rockman X3 (Unl) [!] - } - else if (*(int *)(Pico.rom+0xf20ec) == 0x30143013 && *(int *)(Pico.rom+0xf20f0) == 0x000f0200) { // Super Mario 2 1998 (Unl) [!] - d=0x0a; goto end; - } - } - else if (a == 0xa13002) { // Pocket Monsters (Unl) - d=0x01; goto end; - } - else if (a == 0xa1303E) { // Pocket Monsters (Unl) - d=0x1f; goto end; - } - else if (a == 0x30fe02) { - // Virtua Racing - just for fun - // this seems to be some flag that SVP is ready or something similar - d=1; goto end; - } - -end: - elprintf(EL_UIO, "strange r%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc); - return d; -} - - -//extern UINT32 mz80GetRegisterValue(void *, UINT32); - -static void OtherWrite8End(u32 a,u32 d,int realsize) -{ - // sram - if(a >= SRam.start && a <= SRam.end) { - elprintf(EL_SRAMIO, "sram w8 [%06x] %02x @ %06x", a, d, SekPc); - SRAMWrite(a, d); - return; - } - -#ifdef _ASM_MEMORY_C - // special ROM hardware (currently only banking and sram reg supported) - if((a&0xfffff1) == 0xA130F1) { - PicoWriteRomHW_SSF2(a, d); // SSF2 or SRAM - return; - } -#else - // sram access register - if(a == 0xA130F1) { - elprintf(EL_SRAMIO, "sram reg=%02x", d); - Pico.m.sram_reg &= ~3; - Pico.m.sram_reg |= (u8)(d&3); - return; - } -#endif - elprintf(EL_UIO, "strange w%i: %06x, %08x @%06x", realsize, a&0xffffff, d, SekPc); - - // for games with simple protection devices, discovered by Haze - if ((a>>22) == 1) - Pico.m.prot_bytes[(a>>2)&1] = (u8)d; -} - -#include "MemoryCmn.c" - - -// ----------------------------------------------------------------- -// Read Rom and read Ram - -#ifndef _ASM_MEMORY_C -PICO_INTERNAL_ASM u32 PicoRead8(u32 a) -{ - u32 d=0; - - if ((a&0xe00000)==0xe00000) { d = *(u8 *)(Pico.ram+((a^1)&0xffff)); goto end; } // Ram - - a&=0xffffff; - -#ifndef EMU_CORE_DEBUG - // sram - if (a >= SRam.start && a <= SRam.end && (Pico.m.sram_reg&5)) { - d = SRAMRead(a); - elprintf(EL_SRAMIO, "sram r8 [%06x] %02x @ %06x", a, d, SekPc); - goto end; - } -#endif - - if (a>=8; - -end: - elprintf(EL_IO, "r8 : %06x, %02x @%06x", a&0xffffff, (u8)d, SekPc); -#ifdef EMU_CORE_DEBUG - if (a>=Pico.romsize) { - lastread_a = a; - lastread_d[lrp_cyc++&15] = (u8)d; - } -#endif - return d; -} - -PICO_INTERNAL_ASM u32 PicoRead16(u32 a) -{ - u32 d=0; - - if ((a&0xe00000)==0xe00000) { d=*(u16 *)(Pico.ram+(a&0xfffe)); goto end; } // Ram - - a&=0xfffffe; - -#ifndef EMU_CORE_DEBUG - // sram - if (a >= SRam.start && a <= SRam.end && (Pico.m.sram_reg&5)) { - d = SRAMRead16(a); - elprintf(EL_SRAMIO, "sram r16 [%06x] %04x @ %06x", a, d, SekPc); - goto end; - } -#endif - - if (a=Pico.romsize) { - lastread_a = a; - lastread_d[lrp_cyc++&15] = d; - } -#endif - return d; -} - -PICO_INTERNAL_ASM u32 PicoRead32(u32 a) -{ - u32 d=0; - - if ((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); d = (pm[0]<<16)|pm[1]; goto end; } // Ram - - a&=0xfffffe; - - // sram - if(a >= SRam.start && a <= SRam.end && (Pico.m.sram_reg&5)) { - d = (SRAMRead16(a)<<16)|SRAMRead16(a+2); - elprintf(EL_SRAMIO, "sram r32 [%06x] %08x @ %06x", a, d, SekPc); - goto end; - } - - if (a=Pico.romsize) { - lastread_a = a; - lastread_d[lrp_cyc++&15] = d; - } -#endif - return d; -} -#endif - -// ----------------------------------------------------------------- -// Write Ram - -#if !defined(_ASM_MEMORY_C) || defined(_ASM_MEMORY_C_AMIPS) -PICO_INTERNAL_ASM void PicoWrite8(u32 a,u8 d) -{ - elprintf(EL_IO, "w8 : %06x, %02x @%06x", a&0xffffff, d, SekPc); -#ifdef EMU_CORE_DEBUG - lastwrite_cyc_d[lwp_cyc++&15] = d; -#endif - - if ((a&0xe00000)==0xe00000) { *(u8 *)(Pico.ram+((a^1)&0xffff))=d; return; } // Ram - log_io(a, 8, 1); - - a&=0xffffff; - OtherWrite8(a,d); -} -#endif - -void PicoWrite16(u32 a,u16 d) -{ - elprintf(EL_IO, "w16: %06x, %04x", a&0xffffff, d); -#ifdef EMU_CORE_DEBUG - lastwrite_cyc_d[lwp_cyc++&15] = d; -#endif - - if ((a&0xe00000)==0xe00000) { *(u16 *)(Pico.ram+(a&0xfffe))=d; return; } // Ram - log_io(a, 16, 1); - - a&=0xfffffe; - if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)d); return; } // VDP - OtherWrite16(a,d); -} - -static void PicoWrite32(u32 a,u32 d) -{ - elprintf(EL_IO, "w32: %06x, %08x @%06x", a&0xffffff, d, SekPc); -#ifdef EMU_CORE_DEBUG - lastwrite_cyc_d[lwp_cyc++&15] = d; -#endif - - if ((a&0xe00000)==0xe00000) - { - // Ram: - u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); - pm[0]=(u16)(d>>16); pm[1]=(u16)d; - return; - } - log_io(a, 32, 1); - - a&=0xfffffe; - if ((a&0xe700e0)==0xc00000) - { - // VDP: - PicoVideoWrite(a, (u16)(d>>16)); - PicoVideoWrite(a+2,(u16)d); - return; - } - - OtherWrite16(a, (u16)(d>>16)); - OtherWrite16(a+2,(u16)d); -} - - -// ----------------------------------------------------------------- - -static void OtherWrite16End(u32 a,u32 d,int realsize) -{ - PicoWrite8Hook(a, d>>8, realsize); - PicoWrite8Hook(a+1,d&0xff, realsize); -} - -u32 (*PicoRead16Hook) (u32 a, int realsize) = OtherRead16End; -void (*PicoWrite8Hook) (u32 a, u32 d, int realsize) = OtherWrite8End; -void (*PicoWrite16Hook)(u32 a, u32 d, int realsize) = OtherWrite16End; - -PICO_INTERNAL void PicoMemResetHooks(void) -{ - // default unmapped/cart specific handlers - PicoRead16Hook = OtherRead16End; - PicoWrite8Hook = OtherWrite8End; - PicoWrite16Hook = OtherWrite16End; -} - -#ifdef EMU_M68K -static void m68k_mem_setup(void); -#endif - -PICO_INTERNAL void PicoMemSetup(void) -{ - // Setup memory callbacks: -#ifdef EMU_C68K - PicoCpuCM68k.checkpc=PicoCheckPc; - PicoCpuCM68k.fetch8 =PicoCpuCM68k.read8 =PicoRead8; - PicoCpuCM68k.fetch16=PicoCpuCM68k.read16=PicoRead16; - PicoCpuCM68k.fetch32=PicoCpuCM68k.read32=PicoRead32; - PicoCpuCM68k.write8 =PicoWrite8; - PicoCpuCM68k.write16=PicoWrite16; - PicoCpuCM68k.write32=PicoWrite32; -#endif -#ifdef EMU_F68K - PicoCpuFM68k.read_byte =PicoRead8; - PicoCpuFM68k.read_word =PicoRead16; - PicoCpuFM68k.read_long =PicoRead32; - PicoCpuFM68k.write_byte=PicoWrite8; - PicoCpuFM68k.write_word=PicoWrite16; - PicoCpuFM68k.write_long=PicoWrite32; - - // setup FAME fetchmap - { - int i; - // by default, point everything to first 64k of ROM - for (i = 0; i < M68K_FETCHBANK1; i++) - PicoCpuFM68k.Fetch[i] = (unsigned int)Pico.rom - (i<<(24-FAMEC_FETCHBITS)); - // now real ROM - for (i = 0; i < M68K_FETCHBANK1 && (i<<(24-FAMEC_FETCHBITS)) < Pico.romsize; i++) - PicoCpuFM68k.Fetch[i] = (unsigned int)Pico.rom; - // .. and RAM - for (i = M68K_FETCHBANK1*14/16; i < M68K_FETCHBANK1; i++) - PicoCpuFM68k.Fetch[i] = (unsigned int)Pico.ram - (i<<(24-FAMEC_FETCHBITS)); - } -#endif -#ifdef EMU_M68K - m68k_mem_setup(); -#endif -} - -/* some nasty things below :( */ -#ifdef EMU_M68K -unsigned int (*pm68k_read_memory_8) (unsigned int address) = NULL; -unsigned int (*pm68k_read_memory_16)(unsigned int address) = NULL; -unsigned int (*pm68k_read_memory_32)(unsigned int address) = NULL; -void (*pm68k_write_memory_8) (unsigned int address, unsigned char value) = NULL; -void (*pm68k_write_memory_16)(unsigned int address, unsigned short value) = NULL; -void (*pm68k_write_memory_32)(unsigned int address, unsigned int value) = NULL; -unsigned int (*pm68k_read_memory_pcr_8) (unsigned int address) = NULL; -unsigned int (*pm68k_read_memory_pcr_16)(unsigned int address) = NULL; -unsigned int (*pm68k_read_memory_pcr_32)(unsigned int address) = NULL; - -// these are here for core debugging mode -static unsigned int m68k_read_8 (unsigned int a, int do_fake) -{ - a&=0xffffff; - if(a= 228) - z80_scanline++, z80_scanline_cycles += 228; - return z80_scanline; - } - - return Pico.m.scanline; -} - -/* probably should not 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_next_oflow = TIMER_NO_OFLOW; - else - timer_a_next_oflow = xcycles + timer_a_step; - } - 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_next_oflow = TIMER_NO_OFLOW; - else - timer_b_next_oflow = xcycles + timer_b_step; - } - 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) -{ - int addr; - - a &= 3; - if (a == 1 && ym2612.OPN.ST.address == 0x2a) /* DAC data */ - { - int scanline = get_scanline(is_from_z80); - //elprintf(EL_STATUS, "%03i -> %03i dac w %08x z80 %i", PsndDacLine, scanline, d, is_from_z80); - ym2612.dacout = ((int)d - 0x80) << 6; - if (PsndOut && ym2612.dacen && scanline >= PsndDacLine) - PsndDoDAC(scanline); - return 0; - } - - switch (a) - { - case 0: /* address port 0 */ - ym2612.OPN.ST.address = d; - ym2612.addr_A1 = 0; -#ifdef __GP2X__ - if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, -1); -#endif - return 0; - - case 1: /* data port 0 */ - if (ym2612.addr_A1 != 0) - return 0; - - addr = ym2612.OPN.ST.address; - ym2612.REGS[addr] = d; - - switch (addr) - { - case 0x24: // timer A High 8 - case 0x25: { // timer A Low 2 - int TAnew = (addr == 0x24) ? ((ym2612.OPN.ST.TA & 0x03)|(((int)d)<<2)) - : ((ym2612.OPN.ST.TA & 0x3fc)|(d&3)); - if (ym2612.OPN.ST.TA != TAnew) - { - //elprintf(EL_STATUS, "timer a set %i", TAnew); - ym2612.OPN.ST.TA = TAnew; - //ym2612.OPN.ST.TAC = (1024-TAnew)*18; - //ym2612.OPN.ST.TAT = 0; - timer_a_step = TIMER_A_TICK_ZCYCLES * (1024 - TAnew); - if (ym2612.OPN.ST.mode & 1) { - // this is not right, should really be done on overflow only - int cycles = is_from_z80 ? z80_cyclesDone() : cycles_68k_to_z80(SekCyclesDone()); - timer_a_next_oflow = (cycles << 8) + timer_a_step; - } - elprintf(EL_YMTIMER, "timer a set to %i, %i", 1024 - TAnew, timer_a_next_oflow>>8); - } - return 0; - } - case 0x26: // timer B - 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) * 288; - //ym2612.OPN.ST.TBT = 0; - timer_b_step = TIMER_B_TICK_ZCYCLES * (256 - d); // 262800 - 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 cycles = is_from_z80 ? z80_cyclesDone() : cycles_68k_to_z80(SekCyclesDone()); - ym2612.OPN.ST.mode = d; - - elprintf(EL_YMTIMER, "st mode %02x", d); - ym2612_sync_timers(cycles, old_mode, d); - - /* reset Timer a flag */ - if (d & 0x10) - ym2612.OPN.ST.status &= ~1; - - /* reset Timer b flag */ - if (d & 0x20) - ym2612.OPN.ST.status &= ~2; - - if ((d ^ old_mode) & 0xc0) { -#ifdef __GP2X__ - if (PicoOpt & POPT_EXT_FM) return YM2612Write_940(a, d, get_scanline(is_from_z80)); -#endif - return 1; - } - return 0; - } - case 0x2b: { /* DAC Sel (YM2612) */ - int scanline = get_scanline(is_from_z80); - ym2612.dacen = d & 0x80; - if (d & 0x80) PsndDacLine = scanline; -#ifdef __GP2X__ - if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, scanline); -#endif - return 0; - } - } - break; - - case 2: /* address port 1 */ - ym2612.OPN.ST.address = d; - ym2612.addr_A1 = 1; -#ifdef __GP2X__ - if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, -1); -#endif - return 0; - - case 3: /* data port 1 */ - if (ym2612.addr_A1 != 1) - return 0; - - addr = ym2612.OPN.ST.address | 0x100; - ym2612.REGS[addr] = d; - break; - } - -#ifdef __GP2X__ - if (PicoOpt & POPT_EXT_FM) - return YM2612Write_940(a, d, get_scanline(is_from_z80)); -#endif - return YM2612Write_(a, d); -} - - -#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; - - 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) -{ - // timers are saved as tick counts, in 16.16 int format - int tac, tat = 0, tbc, tbt = 0; - tac = 1024 - ym2612.OPN.ST.TA; - tbc = 256 - ym2612.OPN.ST.TB; - if (timer_a_next_oflow != TIMER_NO_OFLOW) - tat = (int)((double)(timer_a_step - timer_a_next_oflow) / (double)timer_a_step * tac * 65536); - if (timer_b_next_oflow != TIMER_NO_OFLOW) - tbt = (int)((double)(timer_b_step - timer_b_next_oflow) / (double)timer_b_step * tbc * 65536); - elprintf(EL_YMTIMER, "save: timer a %i/%i", tat >> 16, tac); - elprintf(EL_YMTIMER, "save: timer b %i/%i", tbt >> 16, tbc); - -#ifdef __GP2X__ - if (PicoOpt & POPT_EXT_FM) - YM2612PicoStateSave2_940(tat, tbt); - else -#endif - YM2612PicoStateSave2(tat, tbt); -} - -void ym2612_unpack_state(void) -{ - int i, ret, tac, tat, tbc, tbt; - YM2612PicoStateLoad(); - - // feed all the registers and update internal state - for (i = 0x20; i < 0xA0; i++) { - ym2612_write_local(0, i, 0); - ym2612_write_local(1, ym2612.REGS[i], 0); - } - for (i = 0x30; i < 0xA0; i++) { - ym2612_write_local(2, i, 0); - ym2612_write_local(3, ym2612.REGS[i|0x100], 0); - } - for (i = 0xAF; i >= 0xA0; i--) { // must apply backwards - ym2612_write_local(2, i, 0); - ym2612_write_local(3, ym2612.REGS[i|0x100], 0); - ym2612_write_local(0, i, 0); - ym2612_write_local(1, ym2612.REGS[i], 0); - } - for (i = 0xB0; i < 0xB8; i++) { - ym2612_write_local(0, i, 0); - ym2612_write_local(1, ym2612.REGS[i], 0); - 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); - if (ret != 0) { - elprintf(EL_STATUS, "old ym2612 state"); - return; // no saved timers - } - - tac = (1024 - ym2612.OPN.ST.TA) << 16; - tbc = (256 - ym2612.OPN.ST.TB) << 16; - if (ym2612.OPN.ST.mode & 1) - timer_a_next_oflow = (int)((double)(tac - tat) / (double)tac * timer_a_step); - else - timer_a_next_oflow = TIMER_NO_OFLOW; - if (ym2612.OPN.ST.mode & 2) - timer_b_next_oflow = (int)((double)(tbc - tbt) / (double)tbc * timer_b_step); - else - timer_b_next_oflow = TIMER_NO_OFLOW; - elprintf(EL_YMTIMER, "load: %i/%i, timer_a_next_oflow %i", tat>>16, tac>>16, timer_a_next_oflow >> 8); - elprintf(EL_YMTIMER, "load: %i/%i, timer_b_next_oflow %i", tbt>>16, tbc>>16, timer_b_next_oflow >> 8); -} - -// ----------------------------------------------------------------- -// z80 memhandlers - -PICO_INTERNAL unsigned char z80_read(unsigned short a) -{ - u8 ret = 0; - - if ((a>>13)==2) // 0x4000-0x5fff (Charles MacDonald) - { - return ym2612_read_local_z80(); - } - - if (a>=0x8000) - { - extern u32 PicoReadM68k8(u32 a); - u32 addr68k; - 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); -bnkend: - elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret); - return ret; - } - - // should not be needed, cores should be able to access RAM themselves - if (a<0x4000) return Pico.zram[a&0x1fff]; - - elprintf(EL_ANOMALY, "z80 invalid r8 [%06x] %02x", a, ret); - return ret; -} - -#ifndef _USE_CZ80 -PICO_INTERNAL_ASM void z80_write(unsigned char data, unsigned short a) -#else -PICO_INTERNAL_ASM void z80_write(unsigned int a, unsigned char data) -#endif -{ - if ((a>>13)==2) // 0x4000-0x5fff (Charles MacDonald) - { - if(PicoOpt&POPT_EN_FM) emustatus|=ym2612_write_local(a, data, 1) & 1; - return; - } - - if ((a&0xfff9)==0x7f11) // 7f11 7f13 7f15 7f17 - { - if(PicoOpt&POPT_EN_PSG) SN76496Write(data); - return; - } - - if ((a>>8)==0x60) - { - Pico.m.z80_bank68k>>=1; - Pico.m.z80_bank68k|=(data&1)<<8; - Pico.m.z80_bank68k&=0x1ff; // 9 bits and filled in the new top one - return; - } - - if (a>=0x8000) - { - extern void PicoWriteM68k8(u32 a,u8 d); - u32 addr68k; - addr68k=Pico.m.z80_bank68k<<15; - addr68k+=a&0x7fff; - elprintf(EL_Z80BNK, "z80->68k w8 [%06x] %02x", addr68k, data); - if (PicoAHW & PAHW_MCD) - PicoWriteM68k8(addr68k, data); - else PicoWrite8(addr68k, data); - return; - } - - // should not be needed - if (a<0x4000) { Pico.zram[a&0x1fff]=data; return; } - - elprintf(EL_ANOMALY, "z80 invalid w8 [%06x] %02x", a, data); -} - -#ifndef _USE_CZ80 -PICO_INTERNAL unsigned short z80_read16(unsigned short a) -{ - return (u16) ( (u16)z80_read(a) | ((u16)z80_read((u16)(a+1))<<8) ); -} - -PICO_INTERNAL void z80_write16(unsigned short data, unsigned short a) -{ - z80_write((unsigned char) data,a); - z80_write((unsigned char)(data>>8),(u16)(a+1)); -} -#endif -