X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=picodrive.git;a=blobdiff_plain;f=pico%2Fmemory.c;h=fb5fa9be09d0dfc863b241b8571995c708d32de7;hp=e8b65e48e2173b6da44be1e22dd605b1eb352ad0;hb=4f2cdbf551ad1a7f487b65b4754cbf7983e80b8a;hpb=c8d1e9b66255c00a3bef7ca27ae019e3523d7a4b diff --git a/pico/memory.c b/pico/memory.c index e8b65e4..fb5fa9b 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -1,33 +1,185 @@ -// 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. - +/* + * memory handling + * (c) Copyright Dave, 2004 + * (C) notaz, 2006-2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ #include "pico_int.h" +#include "memory.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 +extern unsigned int lastSSRamWrite; // used by serial eeprom code + +uptr m68k_read8_map [0x1000000 >> M68K_MEM_SHIFT]; +uptr m68k_read16_map [0x1000000 >> M68K_MEM_SHIFT]; +uptr m68k_write8_map [0x1000000 >> M68K_MEM_SHIFT]; +uptr m68k_write16_map[0x1000000 >> M68K_MEM_SHIFT]; + +static void xmap_set(uptr *map, int shift, int start_addr, int end_addr, + const void *func_or_mh, int is_func) +{ +#ifdef __clang__ + // workaround bug (segfault) in + // Apple LLVM version 4.2 (clang-425.0.27) (based on LLVM 3.2svn) + volatile #endif + uptr addr = (uptr)func_or_mh; + int mask = (1 << shift) - 1; + int i; -extern unsigned int lastSSRamWrite; // used by serial eeprom code + if ((start_addr & mask) != 0 || (end_addr & mask) != mask) { + elprintf(EL_STATUS|EL_ANOMALY, "xmap_set: tried to map bad range: %06x-%06x", + start_addr, end_addr); + return; + } -#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); + if (addr & 1) { + elprintf(EL_STATUS|EL_ANOMALY, "xmap_set: ptr is not aligned: %08lx", addr); + return; + } + + if (!is_func) + addr -= start_addr; + + for (i = start_addr >> shift; i <= end_addr >> shift; i++) { + map[i] = addr >> 1; + if (is_func) + map[i] |= MAP_FLAG; + } +} + +void z80_map_set(uptr *map, int start_addr, int end_addr, + const void *func_or_mh, int is_func) +{ + xmap_set(map, Z80_MEM_SHIFT, start_addr, end_addr, func_or_mh, is_func); +} + +void cpu68k_map_set(uptr *map, int start_addr, int end_addr, + const void *func_or_mh, int is_func) +{ + xmap_set(map, M68K_MEM_SHIFT, start_addr, end_addr, func_or_mh, is_func); +#ifdef EMU_F68K + // setup FAME fetchmap + if (!is_func) + { + int shiftout = 24 - FAMEC_FETCHBITS; + int i = start_addr >> shiftout; + uptr base = (uptr)func_or_mh - (i << shiftout); + for (; i <= (end_addr >> shiftout); i++) + PicoCpuFM68k.Fetch[i] = base; + } +#endif +} + +// more specialized/optimized function (does same as above) +void cpu68k_map_all_ram(int start_addr, int end_addr, void *ptr, int is_sub) +{ + uptr *r8map, *r16map, *w8map, *w16map; + uptr addr = (uptr)ptr; + int shift = M68K_MEM_SHIFT; + int i; + + if (!is_sub) { + r8map = m68k_read8_map; + r16map = m68k_read16_map; + w8map = m68k_write8_map; + w16map = m68k_write16_map; + } else { + r8map = s68k_read8_map; + r16map = s68k_read16_map; + w8map = s68k_write8_map; + w16map = s68k_write16_map; + } + + addr -= start_addr; + addr >>= 1; + for (i = start_addr >> shift; i <= end_addr >> shift; i++) + r8map[i] = r16map[i] = w8map[i] = w16map[i] = addr; +#ifdef EMU_F68K + // setup FAME fetchmap + { + M68K_CONTEXT *ctx = is_sub ? &PicoCpuFS68k : &PicoCpuFM68k; + int shiftout = 24 - FAMEC_FETCHBITS; + i = start_addr >> shiftout; + addr = (uptr)ptr - (i << shiftout); + for (; i <= (end_addr >> shiftout); i++) + ctx->Fetch[i] = addr; + } #endif +} +static u32 m68k_unmapped_read8(u32 a) +{ + elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc); + return 0; // assume pulldown, as if MegaCD2 was attached +} + +static u32 m68k_unmapped_read16(u32 a) +{ + elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc); + return 0; +} + +static void m68k_unmapped_write8(u32 a, u32 d) +{ + elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); +} + +static void m68k_unmapped_write16(u32 a, u32 d) +{ + elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); +} + +void m68k_map_unmap(int start_addr, int end_addr) +{ +#ifdef __clang__ + // workaround bug (segfault) in + // Apple LLVM version 4.2 (clang-425.0.27) (based on LLVM 3.2svn) + volatile +#endif + uptr addr; + int shift = M68K_MEM_SHIFT; + int i; + + addr = (uptr)m68k_unmapped_read8; + for (i = start_addr >> shift; i <= end_addr >> shift; i++) + m68k_read8_map[i] = (addr >> 1) | MAP_FLAG; + + addr = (uptr)m68k_unmapped_read16; + for (i = start_addr >> shift; i <= end_addr >> shift; i++) + m68k_read16_map[i] = (addr >> 1) | MAP_FLAG; + + addr = (uptr)m68k_unmapped_write8; + for (i = start_addr >> shift; i <= end_addr >> shift; i++) + m68k_write8_map[i] = (addr >> 1) | MAP_FLAG; + + addr = (uptr)m68k_unmapped_write16; + for (i = start_addr >> shift; i <= end_addr >> shift; i++) + m68k_write16_map[i] = (addr >> 1) | MAP_FLAG; +} + +MAKE_68K_READ8(m68k_read8, m68k_read8_map) +MAKE_68K_READ16(m68k_read16, m68k_read16_map) +MAKE_68K_READ32(m68k_read32, m68k_read16_map) +MAKE_68K_WRITE8(m68k_write8, m68k_write8_map) +MAKE_68K_WRITE16(m68k_write16, m68k_write16_map) +MAKE_68K_WRITE32(m68k_write32, m68k_write16_map) + +// ----------------------------------------------------------------- + +static u32 ym2612_read_local_68k(void); +static int ym2612_write_local(u32 a, u32 d, int is_from_z80); +static void z80_mem_setup(void); + +#ifdef _ASM_MEMORY_C +u32 PicoRead8_sram(u32 a); +u32 PicoRead16_sram(u32 a); +#endif #ifdef EMU_CORE_DEBUG u32 lastread_a, lastread_d[16]={0,}, lastwrite_cyc_d[16]={0,}, lastwrite_mus_d[16]={0,}; @@ -44,513 +196,637 @@ void log_io(unsigned int addr, int bits, int rw); #endif #if defined(EMU_C68K) -static __inline int PicoMemBase(u32 pc) +void cyclone_crashed(u32 pc, struct Cyclone *context) { - int membase=0; + elprintf(EL_STATUS|EL_ANOMALY, "%c68k crash detected @ %06x", + context == &PicoCpuCM68k ? 'm' : 's', pc); + context->membase = (u32)Pico.rom; + context->pc = (u32)Pico.rom + Pico.romsize; +} +#endif - if (pc> 2) | (pad & 3); // ?0SA 00DU - return membase; + value |= out_bits & 0x40; + return value; } -#endif - -PICO_INTERNAL u32 PicoCheckPc(u32 pc) +static u32 read_pad_6btn(int i, u32 out_bits) { - u32 ret=0; -#if defined(EMU_C68K) - pc-=PicoCpuCM68k.membase; // Get real pc -// pc&=0xfffffe; - pc&=~1; - if ((pc<<8) == 0) - { - elprintf(EL_STATUS|EL_ANOMALY, "%i:%03i: game crash detected @ %06x\n", - Pico.m.frame_count, Pico.m.scanline, SekPc); - return (int)Pico.rom + Pico.romsize; // common crash condition, may happen with bad ROMs + u32 pad = ~PicoPadInt[i]; // Get inverse of pad MXYZ SACB RLDU + int phase = Pico.m.padTHPhase[i]; + u32 value; + + if (phase == 2 && !(out_bits & 0x40)) { + value = (pad & 0xc0) >> 2; // ?0SA 0000 + goto out; + } + else if(phase == 3) { + if (out_bits & 0x40) + return (pad & 0x30) | ((pad >> 8) & 0xf); // ?1CB MXYZ + else + return ((pad & 0xc0) >> 2) | 0x0f; // ?0SA 1111 + goto out; } - PicoCpuCM68k.membase=PicoMemBase(pc&0x00ffffff); - PicoCpuCM68k.membase-=pc&0xff000000; + if (out_bits & 0x40) // TH + value = pad & 0x3f; // ?1CB RLDU + else + value = ((pad & 0xc0) >> 2) | (pad & 3); // ?0SA 00DU - ret = PicoCpuCM68k.membase+pc; -#endif - return ret; +out: + value |= out_bits & 0x40; + return value; } +static u32 read_nothing(int i, u32 out_bits) +{ + return 0xff; +} + +typedef u32 (port_read_func)(int index, u32 out_bits); -PICO_INTERNAL void PicoInitPc(u32 pc) +static port_read_func *port_readers[3] = { + read_pad_3btn, + read_pad_3btn, + read_nothing +}; + +static NOINLINE u32 port_read(int i) { - PicoCheckPc(pc); + u32 data_reg = Pico.ioports[i + 1]; + u32 ctrl_reg = Pico.ioports[i + 4] | 0x80; + u32 in, out; + + out = data_reg & ctrl_reg; + out |= 0x7f & ~ctrl_reg; // pull-ups + + in = port_readers[i](i, out); + + return (in & ~ctrl_reg) | (data_reg & ctrl_reg); } -#ifndef _ASM_MEMORY_C -PICO_INTERNAL_ASM void PicoMemReset(void) +void PicoSetInputDevice(int port, enum input_device device) { + port_read_func *func; + + if (port < 0 || port > 2) + return; + + switch (device) { + case PICO_INPUT_PAD_3BTN: + func = read_pad_3btn; + break; + + case PICO_INPUT_PAD_6BTN: + func = read_pad_6btn; + break; + + default: + func = read_nothing; + break; + } + + port_readers[port] = func; } -#endif -// ----------------------------------------------------------------- +NOINLINE u32 io_ports_read(u32 a) +{ + u32 d; + a = (a>>1) & 0xf; + switch (a) { + case 0: d = Pico.m.hardware; break; // Hardware value (Version register) + case 1: d = port_read(0); break; + case 2: d = port_read(1); break; + case 3: d = port_read(2); break; + default: d = Pico.ioports[a]; break; // IO ports can be used as RAM + } + return d; +} -int PadRead(int i) +NOINLINE void io_ports_write(u32 a, u32 d) { - int pad,value,data_reg; - pad=~PicoPadInt[i]; // Get inverse of pad MXYZ SACB RLDU - data_reg=Pico.ioports[i+1]; + a = (a>>1) & 0xf; + + // 6 button gamepad: if TH went from 0 to 1, gamepad changes state + if (1 <= a && a <= 2) + { + Pico.m.padDelay[a - 1] = 0; + if (!(Pico.ioports[a] & 0x40) && (d & 0x40)) + Pico.m.padTHPhase[a - 1]++; + } + + // certain IO ports can be used as RAM + Pico.ioports[a] = d; +} - // orr the bits, which are set as output - value = data_reg&(Pico.ioports[i+4]|0x80); +// lame.. +static int z80_cycles_from_68k(void) +{ + return z80_cycle_aim + + cycles_68k_to_z80(SekCyclesDone() - last_z80_sync); +} - if (PicoOpt & POPT_6BTN_PAD) +void NOINLINE ctl_write_z80busreq(u32 d) +{ + d&=1; d^=1; + elprintf(EL_BUSREQ, "set_zrun: %i->%i [%i] @%06x", Pico.m.z80Run, d, SekCyclesDone(), SekPc); + if (d ^ Pico.m.z80Run) { - int phase = Pico.m.padTHPhase[i]; - - if(phase == 2 && !(data_reg&0x40)) { // TH - value|=(pad&0xc0)>>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 (d) + { + z80_cycle_cnt = z80_cycles_from_68k(); + } + else + { + if ((PicoOpt&POPT_EN_Z80) && !Pico.m.z80_reset) { + pprof_start(m68k); + PicoSyncZ80(SekCyclesDone()); + pprof_end_sub(m68k); + } } + Pico.m.z80Run = d; } +} - if(data_reg&0x40) // TH - value|=(pad&0x3f); // ?1CB RLDU - else value|=((pad&0xc0)>>2)|(pad&3); // ?0SA 00DU - - return value; // will mirror later +void NOINLINE ctl_write_z80reset(u32 d) +{ + d&=1; d^=1; + elprintf(EL_BUSREQ, "set_zreset: %i->%i [%i] @%06x", Pico.m.z80_reset, d, SekCyclesDone(), SekPc); + if (d ^ Pico.m.z80_reset) + { + if (d) + { + if ((PicoOpt&POPT_EN_Z80) && Pico.m.z80Run) { + pprof_start(m68k); + PicoSyncZ80(SekCyclesDone()); + pprof_end_sub(m68k); + } + YM2612ResetChip(); + timers_reset(); + } + else + { + z80_cycle_cnt = z80_cycles_from_68k(); + z80_reset(); + } + Pico.m.z80_reset = d; + } } +// ----------------------------------------------------------------- #ifndef _ASM_MEMORY_C -static -#endif -u32 SRAMRead(u32 a) + +// cart (save) RAM area (usually 0x200000 - ...) +static u32 PicoRead8_sram(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 + u32 d; + if (SRam.start <= a && a <= SRam.end && (Pico.m.sram_reg & SRR_MAPPED)) + { + if (SRam.flags & SRF_EEPROM) { + d = EEPROM_read(); + if (!(a & 1)) + d >>= 8; + } else + d = *(u8 *)(SRam.data - SRam.start + a); + elprintf(EL_SRAMIO, "sram r8 [%06x] %02x @ %06x", a, d, SekPc); + return d; } - if (sreg & 4) // EEPROM read - return SRAMReadEEPROM(); - else // if(sreg & 1) // (sreg&5) is one of prerequisites - return *(u8 *)(SRam.data-SRam.start+a); + + // XXX: this is banking unfriendly + if (a < Pico.romsize) + return Pico.rom[a ^ 1]; + + return m68k_unmapped_read8(a); } -#ifndef _ASM_MEMORY_C -static -#endif -u32 SRAMRead16(u32 a) +static u32 PicoRead16_sram(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++; + if (SRam.start <= a && a <= SRam.end && (Pico.m.sram_reg & SRR_MAPPED)) + { + if (SRam.flags & SRF_EEPROM) + d = EEPROM_read(); + else { + u8 *pm = (u8 *)(SRam.data - SRam.start + a); + d = pm[0] << 8; + d |= pm[1]; + } + elprintf(EL_SRAMIO, "sram r16 [%06x] %04x @ %06x", a, d, SekPc); + return d; } - return d; + + if (a < Pico.romsize) + return *(u16 *)(Pico.rom + a); + + return m68k_unmapped_read16(a); } -static void SRAMWrite(u32 a, u32 d) +#endif // _ASM_MEMORY_C + +static void PicoWrite8_sram(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 (a > SRam.end || a < SRam.start || !(Pico.m.sram_reg & SRR_MAPPED)) { + m68k_unmapped_write8(a, d); + return; } - 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) { + + elprintf(EL_SRAMIO, "sram w8 [%06x] %02x @ %06x", a, d & 0xff, SekPc); + if (SRam.flags & SRF_EEPROM) + { + EEPROM_write8(a, d); + } + else { + u8 *pm = (u8 *)(SRam.data - SRam.start + a); + if (*pm != (u8)d) { SRam.changed = 1; - *pm=(u8)d; + *pm = (u8)d; } } } -// for nonstandard reads -static u32 OtherRead16End(u32 a, int realsize) +static void PicoWrite16_sram(u32 a, u32 d) { - u32 d=0; + if (a > SRam.end || a < SRam.start || !(Pico.m.sram_reg & SRR_MAPPED)) { + m68k_unmapped_write16(a, d); + return; + } - // 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; + elprintf(EL_SRAMIO, "sram w16 [%06x] %04x @ %06x", a, d & 0xffff, SekPc); + if (SRam.flags & SRF_EEPROM) + { + EEPROM_write16(d); } - 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 { + u8 *pm = (u8 *)(SRam.data - SRam.start + a); + if (pm[0] != (u8)(d >> 8)) { + SRam.changed = 1; + pm[0] = (u8)(d >> 8); } - else if (*(int *)(Pico.rom+0xf20ec) == 0x30143013 && *(int *)(Pico.rom+0xf20f0) == 0x000f0200) { // Super Mario 2 1998 (Unl) [!] - d=0x0a; goto end; + if (pm[1] != (u8)d) { + SRam.changed = 1; + pm[1] = (u8)d; } } - 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; +} + +// z80 area (0xa00000 - 0xa0ffff) +// TODO: verify mirrors VDP and bank reg (bank area mirroring verified) +static u32 PicoRead8_z80(u32 a) +{ + u32 d = 0xff; + if ((Pico.m.z80Run & 1) || Pico.m.z80_reset) { + elprintf(EL_ANOMALY, "68k z80 read with no bus! [%06x] @ %06x", a, SekPc); + // open bus. Pulled down if MegaCD2 is attached. + return 0; } -end: - elprintf(EL_UIO, "strange r%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc); + if ((a & 0x4000) == 0x0000) + d = Pico.zram[a & 0x1fff]; + else if ((a & 0x6000) == 0x4000) // 0x4000-0x5fff + d = ym2612_read_local_68k(); + else + elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); return d; } +static u32 PicoRead16_z80(u32 a) +{ + u32 d = PicoRead8_z80(a); + return d | (d << 8); +} -//extern UINT32 mz80GetRegisterValue(void *, UINT32); - -static void OtherWrite8End(u32 a,u32 d,int realsize) +static void PicoWrite8_z80(u32 a, u32 d) { - // sram - if(a >= SRam.start && a <= SRam.end) { - elprintf(EL_SRAMIO, "sram w8 [%06x] %02x @ %06x", a, d, SekPc); - SRAMWrite(a, d); + if ((Pico.m.z80Run & 1) || Pico.m.z80_reset) { + // verified on real hw + elprintf(EL_ANOMALY, "68k z80 write with no bus or reset! [%06x] %02x @ %06x", a, d&0xff, SekPc); 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 + if ((a & 0x4000) == 0x0000) { // z80 RAM + SekCyclesBurnRun(2); // FIXME hack + Pico.zram[a & 0x1fff] = (u8)d; 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); + if ((a & 0x6000) == 0x4000) { // FM Sound + if (PicoOpt & POPT_EN_FM) + emustatus |= ym2612_write_local(a&3, d&0xff, 0)&1; 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; + // TODO: probably other VDP access too? Maybe more mirrors? + if ((a & 0x7ff9) == 0x7f11) { // PSG Sound + if (PicoOpt & POPT_EN_PSG) + SN76496Write(d); + return; + } + if ((a & 0x7f00) == 0x6000) // Z80 BANK register + { + Pico.m.z80_bank68k >>= 1; + Pico.m.z80_bank68k |= d << 8; + Pico.m.z80_bank68k &= 0x1ff; // 9 bits and filled in the new top one + elprintf(EL_Z80BNK, "z80 bank=%06x", Pico.m.z80_bank68k << 15); + return; + } + elprintf(EL_UIO|EL_ANOMALY, "68k bad write [%06x] %02x @ %06x", a, d&0xff, SekPc); } -#include "memory_cmn.c" - - -// ----------------------------------------------------------------- -// Read Rom and read Ram - -#ifndef _ASM_MEMORY_C -PICO_INTERNAL_ASM u32 PicoRead8(u32 a) +static void PicoWrite16_z80(u32 a, u32 d) { - u32 d=0; + // for RAM, only most significant byte is sent + // TODO: verify remaining accesses + PicoWrite8_z80(a, d >> 8); +} - if ((a&0xe00000)==0xe00000) { d = *(u8 *)(Pico.ram+((a^1)&0xffff)); goto end; } // Ram +#ifndef _ASM_MEMORY_C - a&=0xffffff; +// IO/control area (0xa10000 - 0xa1ffff) +u32 PicoRead8_io(u32 a) +{ + u32 d; -#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); + if ((a & 0xffe0) == 0x0000) { // I/O ports + d = io_ports_read(a); goto end; } -#endif - if (a>=8; + if ((a & 0xff01) == 0x1100) { // z80 busreq (verified) + d |= (Pico.m.z80Run | Pico.m.z80_reset) & 1; + elprintf(EL_BUSREQ, "get_zrun: %02x [%i] @%06x", d, SekCyclesDone(), SekPc); + } + goto end; + } -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; + if (PicoOpt & POPT_EN_32X) { + d = PicoRead8_32x(a); + goto end; } -#endif + + d = m68k_unmapped_read8(a); +end: return d; } -PICO_INTERNAL_ASM u32 PicoRead16(u32 a) +u32 PicoRead16_io(u32 a) { - u32 d=0; + u32 d; - if ((a&0xe00000)==0xe00000) { d=*(u16 *)(Pico.ram+(a&0xfffe)); goto end; } // Ram + if ((a & 0xffe0) == 0x0000) { // I/O ports + d = io_ports_read(a); + d |= d << 8; + goto end; + } - a&=0xfffffe; + // faking open bus + d = (Pico.m.rotate += 0x41); + d ^= (d << 5) ^ (d << 8); -#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); + // bit8 seems to be readable in this range + if ((a & 0xfc00) == 0x1000) { + d &= ~0x0100; + + if ((a & 0xff00) == 0x1100) { // z80 busreq + d |= ((Pico.m.z80Run | Pico.m.z80_reset) & 1) << 8; + elprintf(EL_BUSREQ, "get_zrun: %04x [%i] @%06x", d, SekCyclesDone(), 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) +void PicoWrite8_io(u32 a, u32 d) { - 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 & 0xffe1) == 0x0001) { // I/O ports (verified: only LSB!) + io_ports_write(a, d); + return; + } + if ((a & 0xff01) == 0x1100) { // z80 busreq + ctl_write_z80busreq(d); + return; + } + if ((a & 0xff01) == 0x1200) { // z80 reset + ctl_write_z80reset(d); + return; + } + if (a == 0xa130f1) { // sram access register + elprintf(EL_SRAMIO, "sram reg=%02x", d); + Pico.m.sram_reg &= ~(SRR_MAPPED|SRR_READONLY); + Pico.m.sram_reg |= (u8)(d & 3); + return; + } + if (PicoOpt & POPT_EN_32X) { + PicoWrite8_32x(a, d); + return; } - if (a=Pico.romsize) { - lastread_a = a; - lastread_d[lrp_cyc++&15] = d; +void PicoWrite16_io(u32 a, u32 d) +{ + if ((a & 0xffe0) == 0x0000) { // I/O ports (verified: only LSB!) + io_ports_write(a, d); + return; } -#endif - return d; + if ((a & 0xff00) == 0x1100) { // z80 busreq + ctl_write_z80busreq(d >> 8); + return; + } + if ((a & 0xff00) == 0x1200) { // z80 reset + ctl_write_z80reset(d >> 8); + return; + } + if (a == 0xa130f0) { // sram access register + elprintf(EL_SRAMIO, "sram reg=%02x", d); + Pico.m.sram_reg &= ~(SRR_MAPPED|SRR_READONLY); + Pico.m.sram_reg |= (u8)(d & 3); + return; + } + if (PicoOpt & POPT_EN_32X) { + PicoWrite16_32x(a, d); + return; + } + m68k_unmapped_write16(a, d); } -#endif -// ----------------------------------------------------------------- -// Write Ram +#endif // _ASM_MEMORY_C -#if !defined(_ASM_MEMORY_C) || defined(_ASM_MEMORY_C_AMIPS) -PICO_INTERNAL_ASM void PicoWrite8(u32 a,u8 d) +// VDP area (0xc00000 - 0xdfffff) +// TODO: verify if lower byte goes to PSG on word writes +static u32 PicoRead8_vdp(u32 a) { - 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); + if ((a & 0x00e0) == 0x0000) + return PicoVideoRead8(a); - a&=0xffffff; - OtherWrite8(a,d); + elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); + return 0; } -#endif -void PicoWrite16(u32 a,u16 d) +static u32 PicoRead16_vdp(u32 a) { - elprintf(EL_IO, "w16: %06x, %04x", a&0xffffff, d); -#ifdef EMU_CORE_DEBUG - lastwrite_cyc_d[lwp_cyc++&15] = d; -#endif + if ((a & 0x00e0) == 0x0000) + return PicoVideoRead(a); - 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); + elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); + return 0; } -static void PicoWrite32(u32 a,u32 d) +static void PicoWrite8_vdp(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; + if ((a & 0x00f9) == 0x0011) { // PSG Sound + if (PicoOpt & POPT_EN_PSG) + SN76496Write(d); return; } - log_io(a, 32, 1); - - a&=0xfffffe; - if ((a&0xe700e0)==0xc00000) - { - // VDP: - PicoVideoWrite(a, (u16)(d>>16)); - PicoVideoWrite(a+2,(u16)d); + if ((a & 0x00e0) == 0x0000) { + d &= 0xff; + PicoVideoWrite(a, d | (d << 8)); return; } - OtherWrite16(a, (u16)(d>>16)); - OtherWrite16(a+2,(u16)d); + elprintf(EL_UIO|EL_ANOMALY, "68k bad write [%06x] %02x @%06x", a, d & 0xff, SekPc); } - -// ----------------------------------------------------------------- - -static void OtherWrite16End(u32 a,u32 d,int realsize) +static void PicoWrite16_vdp(u32 a, u32 d) { - 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; + if ((a & 0x00f9) == 0x0010) { // PSG Sound + if (PicoOpt & POPT_EN_PSG) + SN76496Write(d); + return; + } + if ((a & 0x00e0) == 0x0000) { + PicoVideoWrite(a, d); + return; + } -PICO_INTERNAL void PicoMemResetHooks(void) -{ - // default unmapped/cart specific handlers - PicoRead16Hook = OtherRead16End; - PicoWrite8Hook = OtherWrite8End; - PicoWrite16Hook = OtherWrite16End; + elprintf(EL_UIO|EL_ANOMALY, "68k bad write [%06x] %04x @%06x", a, d & 0xffff, SekPc); } -static void z80_mem_setup(void); +// ----------------------------------------------------------------- + #ifdef EMU_M68K static void m68k_mem_setup(void); #endif PICO_INTERNAL void PicoMemSetup(void) { + int mask, rs, a; + + // setup the memory map + cpu68k_map_set(m68k_read8_map, 0x000000, 0xffffff, m68k_unmapped_read8, 1); + cpu68k_map_set(m68k_read16_map, 0x000000, 0xffffff, m68k_unmapped_read16, 1); + cpu68k_map_set(m68k_write8_map, 0x000000, 0xffffff, m68k_unmapped_write8, 1); + cpu68k_map_set(m68k_write16_map, 0x000000, 0xffffff, m68k_unmapped_write16, 1); + + // ROM + // align to bank size. We know ROM loader allocated enough for this + mask = (1 << M68K_MEM_SHIFT) - 1; + rs = (Pico.romsize + mask) & ~mask; + cpu68k_map_set(m68k_read8_map, 0x000000, rs - 1, Pico.rom, 0); + cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico.rom, 0); + + // Common case of on-cart (save) RAM, usually at 0x200000-... + if ((SRam.flags & SRF_ENABLED) && SRam.data != NULL) { + rs = SRam.end - SRam.start; + rs = (rs + mask) & ~mask; + if (SRam.start + rs >= 0x1000000) + rs = 0x1000000 - SRam.start; + cpu68k_map_set(m68k_read8_map, SRam.start, SRam.start + rs - 1, PicoRead8_sram, 1); + cpu68k_map_set(m68k_read16_map, SRam.start, SRam.start + rs - 1, PicoRead16_sram, 1); + cpu68k_map_set(m68k_write8_map, SRam.start, SRam.start + rs - 1, PicoWrite8_sram, 1); + cpu68k_map_set(m68k_write16_map, SRam.start, SRam.start + rs - 1, PicoWrite16_sram, 1); + } + + // Z80 region + cpu68k_map_set(m68k_read8_map, 0xa00000, 0xa0ffff, PicoRead8_z80, 1); + cpu68k_map_set(m68k_read16_map, 0xa00000, 0xa0ffff, PicoRead16_z80, 1); + cpu68k_map_set(m68k_write8_map, 0xa00000, 0xa0ffff, PicoWrite8_z80, 1); + cpu68k_map_set(m68k_write16_map, 0xa00000, 0xa0ffff, PicoWrite16_z80, 1); + + // IO/control region + cpu68k_map_set(m68k_read8_map, 0xa10000, 0xa1ffff, PicoRead8_io, 1); + cpu68k_map_set(m68k_read16_map, 0xa10000, 0xa1ffff, PicoRead16_io, 1); + cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, PicoWrite8_io, 1); + cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_io, 1); + + // VDP region + for (a = 0xc00000; a < 0xe00000; a += 0x010000) { + if ((a & 0xe700e0) != 0xc00000) + continue; + cpu68k_map_set(m68k_read8_map, a, a + 0xffff, PicoRead8_vdp, 1); + cpu68k_map_set(m68k_read16_map, a, a + 0xffff, PicoRead16_vdp, 1); + cpu68k_map_set(m68k_write8_map, a, a + 0xffff, PicoWrite8_vdp, 1); + cpu68k_map_set(m68k_write16_map, a, a + 0xffff, PicoWrite16_vdp, 1); + } + + // RAM and it's mirrors + for (a = 0xe00000; a < 0x1000000; a += 0x010000) { + cpu68k_map_set(m68k_read8_map, a, a + 0xffff, Pico.ram, 0); + cpu68k_map_set(m68k_read16_map, a, a + 0xffff, Pico.ram, 0); + cpu68k_map_set(m68k_write8_map, a, a + 0xffff, Pico.ram, 0); + cpu68k_map_set(m68k_write16_map, a, a + 0xffff, Pico.ram, 0); + } + // 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; + PicoCpuCM68k.read8 = (void *)m68k_read8_map; + PicoCpuCM68k.read16 = (void *)m68k_read16_map; + PicoCpuCM68k.read32 = (void *)m68k_read16_map; + PicoCpuCM68k.write8 = (void *)m68k_write8_map; + PicoCpuCM68k.write16 = (void *)m68k_write16_map; + PicoCpuCM68k.write32 = (void *)m68k_write16_map; + PicoCpuCM68k.checkpc = NULL; /* unused */ + PicoCpuCM68k.fetch8 = NULL; + PicoCpuCM68k.fetch16 = NULL; + PicoCpuCM68k.fetch32 = NULL; #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; + PicoCpuFM68k.read_byte = m68k_read8; + PicoCpuFM68k.read_word = m68k_read16; + PicoCpuFM68k.read_long = m68k_read32; + PicoCpuFM68k.write_byte = m68k_write8; + PicoCpuFM68k.write_word = m68k_write16; + PicoCpuFM68k.write_long = m68k_write32; // 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)); + for (i = 0; i < M68K_FETCHBANK1 * 0xe0 / 0x100; i++) + PicoCpuFM68k.Fetch[i] = (unsigned long)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)); + PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.rom; + // RAM already set } #endif #ifdef EMU_M68K @@ -560,7 +836,6 @@ PICO_INTERNAL void PicoMemSetup(void) z80_mem_setup(); } -/* 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; @@ -568,103 +843,6 @@ 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 %03i dac w %08x z80 %i", PsndDacLine, scanline, d, is_from_z80); ym2612.dacout = ((int)d - 0x80) << 6; - if (PsndOut && ym2612.dacen && scanline >= PsndDacLine) + if (ym2612.dacen) PsndDoDAC(scanline); return 0; } @@ -795,7 +969,7 @@ int ym2612_write_local(u32 a, u32 d, int is_from_z80) 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()); + int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); 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); @@ -810,7 +984,7 @@ int ym2612_write_local(u32 a, u32 d, int is_from_z80) //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()); + int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); 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); @@ -818,7 +992,7 @@ int ym2612_write_local(u32 a, u32 d, int is_from_z80) 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()); + int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); ym2612.OPN.ST.mode = d; elprintf(EL_YMTIMER, "st mode %02x", d); @@ -842,8 +1016,10 @@ int ym2612_write_local(u32 a, u32 d, int is_from_z80) } case 0x2b: { /* DAC Sel (YM2612) */ int scanline = get_scanline(is_from_z80); - ym2612.dacen = d & 0x80; - if (d & 0x80) PsndDacLine = scanline; + if (ym2612.dacen != (d & 0x80)) { + ym2612.dacen = d & 0x80; + PsndDacLine = scanline; + } #ifdef __GP2X__ if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, scanline); #endif @@ -883,7 +1059,7 @@ int ym2612_write_local(u32 a, u32 d, int is_from_z80) if (xcycles >= timer_b_next_oflow) \ ym2612.OPN.ST.status |= (ym2612.OPN.ST.mode >> 2) & 2 -static u32 MEMH_FUNC ym2612_read_local_z80(void) +static u32 ym2612_read_local_z80(void) { int xcycles = z80_cyclesDone() << 8; @@ -894,9 +1070,9 @@ static u32 MEMH_FUNC ym2612_read_local_z80(void) return ym2612.OPN.ST.status; } -u32 ym2612_read_local_68k(void) +static u32 ym2612_read_local_68k(void) { - int xcycles = cycles_68k_to_z80(SekCyclesDone()) << 8; + int xcycles = z80_cycles_from_68k() << 8; ym2612_read_local(); @@ -978,55 +1154,55 @@ void ym2612_unpack_state(void) elprintf(EL_YMTIMER, "load: %i/%i, timer_b_next_oflow %i", tbt>>16, tbc>>16, timer_b_next_oflow >> 8); } +#if defined(NO_32X) && defined(_ASM_MEMORY_C) +// referenced by asm code +u32 PicoRead8_32x(u32 a) { return 0; } +u32 PicoRead16_32x(u32 a) { return 0; } +void PicoWrite8_32x(u32 a, u32 d) {} +void PicoWrite16_32x(u32 a, u32 d) {} +#endif + // ----------------------------------------------------------------- // z80 memhandlers -static unsigned char MEMH_FUNC z80_md_vdp_read(unsigned short a) +static unsigned char z80_md_vdp_read(unsigned short a) { - // TODO? + if ((a & 0x00e0) == 0x0000) + return PicoVideoRead8(a); // FIXME: depends on 68k cycles + elprintf(EL_ANOMALY, "z80 invalid r8 [%06x] %02x", a, 0xff); return 0xff; } -static unsigned char MEMH_FUNC z80_md_bank_read(unsigned short a) +static unsigned char z80_md_bank_read(unsigned short a) { - extern unsigned int PicoReadM68k8(unsigned int a); unsigned int addr68k; unsigned char ret; addr68k = Pico.m.z80_bank68k<<15; addr68k += a & 0x7fff; - if (addr68k < Pico.romsize) { - ret = Pico.rom[addr68k^1]; - goto out; - } + ret = m68k_read8(addr68k); - elprintf(EL_ANOMALY, "z80->68k upper read [%06x] %02x", addr68k, ret); - if (PicoAHW & PAHW_MCD) - ret = PicoReadM68k8(addr68k); - else ret = PicoRead8(addr68k); - -out: elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret); return ret; } -static void MEMH_FUNC z80_md_ym2612_write(unsigned int a, unsigned char data) +static void z80_md_ym2612_write(unsigned int a, unsigned char data) { if (PicoOpt & POPT_EN_FM) emustatus |= ym2612_write_local(a, data, 1) & 1; } -static void MEMH_FUNC z80_md_vdp_br_write(unsigned int a, unsigned char data) +static void z80_md_vdp_br_write(unsigned int a, unsigned char data) { - // TODO: allow full VDP access if ((a&0xfff9) == 0x7f11) // 7f11 7f13 7f15 7f17 { if (PicoOpt & POPT_EN_PSG) SN76496Write(data); return; } + // at least VDP data writes hang my machine if ((a>>8) == 0x60) { @@ -1039,18 +1215,15 @@ static void MEMH_FUNC z80_md_vdp_br_write(unsigned int a, unsigned char data) elprintf(EL_ANOMALY, "z80 invalid w8 [%06x] %02x", a, data); } -static void MEMH_FUNC z80_md_bank_write(unsigned int a, unsigned char data) +static void z80_md_bank_write(unsigned int a, unsigned char data) { - extern void PicoWriteM68k8(unsigned int a, unsigned char d); unsigned int 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); + m68k_write8(addr68k, data); } // ----------------------------------------------------------------- @@ -1085,10 +1258,11 @@ static void z80_mem_setup(void) drZ80.z80_out = z80_md_out; #endif #ifdef _USE_CZ80 - Cz80_Set_Fetch(&CZ80, 0x0000, 0x1fff, (UINT32)Pico.zram); // main RAM - Cz80_Set_Fetch(&CZ80, 0x2000, 0x3fff, (UINT32)Pico.zram); // mirror + Cz80_Set_Fetch(&CZ80, 0x0000, 0x1fff, (FPTR)Pico.zram); // main RAM + Cz80_Set_Fetch(&CZ80, 0x2000, 0x3fff, (FPTR)Pico.zram); // mirror Cz80_Set_INPort(&CZ80, z80_md_in); Cz80_Set_OUTPort(&CZ80, z80_md_out); #endif } +// vim:shiftwidth=2:ts=2:expandtab