/***************************************************************************************1* Genesis Plus2* CD compatible ROM/RAM cartridge support3*4* Copyright (C) 2012 Eke-Eke (Genesis Plus GX)5*6* Redistribution and use of this code or any derivative works are permitted7* provided that the following conditions are met:8*9* - Redistributions may not be sold, nor may they be used in a commercial10* product or activity.11*12* - Redistributions that are modified from the original source must include the13* complete source code, including the source code for all components used by a14* binary built from the modified sources. However, as a special exception, the15* source code distributed need not include anything that is normally distributed16* (in either source or binary form) with the major components (compiler, kernel,17* and so on) of the operating system on which the executable runs, unless that18* component itself accompanies the executable.19*20* - Redistributions must reproduce the above copyright notice, this list of21* conditions and the following disclaimer in the documentation and/or other22* materials provided with the distribution.23*24* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"25* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE26* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE27* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE28* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR29* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF30* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN32* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)33* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE34* POSSIBILITY OF SUCH DAMAGE.35*36****************************************************************************************/3738#include "shared.h"394041/*--------------------------------------------------------------------------*/42/* backup RAM cartridge (max. 512KB) */43/*--------------------------------------------------------------------------*/44static unsigned int cart_ram_read_byte(unsigned int address)45{46/* LSB only */47if (address & 1)48{49return scd.cartridge.area[(address >> 1) & scd.cartridge.mask];50}5152return 0xff;53}5455static unsigned int cart_ram_read_word(unsigned int address)56{57return (scd.cartridge.area[(address >> 1) & scd.cartridge.mask] | 0xff00);58}5960static void cart_ram_write_byte(unsigned int address, unsigned int data)61{62/* LSB only */63if (address & 1)64{65scd.cartridge.area[(address >> 1) & scd.cartridge.mask] = data;66}67}6869static void cart_ram_write_word(unsigned int address, unsigned int data)70{71scd.cartridge.area[(address >> 1) & scd.cartridge.mask] = data & 0xff;72}737475/*--------------------------------------------------------------------------*/76/* backup RAM cartridge ID */77/*--------------------------------------------------------------------------*/7879static unsigned int cart_id_read_byte(unsigned int address)80{81/* LSB only */82if (address & 1)83{84return scd.cartridge.id;85}8687return 0xff;88}8990static unsigned int cart_id_read_word(unsigned int address)91{92return (scd.cartridge.id | 0xff00);93}949596/*--------------------------------------------------------------------------*/97/* backup RAM cartridge write protection */98/*--------------------------------------------------------------------------*/99100static unsigned int cart_prot_read_byte(unsigned int address)101{102/* LSB only */103if (address & 1)104{105return scd.cartridge.prot;106}107108return 0xff;109}110111static unsigned int cart_prot_read_word(unsigned int address)112{113return (scd.cartridge.prot | 0xff00);114}115116static void cart_prot_write_byte(unsigned int address, unsigned int data)117{118/* LSB only */119if (address & 1)120{121int i;122123if (data & 1)124{125/* cartridge is write enabled */126for (i=0x60; i<0x70; i++)127{128m68k.memory_map[i].write8 = cart_ram_write_byte;129m68k.memory_map[i].write16 = cart_ram_write_word;130zbank_memory_map[i].write = cart_ram_write_byte;131}132}133else134{135/* cartridge is write protected */136for (i=0x60; i<0x70; i++)137{138m68k.memory_map[i].write8 = m68k_unused_8_w;139m68k.memory_map[i].write16 = m68k_unused_16_w;140zbank_memory_map[i].write = zbank_unused_w;141}142}143144scd.cartridge.prot = data;145}146}147148static void cart_prot_write_word(unsigned int address, unsigned int data)149{150int i;151152if (data & 1)153{154/* cartridge is write enabled */155for (i=0x60; i<0x70; i++)156{157m68k.memory_map[i].write8 = cart_ram_write_byte;158m68k.memory_map[i].write16 = cart_ram_write_word;159zbank_memory_map[i].write = cart_ram_write_byte;160}161}162else163{164/* cartridge is write protected */165for (i=0x60; i<0x70; i++)166{167m68k.memory_map[i].write8 = m68k_unused_8_w;168m68k.memory_map[i].write16 = m68k_unused_16_w;169zbank_memory_map[i].write = zbank_unused_w;170}171}172173scd.cartridge.prot = data & 0xff;174}175176/*--------------------------------------------------------------------------*/177/* ROM/RAM cartridge initialization */178/*--------------------------------------------------------------------------*/179void cd_cart_init(void)180{181int i;182183/* System boot mode */184if (scd.cartridge.boot)185{186/* disable backup RAM cartridge when booting from cartridge (Mode 1) */187scd.cartridge.id = 0;188}189else190{191/* enable 512K backup RAM cartridge when booting from CD (Mode 2) */192//scd.cartridge.id = 6;193//scd.cartridge.id = 4; // use 128K instead, which is the size of a real ebram cart194// bizhawk doesn't need the extra space because it gives each game its own anyway195scd.cartridge.id = 1; // 16K to be size-frugal196}197198/* RAM cartridge enabled ? */199if (scd.cartridge.id)200{201/* disable cartridge backup memory */202memset(&sram, 0, sizeof (T_SRAM));203204/* clear backup RAM */205memset(scd.cartridge.area, 0x00, sizeof(scd.cartridge.area));206207/* backup RAM size mask */208scd.cartridge.mask = (1 << (scd.cartridge.id + 13)) - 1;209210/* enable RAM cartridge write access */211scd.cartridge.prot = 1;212213/* RAM cartridge ID register (read-only) */214for (i=0x40; i<0x60; i++)215{216m68k.memory_map[i].base = NULL;217m68k.memory_map[i].read8 = cart_id_read_byte;218m68k.memory_map[i].read16 = cart_id_read_word;219m68k.memory_map[i].write8 = m68k_unused_8_w;220m68k.memory_map[i].write16 = m68k_unused_16_w;221zbank_memory_map[i].read = cart_id_read_byte;222zbank_memory_map[i].write = zbank_unused_w;223}224225/* RAM cartridge memory */226for (i=0x60; i<0x70; i++)227{228m68k.memory_map[i].base = NULL;229m68k.memory_map[i].read8 = cart_ram_read_byte;230m68k.memory_map[i].read16 = cart_ram_read_word;231m68k.memory_map[i].write8 = cart_ram_write_byte;232m68k.memory_map[i].write16 = cart_ram_write_word;233zbank_memory_map[i].read = cart_ram_read_byte;234zbank_memory_map[i].write = cart_ram_write_byte;235}236237/* RAM cartridge write protection register */238for (i=0x70; i<0x80; i++)239{240m68k.memory_map[i].base = NULL;241m68k.memory_map[i].read8 = cart_prot_read_byte;242m68k.memory_map[i].read16 = cart_prot_read_word;243m68k.memory_map[i].write8 = cart_prot_write_byte;244m68k.memory_map[i].write16 = cart_prot_write_word;245zbank_memory_map[i].read = cart_prot_read_byte;246zbank_memory_map[i].write = cart_prot_write_byte;247}248}249else250{251/* initialize ROM cartridge */252md_cart_init();253254/* when booting from CD, cartridge is mapped to $400000-$7FFFFF */255if (!scd.cartridge.boot)256{257for (i=0; i<0x40; i++)258{259m68k.memory_map[i+0x40].base = m68k.memory_map[i].base;260m68k.memory_map[i+0x40].read8 = m68k.memory_map[i].read8;261m68k.memory_map[i+0x40].read16 = m68k.memory_map[i].read16;262m68k.memory_map[i+0x40].write8 = m68k.memory_map[i].write8;263m68k.memory_map[i+0x40].write16 = m68k.memory_map[i].write16;264zbank_memory_map[i+0x40].read = zbank_memory_map[i].read;265zbank_memory_map[i+0x40].write = zbank_memory_map[i].write;266}267}268}269}270271272