mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-11-05 10:25:07 +01:00
624 lines
19 KiB
C
624 lines
19 KiB
C
/****************************************************************************
|
|
* Genesis Plus 1.2a
|
|
* Cartridge Hardware support
|
|
*
|
|
* code by Eke-Eke, GC/Wii port
|
|
*
|
|
* Lots of protection mechanism have been discovered by Haze
|
|
* (http://haze.mameworld.info/)
|
|
*
|
|
* Realtec mapper has been figured out by TascoDeluxe
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
***************************************************************************/
|
|
|
|
#include "shared.h"
|
|
#include "m68kcpu.h"
|
|
|
|
#define CART_CNT 26
|
|
|
|
/* Function prototypes */
|
|
void default_time_w(unsigned int address, unsigned int value);
|
|
void special_mapper_w(unsigned int address, unsigned int value);
|
|
void realtec_mapper_w(unsigned int address, unsigned int value);
|
|
void seganet_mapper_w(unsigned int address, unsigned int value);
|
|
unsigned int radica_mapper_r(unsigned int address);
|
|
void default_regs_w(unsigned int address, unsigned int value);
|
|
unsigned int default_regs_r(unsigned int address);
|
|
void special_regs_w(unsigned int address, unsigned int value);
|
|
|
|
/* Cart database entry */
|
|
typedef struct
|
|
{
|
|
uint16 chk_1; /* header checksum */
|
|
uint16 chk_2; /* real checksum */
|
|
uint8 bank_start; /* first mapped bank in $400000-$7fffff region */
|
|
uint8 bank_end; /* last mapped bank in $400000-$7fffff region */
|
|
T_CART_HW cart_hw; /* hardware description */
|
|
} T_CART_ENTRY;
|
|
|
|
/* Games that need extra hardware emulation:
|
|
- copy protection device
|
|
- custom ROM banking device
|
|
*/
|
|
T_CART_ENTRY rom_database[CART_CNT] =
|
|
{
|
|
/* Game no Kanzume Otokuyou */
|
|
{0x0000,0xf9d1,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,seganet_mapper_w,0,0}},
|
|
/* RADICA (Volume 1) (not byteswapped) */
|
|
{0x0000,0x2326,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,radica_mapper_r,0,0,0}},
|
|
/* RADICA (Volume 2) */
|
|
{0x4f10,0x0836,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,radica_mapper_r,0,0,0}},
|
|
/* RADICA (Volume 1) */
|
|
{0xf424,0x9f82,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,radica_mapper_r,0,0,0}},
|
|
/* Funny World & Balloon Boy */
|
|
{0x0000,0x06ab,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,0,0,0,realtec_mapper_w}},
|
|
/* Whac-a-Critter */
|
|
{0xffff,0xf863,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,0,0,0,realtec_mapper_w}},
|
|
/* Earth Defense */
|
|
{0xffff,0x44fb,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,0,0,0,realtec_mapper_w}},
|
|
/* Super Mario 2 1998 */
|
|
{0xffff,0x0474,0,0,{{0x0a,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,default_regs_r,0,0,0}},
|
|
/* Super Mario 2 1998 */
|
|
{0x2020,0xb4eb,0,0,{{0x1c,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,default_regs_r,0,0,0}},
|
|
/* Supper Bubble Bobble */
|
|
{0x0000,0x16cd,8,8,{{0x55,0x0f,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x400002,0,0},0,0,0,default_regs_r,0}},
|
|
/* Mahjong Lover */
|
|
{0x0000,0x7037,8,8,{{0x90,0xd3,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x401000,0,0},0,0,0,default_regs_r,0}},
|
|
/* Lion King 2 */
|
|
{0xffff,0x1d9b,8,8,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,default_regs_r,default_regs_w}},
|
|
/* Squirell King */
|
|
{0x0000,0x8ec8,8,8,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,default_regs_r,default_regs_w}},
|
|
/* Rockman X3 */
|
|
{0x0000,0x9d0e,8,8,{{0x0c,0x88,0,0},{0xffffff,0xffffff,0,0},{0xa13000,0x400004,0,0},0,default_regs_r,0,default_regs_r,0}},
|
|
/* A Bug's Life */
|
|
{0x7f7f,0x2aad,0,0,{{0x28,0x1f,0x01,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,default_regs_r,0,0,0}},
|
|
/* King of Fighter 99 */
|
|
{0x0000,0x21e,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,default_regs_r,0,0,0}},
|
|
/* Pocket Monster */
|
|
{0xd6fc,0x1eb1,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,default_regs_r,0,0,0}},
|
|
/* Lion King 3 */
|
|
{0x0000,0x507c,12,15,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,0,0,default_regs_r,special_regs_w}},
|
|
/* Super King Kong 99 */
|
|
{0x0000,0x7d6e,12,15,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,0,0,default_regs_r,special_regs_w}},
|
|
/* Pokemon Stadium */
|
|
{0x0000,0x843c,14,15,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,0,special_regs_w}},
|
|
/* Elf Wor */
|
|
{0x0080,0x3dba,8,8,{{0x55,0x0f,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}},
|
|
/* Huan Le Tao Qi Shu - Smart Mouse */
|
|
{0x0000,0x1a28,8,8,{{0x55,0x0f,0xaa,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}},
|
|
/* Ya-Se Chuanshuo */
|
|
{0xffff,0xd472,8,8,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}},
|
|
/* Soul Blade */
|
|
{0x0000,0x0c5b,8,8,{{0x00,0x98,0xc9,0xF0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}},
|
|
/* King of Fighter 98 */
|
|
{0x0000,0xd0a0,9,9,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},0,0,0,default_regs_r,0}},
|
|
/* Lian Huan Pao - Barver Battle Saga */
|
|
{0x30b9,0x1c2a,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,default_regs_r,0}}
|
|
};
|
|
|
|
|
|
/* current cart hardware */
|
|
T_CART_HW cart_hw;
|
|
uint8 j_cart;
|
|
int old_system[2] = {-1,-1};
|
|
|
|
/************************************************************
|
|
Cart Hardware initialization
|
|
*************************************************************/
|
|
|
|
/* hardware that need to be reseted on power on */
|
|
void cart_hw_reset()
|
|
{
|
|
/* Realtec mapper */
|
|
if (cart_hw.realtec & 1)
|
|
{
|
|
int i;
|
|
|
|
/* enable BOOTROM */
|
|
for (i=0; i<8; i++) m68k_readmap_16[i] = REALTEC_ROM;
|
|
cart_hw.realtec |= 2;
|
|
}
|
|
|
|
/* SVP chip */
|
|
if (svp) svp_reset();
|
|
}
|
|
|
|
/* cart hardware detection */
|
|
void cart_hw_init()
|
|
{
|
|
int i;
|
|
|
|
/**********************************************
|
|
DEFAULT CART MAPPING
|
|
***********************************************/
|
|
for (i=0; i<8; i++)
|
|
{
|
|
m68k_readmap_8[i] = ROM;
|
|
m68k_readmap_16[i] = ROM;
|
|
m68k_writemap_8[i] = UNUSED;
|
|
m68k_writemap_16[i] = UNUSED;
|
|
}
|
|
|
|
for (i=8; i<16; i++)
|
|
{
|
|
m68k_readmap_8[i] = UNUSED;
|
|
m68k_readmap_16[i] = UNUSED;
|
|
m68k_writemap_8[i] = UNUSED;
|
|
m68k_writemap_16[i] = UNUSED;
|
|
}
|
|
|
|
/* restore previous setting */
|
|
if (old_system[0] != -1) input.system[0] = old_system[0];
|
|
if (old_system[1] != -1) input.system[1] = old_system[1];
|
|
|
|
/**********************************************
|
|
EXTERNAL RAM
|
|
***********************************************/
|
|
sram_init();
|
|
eeprom_init();
|
|
if (sram.on)
|
|
{
|
|
if (sram.custom)
|
|
{
|
|
/* serial EEPROM */
|
|
m68k_readmap_8[eeprom.type.sda_out_adr >> 19] = EEPROM;
|
|
m68k_readmap_16[eeprom.type.sda_out_adr >> 19] = EEPROM;
|
|
m68k_writemap_8[eeprom.type.sda_in_adr >> 19] = EEPROM;
|
|
m68k_writemap_16[eeprom.type.sda_in_adr >> 19] = EEPROM;
|
|
m68k_writemap_8[eeprom.type.scl_adr >> 19] = EEPROM;
|
|
m68k_writemap_16[eeprom.type.scl_adr >> 19] = EEPROM;
|
|
}
|
|
else
|
|
{
|
|
/* 64KB SRAM */
|
|
m68k_readmap_8[sram.start >> 19] = SRAM;
|
|
m68k_readmap_16[sram.start >> 19] = SRAM;
|
|
if (sram.write)
|
|
{
|
|
m68k_writemap_8[sram.start >> 19] = SRAM;
|
|
m68k_writemap_16[sram.start >> 19] = SRAM;
|
|
}
|
|
}
|
|
}
|
|
/**********************************************
|
|
SVP CHIP
|
|
***********************************************/
|
|
svp = NULL;
|
|
if (strstr(rominfo.international,"Virtua Racing") != NULL)
|
|
{
|
|
svp_init();
|
|
m68k_readmap_16[6] = SVP_DRAM;
|
|
m68k_writemap_16[6] = SVP_DRAM;
|
|
m68k_readmap_16[7] = SVP_CELL;
|
|
m68k_writemap_16[7] = SVP_CELL;
|
|
}
|
|
|
|
/* default GUN settings */
|
|
input.x_offset = 0x00;
|
|
input.y_offset = 0x00;
|
|
|
|
/**********************************************
|
|
SEGA MENACER
|
|
***********************************************/
|
|
if (strstr(rominfo.international,"MENACER") != NULL)
|
|
{
|
|
/* save current setting */
|
|
if (old_system[0] == -1) old_system[0] = input.system[0];
|
|
if (old_system[1] == -1) old_system[1] = input.system[1];
|
|
|
|
input.system[0] = NO_SYSTEM;
|
|
input.system[1] = SYSTEM_MENACER;
|
|
input.x_offset = 0x52;
|
|
input.y_offset = 0x00;
|
|
}
|
|
else if (strstr(rominfo.international,"T2 ; THE ARCADE GAME") != NULL)
|
|
{
|
|
/* save current setting */
|
|
if (old_system[0] == -1) old_system[0] = input.system[0];
|
|
if (old_system[1] == -1) old_system[1] = input.system[1];
|
|
|
|
input.system[0] = SYSTEM_GAMEPAD;
|
|
input.system[1] = SYSTEM_MENACER;
|
|
input.x_offset = 0x84;
|
|
input.y_offset = 0x08;
|
|
}
|
|
else if (strstr(rominfo.international,"BODY COUNT") != NULL)
|
|
{
|
|
/* save current setting */
|
|
if (old_system[0] == -1) old_system[0] = input.system[0];
|
|
if (old_system[1] == -1) old_system[1] = input.system[1];
|
|
|
|
input.system[0] = SYSTEM_MOUSE;
|
|
input.system[1] = SYSTEM_MENACER;
|
|
input.x_offset = 0x44;
|
|
input.y_offset = 0x18;
|
|
}
|
|
|
|
/**********************************************
|
|
KONAMI JUSTIFIER
|
|
***********************************************/
|
|
if (strstr(rominfo.international,"LETHAL ENFORCERS II") != NULL)
|
|
{
|
|
/* save current setting */
|
|
if (old_system[0] == -1) old_system[0] = input.system[0];
|
|
if (old_system[1] == -1) old_system[1] = input.system[1];
|
|
|
|
input.system[0] = SYSTEM_GAMEPAD;
|
|
input.system[1] = SYSTEM_JUSTIFIER;
|
|
input.x_offset = 0x18;
|
|
input.y_offset = 0x00;
|
|
}
|
|
else if (strstr(rominfo.international,"LETHAL ENFORCERS") != NULL)
|
|
{
|
|
/* save current setting */
|
|
if (old_system[0] == -1) old_system[0] = input.system[0];
|
|
if (old_system[1] == -1) old_system[1] = input.system[1];
|
|
|
|
input.system[0] = SYSTEM_GAMEPAD;
|
|
input.system[1] = SYSTEM_JUSTIFIER;
|
|
input.x_offset = 0x00;
|
|
input.y_offset = 0x00;
|
|
}
|
|
|
|
/**********************************************
|
|
J-CART
|
|
***********************************************/
|
|
j_cart = 0;
|
|
if (((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x168b)) || /* Super Skidmarks, Micro Machines Military*/
|
|
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x165e)) || /* Pete Sampras Tennis (1991), Micro Machines 96 */
|
|
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0xcee0)) || /* Micro Machines Military (bad) */
|
|
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x2c41)) || /* Micro Machines 96 (bad) */
|
|
((strstr(rominfo.product,"XXXXXXXX") != NULL) && (rominfo.checksum == 0xdf39)) || /* Sampras Tennis 96 */
|
|
((strstr(rominfo.product,"T-123456") != NULL) && (rominfo.checksum == 0x1eae)) || /* Sampras Tennis 96 */
|
|
((strstr(rominfo.product,"T-120066") != NULL) && (rominfo.checksum == 0x16a4)) || /* Pete Sampras Tennis (1994)*/
|
|
(strstr(rominfo.product,"T-120096") != NULL)) /* Micro Machines 2 */
|
|
{
|
|
if (genromsize <= 0x380000) /* just to be sure (checksum might not be enough) */
|
|
{
|
|
j_cart = 1;
|
|
m68k_readmap_16[7] = J_CART;
|
|
m68k_writemap_16[7] = J_CART;
|
|
|
|
/* save current setting */
|
|
if (old_system[0] == -1) old_system[0] = input.system[0];
|
|
if (old_system[1] == -1) old_system[1] = input.system[1];
|
|
|
|
/* PORT B by default */
|
|
input.system[0] = SYSTEM_GAMEPAD;
|
|
input.system[1] = SYSTEM_GAMEPAD;
|
|
}
|
|
}
|
|
|
|
/**********************************************
|
|
ULTIMATE MK3 HACK
|
|
***********************************************/
|
|
if (genromsize > 0x600000)
|
|
{
|
|
for (i=8; i<20; i++)
|
|
{
|
|
m68k_readmap_8[i] = UMK3_HACK;
|
|
m68k_readmap_16[i] = UMK3_HACK;
|
|
}
|
|
|
|
#if M68K_EMULATE_ADDRESS_ERROR
|
|
/* this game does not work properly on real hardware */
|
|
emulate_address_error = 0;
|
|
#endif
|
|
}
|
|
#if M68K_EMULATE_ADDRESS_ERROR
|
|
/* default behavior */
|
|
else emulate_address_error = 1;
|
|
#endif
|
|
|
|
/**********************************************
|
|
Mappers & HW registers
|
|
***********************************************/
|
|
memset(&cart_hw, 0, sizeof(cart_hw));
|
|
|
|
/* default write handler for !TIME signal */
|
|
cart_hw.time_w = default_time_w;
|
|
|
|
/* search for game into database */
|
|
for (i=0; i < CART_CNT + 1; i++)
|
|
{
|
|
/* known cart found ! */
|
|
if ((rominfo.checksum == rom_database[i].chk_1) &&
|
|
(realchecksum == rom_database[i].chk_2))
|
|
{
|
|
/* retrieve hardware information */
|
|
memcpy(&cart_hw, &(rom_database[i].cart_hw), sizeof(cart_hw));
|
|
|
|
/* initialize memory handlers for $400000-$7fffff region */
|
|
int j = rom_database[i].bank_start;
|
|
while (j <= rom_database[i].bank_end)
|
|
{
|
|
if (cart_hw.regs_r) m68k_readmap_8[j] = CART_HW;
|
|
if (cart_hw.regs_w) m68k_writemap_8[j] = CART_HW;
|
|
j++;
|
|
}
|
|
i = CART_CNT + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************
|
|
MAPPER handlers
|
|
*************************************************************/
|
|
/*
|
|
"official" ROM/RAM switch
|
|
*/
|
|
static inline void sega_mapper_w(unsigned int address, unsigned int value)
|
|
{
|
|
uint8 bank = (address >> 1) & 7;
|
|
|
|
switch (bank)
|
|
{
|
|
case 0:
|
|
{
|
|
/* ROM/RAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */
|
|
if (value & 1)
|
|
{
|
|
/* SRAM is mapped above 200000h */
|
|
m68k_readmap_8[4] = SRAM;
|
|
m68k_readmap_16[4] = SRAM;
|
|
|
|
if (value & 2)
|
|
{
|
|
/* SRAM write protected */
|
|
m68k_writemap_8[4] = UNUSED;
|
|
m68k_writemap_16[4] = UNUSED;
|
|
}
|
|
else
|
|
{
|
|
/* SRAM write enabled */
|
|
m68k_writemap_8[4] = SRAM;
|
|
m68k_writemap_16[4] = SRAM;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* ROM is mapped above 200000h */
|
|
m68k_readmap_8[4] = ROM;
|
|
m68k_readmap_16[4] = ROM;
|
|
m68k_writemap_8[4] = UNUSED;
|
|
m68k_writemap_16[4] = UNUSED;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
/* ROM Bankswitch (Super Street Fighter 2)
|
|
documented by Bart Trzynadlowski (http://www.trzy.org/files/ssf2.txt)
|
|
*/
|
|
rom_readmap[bank] = &cart_rom[value << 19];
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
custom ROM Bankswitch used by pirate "Multi-in-1" carts
|
|
(documented by Haze)
|
|
*/
|
|
static inline void multi_mapper_w(unsigned int address, unsigned int value)
|
|
{
|
|
int i;
|
|
uint32 bank_addr = (address & 0x3F) << 16;
|
|
|
|
/* those games are generally not bigger than 1MB but it's safer to update all 512K banks */
|
|
for (i=0; i<8; i++)
|
|
{
|
|
if (bank_addr >= genromsize) return;
|
|
rom_readmap[i] = &cart_rom[bank_addr];
|
|
bank_addr += 0x80000;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Special ROM Bankswitch used for copy protection
|
|
Used by unlicensed cartridges (Lion King III, Super King Kong 99)
|
|
(documented by Haze)
|
|
*/
|
|
void special_mapper_w(unsigned int address, unsigned int value)
|
|
{
|
|
rom_readmap[0] = &cart_rom[value << 15];
|
|
}
|
|
|
|
/*
|
|
Realtec ROM Bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter)
|
|
(documented by TascoDeluxe)
|
|
*/
|
|
void realtec_mapper_w(unsigned int address, unsigned int value)
|
|
{
|
|
uint32 base_addr;
|
|
|
|
if (cart_hw.realtec & 2)
|
|
{
|
|
int i;
|
|
cart_hw.realtec &= ~2;
|
|
|
|
/* disable Realtec BOOTROM */
|
|
for (i=0; i<8; i++)
|
|
{
|
|
m68k_readmap_8[i] = ROM;
|
|
m68k_readmap_16[i] = ROM;
|
|
}
|
|
}
|
|
|
|
switch (address)
|
|
{
|
|
case 0x404000: /* three lower bits of ROM base address */
|
|
cart_hw.regs[0] = value;
|
|
base_addr = (value | ((cart_hw.regs[1] & 6) << 2)) << 17;
|
|
rom_readmap[0] = &cart_rom[base_addr];
|
|
return;
|
|
|
|
case 0x400000: /* two higher bits of ROM base address */
|
|
cart_hw.regs[1] = value;
|
|
base_addr = ((cart_hw.regs[0] & 7) | ((value & 6) << 2)) << 17;
|
|
rom_readmap[0] = &cart_rom[base_addr];
|
|
return;
|
|
|
|
case 0x402000: /* size of ROM range to map */
|
|
cart_hw.regs[2] = value;
|
|
return;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/* Game no Kanzume Otokuyou ROM Mapper */
|
|
void seganet_mapper_w(unsigned int address, unsigned int value)
|
|
{
|
|
int i;
|
|
switch (address & 0xff)
|
|
{
|
|
case 0x01:
|
|
if (value & 1)
|
|
{
|
|
/* ROM disabled */
|
|
for (i=0; i<8; i++)
|
|
{
|
|
m68k_readmap_8[i] = UNUSED;
|
|
m68k_readmap_16[i] = UNUSED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* ROM enabled */
|
|
for (i=0; i<8; i++)
|
|
{
|
|
m68k_readmap_8[i] = ROM;
|
|
m68k_readmap_16[i] = ROM;
|
|
}
|
|
}
|
|
break;;
|
|
|
|
case 0xf1:
|
|
if (value & 1)
|
|
{
|
|
/* ROM Write protected*/
|
|
for (i=0; i<8; i++)
|
|
{
|
|
m68k_writemap_8[i] = UNUSED;
|
|
m68k_writemap_16[i] = UNUSED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* ROM Write enabled */
|
|
for (i=0; i<8; i++)
|
|
{
|
|
m68k_writemap_8[i] = ROM;
|
|
m68k_writemap_16[i] = ROM;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
RADICA ROM Bankswitch
|
|
(documented by Haze)
|
|
*/
|
|
unsigned int radica_mapper_r(unsigned int address)
|
|
{
|
|
/* 64KB ROM banks */
|
|
uint8 bank = (address >> 1) & 0x3F;
|
|
rom_readmap[0] = &cart_rom[bank * 0x10000];
|
|
rom_readmap[1] = &cart_rom[bank * 0x10000 + 0x80000]; /* ROM is max. 1MB */
|
|
return 0xff;
|
|
}
|
|
|
|
|
|
/************************************************************
|
|
default !TIME signal handler
|
|
*************************************************************/
|
|
|
|
/* default ROM bankswitch */
|
|
void default_time_w(unsigned int address, unsigned int value)
|
|
{
|
|
if ((address & 0xf1) == 0xf1) sega_mapper_w(address, value);
|
|
else if (address < 0xa13040) multi_mapper_w(address, value);
|
|
}
|
|
|
|
/************************************************************
|
|
Internal register handlers
|
|
*************************************************************/
|
|
|
|
unsigned int default_regs_r(unsigned int address)
|
|
{
|
|
uint8 i;
|
|
for (i=0; i<4; i++)
|
|
{
|
|
if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
|
|
return cart_hw.regs[i];
|
|
}
|
|
|
|
/* unused */
|
|
return -1;
|
|
}
|
|
|
|
void default_regs_w(unsigned int address, unsigned int value)
|
|
{
|
|
uint8 i;
|
|
for (i=0; i<4; i++)
|
|
{
|
|
if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
|
|
{
|
|
cart_hw.regs[i] = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* special register behaviour (Lion King III, Super Donkey Kong 99) */
|
|
void special_regs_w(unsigned int address, unsigned int value)
|
|
{
|
|
/* ROM bankswitch */
|
|
if ((address >> 16) > 0x6f)
|
|
{
|
|
special_mapper_w(address, value);
|
|
return;
|
|
}
|
|
|
|
/* write regs */
|
|
default_regs_w(address, value);
|
|
|
|
/* bitswapping (documented by Haze) */
|
|
uint8 temp = cart_hw.regs[0];
|
|
switch (cart_hw.regs[1])
|
|
{
|
|
case 1:
|
|
cart_hw.regs[2] = (temp >> 1);
|
|
return;
|
|
|
|
case 2:
|
|
cart_hw.regs[2] = ((temp >> 4) | ((temp & 0x0F) << 4));
|
|
return;
|
|
|
|
default:
|
|
cart_hw.regs[2] = (((temp >> 7) & 0x01) | ((temp >> 5) & 0x02) |
|
|
((temp >> 3) & 0x04) | ((temp >> 1) & 0x08) |
|
|
((temp << 1) & 0x10) | ((temp << 3) & 0x20) |
|
|
((temp << 5) & 0x40) | ((temp << 7) & 0x80));
|
|
return;
|
|
}
|
|
}
|