/**************************************************************************** * Genesis Plus * Action Replay / Pro Action Replay emulation * * Copyright (C) 2009-2011 Eke-Eke (Genesis Plus GX) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: * * - Redistributions may not be sold, nor may they be used in a commercial * product or activity. * * - Redistributions that are modified from the original source must include the * complete source code, including the source code for all components used by a * binary built from the modified sources. However, as a special exception, the * source code distributed need not include anything that is normally distributed * (in either source or binary form) with the major components (compiler, kernel, * and so on) of the operating system on which the executable runs, unless that * component itself accompanies the executable. * * - Redistributions must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************************/ #include "shared.h" #define TYPE_PRO1 0x12 #define TYPE_PRO2 0x22 static struct { uint8 enabled; uint8 status; uint8 *rom; uint8 *ram; uint16 regs[13]; uint16 old[4]; uint16 data[4]; uint32 addr[4]; } action_replay; static void ar_write_regs(uint32 address, uint32 data); static void ar_write_regs_2(uint32 address, uint32 data); static void ar_write_ram_8(uint32 address, uint32 data); void areplay_init(void) { int size; FILE *f; memset(&action_replay,0,sizeof(action_replay)); /* store Action replay ROM (max. 128k) & RAM (64k) above cartridge ROM + SRAM area */ if (cart.romsize > 0x810000) return; action_replay.rom = cart.rom + 0x810000; action_replay.ram = cart.rom + 0x830000; /* Open Action Replay ROM */ f = fopen(AR_ROM,"rb"); if (f == NULL) return; /* ROM size */ fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); /* detect Action Replay board type */ switch (size) { case 0x8000: { /* normal Action Replay (32K) */ action_replay.enabled = TYPE_AR; /* internal registers mapped at $010000-$01ffff */ m68k.memory_map[0x01].write16 = ar_write_regs; break; } case 0x10000: case 0x20000: { /* read Stack Pointer */ uint8 sp[4]; fread(&sp, 4, 1, f); fseek(f, 0, SEEK_SET); /* Detect board version */ if (sp[1] == 0x42) { /* PRO Action Replay 1 (64/128K) */ action_replay.enabled = TYPE_PRO1; /* internal registers mapped at $010000-$01ffff */ m68k.memory_map[0x01].write16 = ar_write_regs; } else if (sp[1] == 0x60) { /* PRO Action Replay 2 (64K) */ action_replay.enabled = TYPE_PRO2; /* internal registers mapped at $100000-$10ffff */ m68k.memory_map[0x10].write16 = ar_write_regs_2; } /* internal RAM (64k), mapped at $420000-$42ffff or $600000-$60ffff */ if (action_replay.enabled) { m68k.memory_map[sp[1]].base = action_replay.ram; m68k.memory_map[sp[1]].read8 = NULL; m68k.memory_map[sp[1]].read16 = NULL; m68k.memory_map[sp[1]].write8 = ar_write_ram_8; m68k.memory_map[sp[1]].write16 = NULL; } break; } default: { break; } } if (action_replay.enabled) { /* Load ROM */ int i = 0; for (i=0; i> 1; if (offset > 12) { m68k_unused_16_w(address,data); return; } /* update internal register */ action_replay.regs[offset] = data; /* MODE register */ if (action_replay.regs[3] == 0xffff) { /* check switch status */ if (action_replay.status == AR_SWITCH_ON) { /* reset existing patches */ areplay_set_status(AR_SWITCH_OFF); areplay_set_status(AR_SWITCH_ON); } /* enable Cartridge ROM */ m68k.memory_map[0].base = cart.rom; } } static void ar_write_regs_2(uint32 address, uint32 data) { /* enable Cartridge ROM */ if (((address & 0xff) == 0x78) && (data == 0xffff)) { m68k.memory_map[0].base = cart.rom; } } static void ar_write_ram_8(uint32 address, uint32 data) { /* byte writes are handled as word writes, with LSB duplicated in MSB (/LWR is not used) */ *(uint16 *)(action_replay.ram + (address & 0xfffe)) = (data | (data << 8)); }