added proper IO initialization routines

improved cartridge structure
added Lock-ON hardware emulation (Sonic & Knuckles)
added cartridge ROM mirroring support (required for Lock-ON emulation)
This commit is contained in:
ekeeke31 2009-08-06 18:31:05 +00:00
parent 0743df467e
commit 5b888e725b
33 changed files with 704 additions and 491 deletions

View File

@ -32,20 +32,7 @@
extern int emulate_address_error; extern int emulate_address_error;
/* Global Variables */ /* Global Variables */
T_CART_HW cart_hw; T_CART cart;
uint8 j_cart;
uint8 *default_rom;
int old_system[2] = {-1,-1};
/* Function prototypes */
void default_time_w(uint32 address, uint32 data);
void special_mapper_w(uint32 address, uint32 data);
void realtec_mapper_w(uint32 address, uint32 data);
void seganet_mapper_w(uint32 address, uint32 data);
uint32 radica_mapper_r(uint32 address);
void default_regs_w(uint32 address, uint32 data);
uint32 default_regs_r(uint32 address);
void special_regs_w(uint32 address, uint32 data);
/* Cart database entry */ /* Cart database entry */
typedef struct typedef struct
@ -57,64 +44,75 @@ typedef struct
T_CART_HW cart_hw; /* hardware description */ T_CART_HW cart_hw; /* hardware description */
} T_CART_ENTRY; } T_CART_ENTRY;
/* Function prototypes */
static void sega_mapper_w(uint32 address, uint32 data);
static void special_mapper_w(uint32 address, uint32 data);
static void realtec_mapper_w(uint32 address, uint32 data);
static void seganet_mapper_w(uint32 address, uint32 data);
static uint32 radica_mapper_r(uint32 address);
static void default_time_w(uint32 address, uint32 data);
static void default_regs_w(uint32 address, uint32 data);
static uint32 default_regs_r(uint32 address);
static void special_regs_w(uint32 address, uint32 data);
/* Games that need extra hardware emulation: /* Games that need extra hardware emulation:
- copy protection device - copy protection device
- custom ROM banking device - custom ROM banking device
*/ */
static const T_CART_ENTRY rom_database[CART_CNT] = static const 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,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,1,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,1,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,1,radica_mapper_r,0,0,0}},
/* Funny World & Balloon Boy */ /* Funny World & Balloon Boy */
{0x0000,0x06ab,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}}, {0x0000,0x06ab,0x40,0x40,{{0x00,0x00,0x00,0x00},{0x000000,0x000000,0x000000,0x000000},{0x000000,0x000000,0x000000,0x000000},1,0,1,NULL,NULL,NULL,realtec_mapper_w}},
/* Whac-a-Critter */ /* Whac-a-Critter */
{0xffff,0xf863,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}}, {0xffff,0xf863,0x40,0x40,{{0x00,0x00,0x00,0x00},{0x000000,0x000000,0x000000,0x000000},{0x000000,0x000000,0x000000,0x000000},1,0,1,NULL,NULL,NULL,realtec_mapper_w}},
/* Earth Defense */ /* Earth Defense */
{0xffff,0x44fb,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}}, {0xffff,0x44fb,0x40,0x40,{{0x00,0x00,0x00,0x00},{0x000000,0x000000,0x000000,0x000000},{0x000000,0x000000,0x000000,0x000000},1,0,1,NULL,NULL,NULL,realtec_mapper_w}},
/* Super Mario 2 1998 */ /* RADICA (Volume 1) (not byteswapped) */
{0xffff,0x0474,0,0,{{0x0a,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,0,default_regs_r,0,0,0}}, {0x0000,0x2326,0x00,0x00,{{0x00,0x00,0x00,0x00},{0x000000,0x000000,0x000000,0x000000},{0x000000,0x000000,0x000000,0x000000},0,0,1,radica_mapper_r,NULL,NULL,NULL}},
/* Super Mario 2 1998 */ /* RADICA (Volume 2) */
{0x2020,0xb4eb,0,0,{{0x1c,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,0,default_regs_r,0,0,0}}, {0x4f10,0x0836,0x00,0x00,{{0x00,0x00,0x00,0x00},{0x000000,0x000000,0x000000,0x000000},{0x000000,0x000000,0x000000,0x000000},0,0,1,radica_mapper_r,NULL,NULL,NULL}},
/* Supper Bubble Bobble */ /* RADICA (Volume 1) */
{0x0000,0x16cd,0x40,0x40,{{0x55,0x0f,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x400002,0,0},0,0,0,0,default_regs_r,0}}, {0xf424,0x9f82,0x00,0x00,{{0x00,0x00,0x00,0x00},{0x000000,0x000000,0x000000,0x000000},{0x000000,0x000000,0x000000,0x000000},0,0,1,radica_mapper_r,NULL,NULL,NULL}},
/* Mahjong Lover */
{0x0000,0x7037,0x40,0x40,{{0x90,0xd3,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x401000,0,0},0,0,0,0,default_regs_r,0}},
/* Lion King 2 */
{0xffff,0x1d9b,0x40,0x40,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,0,default_regs_r,default_regs_w}},
/* Squirell King */
{0x0000,0x8ec8,0x40,0x40,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,0,default_regs_r,default_regs_w}},
/* Rockman X3 */
{0x0000,0x9d0e,0x40,0x40,{{0x0c,0x88,0,0},{0xffffff,0xffffff,0,0},{0xa13000,0x400004,0,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,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,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,0,default_regs_r,0,0,0}},
/* Lion King 3 */ /* Lion King 3 */
{0x0000,0x507c,0x60,0x7f,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,1,0,0,default_regs_r,special_regs_w}}, {0x0000,0x507c,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf0000e,0xf0000e,0xf0000e,0x000000},{0x600000,0x600002,0x600004,0x000000},0,0,1,NULL,NULL,default_regs_r,special_regs_w}},
/* Super King Kong 99 */ /* Super King Kong 99 */
{0x0000,0x7d6e,0x60,0x7f,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,1,0,0,default_regs_r,special_regs_w}}, {0x0000,0x7d6e,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf0000e,0xf0000e,0xf0000e,0x000000},{0x600000,0x600002,0x600004,0x000000},0,0,1,NULL,NULL,default_regs_r,special_regs_w}},
/* Pokemon Stadium */ /* Pokemon Stadium */
{0x0000,0x843c,0x70,0x7f,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,0,0,0,special_regs_w}}, {0x0000,0x843c,0x70,0x7f,{{0x00,0x00,0x00,0x00},{0x000000,0x000000,0x000000,0x000000},{0x000000,0x000000,0x000000,0x000000},0,0,1,NULL,NULL,default_regs_r,special_regs_w}},
/* Lion King 2 */
{0xffff,0x1d9b,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xfffffd,0xfffffd,0x000000,0x000000},{0x400000,0x400004,0x000000,0x000000},0,0,0,NULL,NULL,default_regs_r,default_regs_w}},
/* Squirell King */
{0x0000,0x8ec8,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xfffffd,0xfffffd,0x000000,0x000000},{0x400000,0x400004,0x000000,0x000000},0,0,0,NULL,NULL,default_regs_r,default_regs_w}},
/* Supper Bubble Bobble */
{0x0000,0x16cd,0x40,0x40,{{0x55,0x0f,0x00,0x00},{0xffffff,0xffffff,0x000000,0x000000},{0x400000,0x400002,0x000000,0x000000},0,0,0,NULL,NULL,default_regs_r,NULL}},
/* Mahjong Lover */
{0x0000,0x7037,0x40,0x40,{{0x90,0xd3,0x00,0x00},{0xffffff,0xffffff,0x000000,0x000000},{0x400000,0x401000,0x000000,0x000000},0,0,0,NULL,NULL,default_regs_r,NULL}},
/* Elf Wor */ /* Elf Wor */
{0x0080,0x3dba,0x40,0x40,{{0x55,0x0f,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}}, {0x0080,0x3dba,0x40,0x40,{{0x55,0x0f,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,NULL,NULL,default_regs_r,NULL}},
/* Huan Le Tao Qi Shu - Smart Mouse */ /* Huan Le Tao Qi Shu - Smart Mouse */
{0x0000,0x1a28,0x40,0x40,{{0x55,0x0f,0xaa,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}}, {0x0000,0x1a28,0x40,0x40,{{0x55,0x0f,0xaa,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,NULL,NULL,default_regs_r,NULL}},
/* Ya-Se Chuanshuo */ /* Ya-Se Chuanshuo */
{0xffff,0xd472,0x40,0x40,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}}, {0xffff,0xd472,0x40,0x40,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,NULL,NULL,default_regs_r,NULL}},
/* Soul Blade */ /* Soul Blade */
{0x0000,0x0c5b,0x40,0x40,{{0x00,0x98,0xc9,0xF0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}}, {0x0000,0x0c5b,0x40,0x40,{{0x00,0x98,0xc9,0xF0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,NULL,NULL,default_regs_r,NULL}},
/* King of Fighter 98 */ /* King of Fighter 98 */
{0x0000,0xd0a0,0x48,0x4f,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},0,0,0,0,default_regs_r,0}}, {0x0000,0xd0a0,0x48,0x4f,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},0,0,0,NULL,NULL,default_regs_r,NULL}},
/* Lian Huan Pao - Barver Battle Saga */ /* Lian Huan Pao - Barver Battle Saga */
{0x30b9,0x1c2a,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,0,default_regs_r,0}} {0x30b9,0x1c2a,0x40,0x40,{{0x00,0x00,0x00,0x00},{0x000000,0x000000,0x000000,0x000000},{0x000000,0x000000,0x000000,0x000000},0,0,0,NULL,NULL,default_regs_r,NULL}},
/* Rockman X3 */
{0x0000,0x9d0e,0x40,0x40,{{0x0c,0x88,0x00,0x00},{0xffffff,0xffffff,0x000000,0x000000},{0xa13000,0x400004,0x000000,0x000000},0,0,0,default_regs_r,NULL,default_regs_r,NULL}},
/* Super Mario 2 1998 */
{0xffff,0x0474,0x00,0x00,{{0x0a,0x00,0x00,0x00},{0xffffff,0x000000,0x000000,0x000000},{0xa13000,0x000000,0x000000,0x000000},0,0,0,default_regs_r,NULL,NULL,NULL}},
/* Super Mario 2 1998 */
{0x2020,0xb4eb,0x00,0x00,{{0x1c,0x00,0x00,0x00},{0xffffff,0x000000,0x000000,0x000000},{0xa13000,0x000000,0x000000,0x000000},0,0,0,default_regs_r,NULL,NULL,NULL}},
/* A Bug's Life */
{0x7f7f,0x2aad,0x00,0x00,{{0x28,0x1f,0x01,0x00},{0xffffff,0xffffff,0xffffff,0x000000},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,0,default_regs_r,NULL,NULL,NULL}},
/* King of Fighter 99 */
{0x0000,0x021e,0x00,0x00,{{0x00,0x01,0x1f,0x00},{0xffffff,0xffffff,0xffffff,0x000000},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,0,default_regs_r,NULL,NULL,NULL}},
/* Pocket Monster */
{0xd6fc,0x1eb1,0x00,0x00,{{0x00,0x01,0x1f,0x00},{0xffffff,0xffffff,0xffffff,0x000000},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,0,default_regs_r,NULL,NULL,NULL}},
/* Game no Kanzume Otokuyou */
{0x0000,0xf9d1,0x00,0x00,{{0x00,0x00,0x00,0x00},{0x000000,0x000000,0x000000,0x000000},{0x000000,0x000000,0x000000,0x000000},0,0,0,NULL,seganet_mapper_w,NULL,NULL}}
}; };
/* temporary memory chunk */ /* temporary memory chunk */
@ -125,64 +123,97 @@ static uint8 mem_chunk[0x10000];
Cart Hardware initialization Cart Hardware initialization
*************************************************************/ *************************************************************/
/* hardware that need to be reseted on power on */
void cart_hw_reset()
{
int i;
/* reset bankshifting */
if (cart_hw.bankshift)
{
for (i=0x00; i<0x40; i++)
m68k_memory_map[i].base = cart_rom + (i<<16);
}
/* Realtec mapper */
if (cart_hw.realtec & 1)
{
/* enable BOOTROM */
for (i=0; i<0x40; i++) m68k_memory_map[i].base = mem_chunk;
for (i=0; i<8; i++) memcpy(mem_chunk + i*0x2000, cart_rom + 0x7e000, 0x2000);
cart_hw.realtec |= 2;
}
/* SVP chip */
if (svp) svp_reset();
/* Lock-ON */
switch (config.lock_on)
{
case GAME_GENIE:
ggenie_reset();
break;
case ACTION_REPLAY:
datel_reset();
break;
case SONIC_KNUCKLES:
break;
default:
break;
}
/* save default cartridge slot mapping */
default_rom = m68k_memory_map[0].base;
}
/* cart hardware detection */ /* cart hardware detection */
void cart_hw_init() void cart_hw_init()
{ {
int i; /***************************************************************************************************************
CARTRIDGE ROM MIRRORING
***************************************************************************************************************
Cartridge area is mapped to $000000-$3fffff:
-> when accessing ROM, 68k address lines A1 to A21 are used by the internal cartridge hardware to decode the
full 4MB address range.
-> depending on the ROM total size, some address lines might be ignored, resulting in ROM mirroring.
Cartridges can use either 8-bits (x2) or 16-bits (x1, x2) Mask ROM chips, each chip size is a factor of 2 bytes:
-> two 8-bits chips are equivalent to one 16-bits chip, no specific address decoding is required, needed
address lines are simply connected to each chip, upper address lines are ignored and data lines are
connected appropriately to each chip (D0-D7 to one chip, D8-D15 to the other one).
ROM is mirrored each N bytes where N=2^(k+1) is the total ROM size (ROM1+ROM2,ROM1+ROM2,...).
-> one single 16-bits chip do not need specific address decoding, address lines are simply connected
depending on the ROM size, upper address lines being ignored.
ROM is mirrored each N bytes where N=2^k is the size of the ROM chip (ROM1,ROM1,ROM1,...).
-> two 16-bits chips of the same size are equivalent to one chip of double size, address decoding generally
is the same except that specific hardware is used (one address line is generally used for chip selection,
lower ones being used to address the chips and upper ones being ignored).
ROM is mirrored continuously each N bytes where N=2^(k+1) is the total ROM size (ROM1,ROM2,ROM1,ROM2,...).
-> two 16-bits chips with different size are mapped differently. Address decoding is done the same way as
above (one address line used for chip selection) but the ignored & required address lines differ from
one chip to another, which makes ROM mirroring different.
ROM2 size is generally half of ROM1 size and ROM are mirrored like that : ROM1,ROM2,ROM2,ROM1,ROM2,ROM2,...
From the emulator point of view, we only need to distinguish 3 cases:
1/ total ROM size is a factor of 2: ROM is mirrored each 2^k bytes.
2/ total ROM size is not a factor of 2 and cartridge uses one or two chips of the same size (Type A):
ROM is padded up to 2^k and mirrored each 2^k bytes.
3/ total ROM size is not a factor of 2 and cartridge uses two chips of different sizes (Type B):
ROM is not padded and the first 2^(k-1) bytes are mirrored each 2^k bytes while the next 2^(k-2) bytes are
mirrored in the last 2^(k-2) bytes.
******************************************************************************************************************/
/* calculate nearest size with factor of 2 */
int size = 0x10000;
while (cart.romsize > size) size <<= 1;
/* total ROM size is not a factor of 2 */
if ((size < MAXROMSIZE) && (cart.romsize < size))
{
/* two chips with different size */
if (config.romtype)
{
/* third ROM section is mirrored in the last section */
memcpy(cart.rom + cart.romsize, cart.rom + 2*cart.romsize - size, size - cart.romsize);
}
else
{
/* ROM is padded up to 2^k bytes */
memset(cart.rom + cart.romsize, 0xff, size - cart.romsize);
}
}
/* special case: Sonic & Knuckles */
/* $200000-$3fffff is mapped to external cartridge */
if (strstr(rominfo.international,"SONIC & KNUCKLES") != NULL)
{
/* disable ROM mirroring */
size = 0x400000;
}
/* ROM is mirrored each 2^k bytes */
int i = size;
while (i < 0x400000)
{
memcpy(cart.rom + i, cart.rom, size);
i += size;
}
/********************************************** /**********************************************
DEFAULT CARTRIDGE MAPPING DEFAULT CARTRIDGE MAPPING
***********************************************/ ***********************************************/
for (i=0; i<0x40; i++) for (i=0; i<0x40; i++)
{ {
/* cartridge ROM */ /* cartridge ROM */
m68k_memory_map[i].base = cart_rom + (i<<16); m68k_memory_map[i].base = cart.rom + (i<<16);
m68k_memory_map[i].read8 = NULL; m68k_memory_map[i].read8 = NULL;
m68k_memory_map[i].read16 = NULL; m68k_memory_map[i].read16 = NULL;
m68k_memory_map[i].write8 = m68k_unused_8_w; m68k_memory_map[i].write8 = m68k_unused_8_w;
@ -194,7 +225,7 @@ void cart_hw_init()
for (i=0x40; i<0x80; i++) for (i=0x40; i<0x80; i++)
{ {
/* unused area */ /* unused area */
m68k_memory_map[i].base = cart_rom + (i<<16); m68k_memory_map[i].base = cart.rom + (i<<16);
m68k_memory_map[i].read8 = m68k_read_bus_8; m68k_memory_map[i].read8 = m68k_read_bus_8;
m68k_memory_map[i].read16 = m68k_read_bus_16; m68k_memory_map[i].read16 = m68k_read_bus_16;
m68k_memory_map[i].write8 = m68k_unused_8_w; m68k_memory_map[i].write8 = m68k_unused_8_w;
@ -203,10 +234,6 @@ void cart_hw_init()
zbank_memory_map[i].write = zbank_unused_w; zbank_memory_map[i].write = zbank_unused_w;
} }
/* 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 EXTERNAL RAM
***********************************************/ ***********************************************/
@ -240,26 +267,6 @@ void cart_hw_init()
} }
} }
/**********************************************
CARTRIDGE LOCK-ON
***********************************************/
switch (config.lock_on)
{
case GAME_GENIE:
ggenie_init();
break;
case ACTION_REPLAY:
datel_init();
break;
case SONIC_KNUCKLES:
break;
default:
break;
}
/********************************************** /**********************************************
SVP CHIP SVP CHIP
***********************************************/ ***********************************************/
@ -268,11 +275,11 @@ void cart_hw_init()
{ {
svp_init(); svp_init();
m68k_memory_map[0x30].base = svp->dram; m68k_memory_map[0x30].base = svp->dram;
m68k_memory_map[0x30].read16 = NULL; m68k_memory_map[0x30].read16 = NULL;
m68k_memory_map[0x30].write16 = svp_write_dram; m68k_memory_map[0x30].write16 = svp_write_dram;
m68k_memory_map[0x31].base = svp->dram + 0x10000; m68k_memory_map[0x31].base = svp->dram + 0x10000;
m68k_memory_map[0x31].read16 = NULL; m68k_memory_map[0x31].read16 = NULL;
m68k_memory_map[0x31].write16 = svp_write_dram; m68k_memory_map[0x31].write16 = svp_write_dram;
@ -280,109 +287,89 @@ void cart_hw_init()
m68k_memory_map[0x3a].read16 = svp_read_cell_2; m68k_memory_map[0x3a].read16 = svp_read_cell_2;
} }
/* 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
***********************************************/
else if (strstr(rominfo.international,"LETHAL ENFORCERSII") != 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
***********************************************/ ***********************************************/
j_cart = 0; cart.hw.jcart = 0;
if (((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x168b)) || /* Super Skidmarks, Micro Machines Military*/ 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 == 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 == 0xcee0)) || /* Micro Machines Military (bad) */
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x2c41)) || /* Micro Machines 96 (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,"XXXXXXXX") != NULL) && (rominfo.checksum == 0xdf39)) || /* Sampras Tennis 96 */
((strstr(rominfo.product,"T-123456") != NULL) && (rominfo.checksum == 0x1eae)) || /* 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-120066") != NULL) && (rominfo.checksum == 0x16a4)) || /* Pete Sampras Tennis (1994)*/
(strstr(rominfo.product,"T-120096") != NULL)) /* Micro Machines 2 */ (strstr(rominfo.product,"T-120096") != NULL)) /* Micro Machines 2 */
{ {
if (genromsize <= 0x380000) /* just to be sure (checksum might not be enough) */ if (cart.romsize <= 0x380000) /* just to be sure (checksum might not be enough) */
{ {
j_cart = 1; cart.hw.jcart = 1;
m68k_memory_map[0x38].read16 = jcart_read; m68k_memory_map[0x38].read16 = jcart_read;
m68k_memory_map[0x38].write16 = jcart_write; m68k_memory_map[0x38].write16 = jcart_write;
m68k_memory_map[0x3f].read16 = jcart_read; m68k_memory_map[0x3f].read16 = jcart_read;
m68k_memory_map[0x3f].write16 = jcart_write; m68k_memory_map[0x3f].write16 = jcart_write;
/* 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;
} }
} }
/********************************************** /**********************************************
Mappers & HW registers LOCK-ON
***********************************************/ ***********************************************/
memset(&cart_hw, 0, sizeof(cart_hw)); cart.lock_on = 0;
switch (config.lock_on)
{
case TYPE_GG:
ggenie_init();
break;
case TYPE_AR:
datel_init();
break;
case TYPE_SK:
/* be sure we have enough place to copy everything */
if (cart.romsize < 0x700000)
{
/* load Sonic & Knuckles ROM (2 MBytes) */
FILE *f = fopen(SK_ROM,"r+b");
if (!f) break;
fread(cart.rom+0x700000,1,0x200000,f);
fclose(f);
/* load Sonic 2 UPMEM ROM (256 KBytes) */
f = fopen(SK_UPMEM,"r+b");
if (!f) break;
fread(cart.rom+0x900000,1,0x40000,f);
fclose(f);
/* ROM is mirrored each 256K */
memcpy(cart.rom+0x940000,cart.rom+0x900000,0x40000);
memcpy(cart.rom+0x980000,cart.rom+0x900000,0x40000);
memcpy(cart.rom+0x9C0000,cart.rom+0x900000,0x40000);
#ifdef LSB_FIRST
/* Byteswap ROM */
int i;
uint8 temp;
for(i = 0; i < 0x300000; i += 2)
{
temp = cart.rom[i+0x700000];
cart.rom[i+0x700000] = cart.rom[i+1+0x700000];
cart.rom[i+1+0x700000] = temp;
}
#endif
cart.lock_on = 1;
}
break;
default:
break;
}
/**********************************************
Cartridge Extra Hardware
***********************************************/
memset(&cart.hw, 0, sizeof(T_CART_HW));
/* search for game into database */ /* search for game into database */
for (i=0; i < CART_CNT + 1; i++) for (i=0; i < CART_CNT + 1; i++)
@ -392,23 +379,23 @@ void cart_hw_init()
(realchecksum == rom_database[i].chk_2)) (realchecksum == rom_database[i].chk_2))
{ {
/* retrieve hardware information */ /* retrieve hardware information */
memcpy(&cart_hw, &(rom_database[i].cart_hw), sizeof(cart_hw)); memcpy(&cart.hw, &(rom_database[i].cart_hw), sizeof(T_CART_HW));
/* initialize memory handlers for $400000-$7fffff region */ /* initialize memory handlers for $400000-$7fffff region */
int j = rom_database[i].bank_start; int j = rom_database[i].bank_start;
while (j <= rom_database[i].bank_end) while (j <= rom_database[i].bank_end)
{ {
if (cart_hw.regs_r) if (cart.hw.regs_r)
{ {
m68k_memory_map[j].read8 = cart_hw.regs_r; m68k_memory_map[j].read8 = cart.hw.regs_r;
m68k_memory_map[j].read16 = cart_hw.regs_r; m68k_memory_map[j].read16 = cart.hw.regs_r;
zbank_memory_map[j].read = cart_hw.regs_r; zbank_memory_map[j].read = cart.hw.regs_r;
} }
if (cart_hw.regs_w) if (cart.hw.regs_w)
{ {
m68k_memory_map[j].write8 = cart_hw.regs_w; m68k_memory_map[j].write8 = cart.hw.regs_w;
m68k_memory_map[j].write16 = cart_hw.regs_w; m68k_memory_map[j].write16 = cart.hw.regs_w;
zbank_memory_map[j].write = cart_hw.regs_w; zbank_memory_map[j].write = cart.hw.regs_w;
} }
j++; j++;
} }
@ -424,12 +411,12 @@ void cart_hw_init()
#endif #endif
/* detect ROM files larger than 4MB */ /* detect ROM files larger than 4MB */
if (genromsize > 0x800000) if (cart.romsize > 0x800000)
{ {
/* Ultimate MK3 (hack) */ /* Ultimate MK3 (hack) */
for (i=0x40; i<0xA0; i++) for (i=0x40; i<0xA0; i++)
{ {
m68k_memory_map[i].base = cart_rom + (i<<16); m68k_memory_map[i].base = cart.rom + (i<<16);
m68k_memory_map[i].read8 = NULL; m68k_memory_map[i].read8 = NULL;
m68k_memory_map[i].read16 = NULL; m68k_memory_map[i].read16 = NULL;
zbank_memory_map[i].read = NULL; zbank_memory_map[i].read = NULL;
@ -440,17 +427,77 @@ void cart_hw_init()
emulate_address_error = 0; emulate_address_error = 0;
#endif #endif
} }
else if (genromsize > 0x400000) else if (cart.romsize > 0x400000)
{ {
/* assume SSF2 mapper */ /* assume SSF2 mapper */
cart_hw.bankshift = 1; cart.hw.bankshift = 1;
cart.hw.time_w = sega_mapper_w;
} }
/* default write handler for !TIME signal */ /* default write handler for !TIME signal */
/* TODO: handle Sonic & Knuckles + Sonic 2 case to prevent RAM activation */ /* TODO: handle Sonic & Knuckles + Sonic 2 case to prevent RAM activation */
if (!cart_hw.time_w) cart_hw.time_w = default_time_w; if (!cart.hw.time_w)
cart.hw.time_w = default_time_w;
} }
/* hardware that need to be reseted on power on */
void cart_hw_reset()
{
int i;
/* reset bankshifting */
if (cart.hw.bankshift)
{
for (i=0x00; i<0x40; i++)
m68k_memory_map[i].base = cart.rom + (i<<16);
}
/* Realtec mapper */
if (cart.hw.realtec & 1)
{
/* enable BOOTROM */
for (i=0; i<0x40; i++)
m68k_memory_map[i].base = mem_chunk;
for (i=0; i<8; i++)
memcpy(mem_chunk + i*0x2000, cart.rom + 0x7e000, 0x2000);
cart.hw.realtec |= 2;
}
/* SVP chip */
if (svp)
svp_reset();
/* Lock-ON */
switch (config.lock_on)
{
case TYPE_GG:
ggenie_reset();
break;
case TYPE_AR:
datel_reset();
break;
case TYPE_SK:
if (cart.lock_on)
{
/* reset memory map */
for (i=0x00; i<0x20; i++)
m68k_memory_map[i].base = cart.rom + 0x700000 + (i<<16);
for (i=0x30; i<0x40; i++)
m68k_memory_map[i].base = cart.rom + (i<<16);
}
break;
default:
break;
}
/* save default cartridge slot mapping */
cart.base = m68k_memory_map[0].base;
}
/************************************************************ /************************************************************
MAPPER handlers MAPPER handlers
*************************************************************/ *************************************************************/
@ -458,7 +505,7 @@ void cart_hw_init()
/* /*
"official" ROM/RAM switch "official" ROM/RAM switch
*/ */
static inline void sega_mapper_w(uint32 address, uint32 data) static void sega_mapper_w(uint32 address, uint32 data)
{ {
uint32 i,slot = (address >> 1) & 7; uint32 i,slot = (address >> 1) & 7;
uint8 *src; uint8 *src;
@ -486,21 +533,36 @@ static inline void sega_mapper_w(uint32 address, uint32 data)
m68k_memory_map[0x20].write16 = NULL; m68k_memory_map[0x20].write16 = NULL;
zbank_memory_map[0x20].write = NULL; zbank_memory_map[0x20].write = NULL;
} }
if (cart.lock_on)
{
/* enable UPMEM chip at $300000-$3fffff */
for (i=0x30; i<0x40; i++)
m68k_memory_map[i].base = cart.rom + 0x600000 + (i<<16);
}
} }
else else
{ {
/* ROM enabled */ /* ROM enabled */
m68k_memory_map[0x20].base = cart_rom + 0x200000; m68k_memory_map[0x20].base = cart.rom + 0x200000;
if (cart.lock_on)
{
/* enable cartridge ROM at $300000-$3fffff */
for (i=0x30; i<0x40; i++)
m68k_memory_map[i].base = cart.rom + (i<<16);
}
} }
break; break;
default: default:
/* ROM Bankswitch (Super Street Fighter 2) /* ROM Bankswitch (Super Street Fighter 2)
documented by Bart Trzynadlowski (http://www.trzy.org/files/ssf2.txt) documented by Bart Trzynadlowski (http://www.trzy.org/files/ssf2.txt)
*/ */
slot = slot << 3; /* 8 x 512k banks */ slot = slot << 3; /* 8 x 512k banks */
src = cart_rom + (data << 19); src = cart.rom + (data << 19);
for (i=0; i<8; i++) m68k_memory_map[slot++].base = src + (i<<16); for (i=0; i<8; i++)
m68k_memory_map[slot++].base = src + (i<<16);
break; break;
} }
} }
@ -508,35 +570,33 @@ static inline void sega_mapper_w(uint32 address, uint32 data)
/* /*
custom ROM Bankswitch used by pirate "Multi-in-1" carts custom ROM Bankswitch used by pirate "Multi-in-1" carts
*/ */
static inline void multi_mapper_w(uint32 address, uint32 data) static void multi_mapper_w(uint32 address, uint32 data)
{ {
int i; int i;
cart_hw.bankshift = 1; cart.hw.bankshift = 1;
/* 64 x 64k banks */ /* 64 x 64k banks */
for (i=0; i<64; i++) for (i=0; i<64; i++)
{ m68k_memory_map[i].base = &cart.rom[((address++) & 0x3f) << 16];
m68k_memory_map[i].base = &cart_rom[((address++) & 0x3f) << 16];
}
} }
/* /*
Special ROM Bankswitch used for copy protection Special ROM Bankswitch used for copy protection
Used by unlicensed cartridges (Lion King III, Super King Kong 99) Used by unlicensed cartridges (Lion King III, Super King Kong 99)
*/ */
void special_mapper_w(uint32 address, uint32 data) static void special_mapper_w(uint32 address, uint32 data)
{ {
/* 1 x 32k bank */ /* 1 x 32k bank */
m68k_memory_map[0].base = mem_chunk; m68k_memory_map[0].base = mem_chunk;
memcpy(mem_chunk,&cart_rom[(data & 0x7f) << 15],0x8000); memcpy(mem_chunk,&cart.rom[(data & 0x7f) << 15],0x8000);
memcpy(mem_chunk+0x8000,cart_rom + 0x8000,0x8000); memcpy(mem_chunk+0x8000,cart.rom + 0x8000,0x8000);
} }
/* /*
Realtec ROM Bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter) Realtec ROM Bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter)
*/ */
void realtec_mapper_w(uint32 address, uint32 data) static void realtec_mapper_w(uint32 address, uint32 data)
{ {
int i; int i;
uint32 base; uint32 base;
@ -545,32 +605,32 @@ void realtec_mapper_w(uint32 address, uint32 data)
switch (address) switch (address)
{ {
case 0x404000: /* three lower bits of ROM base address */ case 0x404000: /* three lower bits of ROM base address */
cart_hw.regs[0] = data & 7; cart.hw.regs[0] = data & 7;
base = ((data & 7) | (cart_hw.regs[1] << 2)); base = ((data & 7) | (cart.hw.regs[1] << 2));
for (i=0; i<=cart_hw.regs[2]; i++) for (i=0; i<=cart.hw.regs[2]; i++)
{ {
m68k_memory_map[i*2].base = &cart_rom[((base + i)*2 & 0x3f) << 16]; m68k_memory_map[i*2].base = &cart.rom[((base + i)*2 & 0x3f) << 16];
m68k_memory_map[i*2+1].base = &cart_rom[(((base + i)*2 + 1) & 0x3f) << 16]; m68k_memory_map[i*2+1].base = &cart.rom[(((base + i)*2 + 1) & 0x3f) << 16];
} }
return; return;
case 0x400000: /* two higher bits of ROM base address */ case 0x400000: /* two higher bits of ROM base address */
cart_hw.regs[1] = data & 6; cart.hw.regs[1] = data & 6;
base = cart_hw.regs[0] | ((data & 6) << 2); base = cart.hw.regs[0] | ((data & 6) << 2);
for (i=0; i<=cart_hw.regs[2]; i++) for (i=0; i<=cart.hw.regs[2]; i++)
{ {
m68k_memory_map[i*2].base = &cart_rom[((base + i)*2 & 0x3f) << 16]; m68k_memory_map[i*2].base = &cart.rom[((base + i)*2 & 0x3f) << 16];
m68k_memory_map[i*2+1].base = &cart_rom[(((base + i)*2 + 1) & 0x3f) << 16]; m68k_memory_map[i*2+1].base = &cart.rom[(((base + i)*2 + 1) & 0x3f) << 16];
} }
return; return;
case 0x402000: /* number of 128k blocks to map */ case 0x402000: /* number of 128k blocks to map */
cart_hw.regs[2] = data & 0x1f; cart.hw.regs[2] = data & 0x1f;
base = cart_hw.regs[0] | (cart_hw.regs[1] << 2); base = cart.hw.regs[0] | (cart.hw.regs[1] << 2);
for (i=0; i<=(data & 0x1f); i++) for (i=0; i<=(data & 0x1f); i++)
{ {
m68k_memory_map[i*2].base = &cart_rom[((base + i)*2 & 0x3f) << 16]; m68k_memory_map[i*2].base = &cart.rom[((base + i)*2 & 0x3f) << 16];
m68k_memory_map[i*2+1].base = &cart_rom[(((base + i)*2 + 1) & 0x3f) << 16]; m68k_memory_map[i*2+1].base = &cart.rom[(((base + i)*2 + 1) & 0x3f) << 16];
} }
return; return;
@ -578,7 +638,7 @@ void realtec_mapper_w(uint32 address, uint32 data)
} }
/* Game no Kanzume Otokuyou ROM Mapper */ /* Game no Kanzume Otokuyou ROM Mapper */
void seganet_mapper_w(uint32 address, uint32 data) static void seganet_mapper_w(uint32 address, uint32 data)
{ {
if ((address & 0xff) == 0xf1) if ((address & 0xff) == 0xf1)
{ {
@ -609,16 +669,15 @@ void seganet_mapper_w(uint32 address, uint32 data)
/* /*
RADICA ROM Bankswitch (use !TIME) RADICA ROM Bankswitch (use !TIME)
*/ */
uint32 radica_mapper_r(uint32 address) static uint32 radica_mapper_r(uint32 address)
{ {
int i = 0; int i = 0;
address = (address >> 1); address = (address >> 1);
/* 64 x 64k banks */ /* 64 x 64k banks */
for (i = 0; i < 64; i++) for (i = 0; i < 64; i++)
{ m68k_memory_map[i].base = &cart.rom[((address++)& 0x3f)<< 16];
m68k_memory_map[i].base = &cart_rom[((address++)& 0x3f)<< 16];
}
return 0xff; return 0xff;
} }
@ -628,10 +687,13 @@ uint32 radica_mapper_r(uint32 address)
*************************************************************/ *************************************************************/
/* default ROM bankswitch */ /* default ROM bankswitch */
void default_time_w(uint32 address, uint32 data) static void default_time_w(uint32 address, uint32 data)
{ {
if ((address & 0xf1) == 0xf1) sega_mapper_w(address, data); if ((address & 0xf1) == 0xf1)
else if (address < 0xa13040) multi_mapper_w(address, data); sega_mapper_w(address, data);
else if (address < 0xa13040)
multi_mapper_w(address, data);
} }
@ -639,33 +701,31 @@ void default_time_w(uint32 address, uint32 data)
Internal register handlers Internal register handlers
*************************************************************/ *************************************************************/
uint32 default_regs_r(uint32 address) static uint32 default_regs_r(uint32 address)
{ {
int i; int i;
for (i=0; i<4; i++) for (i=0; i<4; i++)
{ {
if ((address & cart_hw.mask[i]) == cart_hw.addr[i]) if ((address & cart.hw.mask[i]) == cart.hw.addr[i])
return cart_hw.regs[i]; return cart.hw.regs[i];
} }
/* unused */ /* unused */
return 0xffff; return 0xffff;
} }
void default_regs_w(uint32 address, uint32 data) static void default_regs_w(uint32 address, uint32 data)
{ {
int i; int i;
for (i=0; i<4; i++) for (i=0; i<4; i++)
{ {
if ((address & cart_hw.mask[i]) == cart_hw.addr[i]) if ((address & cart.hw.mask[i]) == cart.hw.addr[i])
{ cart.hw.regs[i] = data;
cart_hw.regs[i] = data;
}
} }
} }
/* special register behaviour (Lion King III, Super Donkey Kong 99) */ /* special register behaviour (Lion King III, Super Donkey Kong 99) */
void special_regs_w(uint32 address, uint32 data) static void special_regs_w(uint32 address, uint32 data)
{ {
/* ROM bankswitch */ /* ROM bankswitch */
if ((address >> 16) > 0x6f) if ((address >> 16) > 0x6f)
@ -678,19 +738,19 @@ void special_regs_w(uint32 address, uint32 data)
default_regs_w(address, data); default_regs_w(address, data);
/* bitswapping (documented by Haze) */ /* bitswapping (documented by Haze) */
uint32 temp = cart_hw.regs[0]; uint32 temp = cart.hw.regs[0];
switch (cart_hw.regs[1]) switch (cart.hw.regs[1])
{ {
case 1: case 1:
cart_hw.regs[2] = (temp >> 1); cart.hw.regs[2] = (temp >> 1);
return; return;
case 2: case 2:
cart_hw.regs[2] = ((temp >> 4) | ((temp & 0x0F) << 4)); cart.hw.regs[2] = ((temp >> 4) | ((temp & 0x0F) << 4));
return; return;
default: default:
cart_hw.regs[2] = (((temp >> 7) & 0x01) | ((temp >> 5) & 0x02) | cart.hw.regs[2] = (((temp >> 7) & 0x01) | ((temp >> 5) & 0x02) |
((temp >> 3) & 0x04) | ((temp >> 1) & 0x08) | ((temp >> 3) & 0x04) | ((temp >> 1) & 0x08) |
((temp << 1) & 0x10) | ((temp << 3) & 0x20) | ((temp << 1) & 0x10) | ((temp << 3) & 0x20) |
((temp << 5) & 0x40) | ((temp << 7) & 0x80)); ((temp << 5) & 0x40) | ((temp << 7) & 0x80));

View File

@ -27,34 +27,42 @@
#ifndef _CART_HW_H_ #ifndef _CART_HW_H_
#define _CART_HW_H_ #define _CART_HW_H_
/* Lock-ON cartridge devices */ /* Lock-ON cartridge type */
#define GAME_GENIE 1 #define TYPE_GG 0x10 /* Game Genie */
#define ACTION_REPLAY 2 #define TYPE_AR 0x20 /* Action Replay (Pro) */
#define SONIC_KNUCKLES 3 #define TYPE_SK 0x40 /* Sonic & Knuckles */
/* Hardware description */ /* Cartridge extra hardware */
typedef struct typedef struct
{ {
uint8 regs[4]; /* internal registers (R/W) */ uint8 regs[4]; /* internal registers (R/W) */
uint32 mask[4]; /* registers address mask */ uint32 mask[4]; /* registers address mask */
uint32 addr[4]; /* registers address */ uint32 addr[4]; /* registers address */
uint32 realtec; /* bit 0: realtec mapper detected, bit 1: bootrom enabled */ uint32 realtec; /* bit 0: realtec mapper detected, bit 1: bootrom enabled */
uint32 bankshift; /* cartridge with bankshift mecanism */ uint16 jcart; /* cartridge with JCART port */
uint16 bankshift; /* cartridge with bankshift mecanism */
unsigned int (*time_r)(unsigned int address); /* !TIME signal ($a130xx) read handler */ unsigned int (*time_r)(unsigned int address); /* !TIME signal ($a130xx) read handler */
void (*time_w)(unsigned int address, unsigned int data); /* !TIME signal ($a130xx) write handler */ void (*time_w)(unsigned int address, unsigned int data); /* !TIME signal ($a130xx) write handler */
unsigned int (*regs_r)(unsigned int address); /* cart hardware region ($400000-$7fffff) read handler */ unsigned int (*regs_r)(unsigned int address); /* cart hardware registers read handler */
void (*regs_w)(unsigned int address, unsigned int data); /* cart hardware region ($400000-$7fffff) write handler */ void (*regs_w)(unsigned int address, unsigned int data); /* cart hardware registers write handler */
} T_CART_HW; } T_CART_HW;
/* Cartridge type */
typedef struct
{
uint8 *rom; /* ROM data */
uint8 *base; /* ROM area (slot 0) */
uint32 lock_on; /* 1: Lock-On enabled */
uint32 romsize; /* ROM size */
T_CART_HW hw; /* Custom hardware */
} T_CART;
/* global variables */ /* global variables */
extern T_CART_HW cart_hw; extern T_CART cart;
extern uint8 j_cart;
extern uint8 *default_rom;
extern int old_system[2];
/* Function prototypes */ /* Function prototypes */
extern void cart_hw_reset();
extern void cart_hw_init(); extern void cart_hw_init();
extern void cart_hw_reset();
#endif #endif

View File

@ -21,9 +21,9 @@
#include "shared.h" #include "shared.h"
#define TYPE_AR 1 #define TYPE_AR 0x01
#define TYPE_PRO1 2 #define TYPE_PRO1 0x02
#define TYPE_PRO2 3 #define TYPE_PRO2 0x03
static struct static struct
{ {
@ -145,7 +145,7 @@ void datel_switch(uint8 enable)
offset = action_replay.addr[i] >> 16; offset = action_replay.addr[i] >> 16;
if (offset < 0x40) /* cartridge ROM */ if (offset < 0x40) /* cartridge ROM */
action_replay.old[i] = *(uint16 *)(cart_rom + action_replay.addr[i]); action_replay.old[i] = *(uint16 *)(cart.rom + action_replay.addr[i]);
else if (offset >= 0xe0) /* Work RAM */ else if (offset >= 0xe0) /* Work RAM */
action_replay.old[i] = *(uint16 *)(work_ram + (action_replay.addr[i]&0xffff)); action_replay.old[i] = *(uint16 *)(work_ram + (action_replay.addr[i]&0xffff));
} }
@ -159,7 +159,7 @@ void datel_switch(uint8 enable)
offset = action_replay.addr[i] >> 16; offset = action_replay.addr[i] >> 16;
if (offset < 0x40) /* cartridge ROM */ if (offset < 0x40) /* cartridge ROM */
*(uint16 *)(cart_rom + action_replay.addr[i]) = action_replay.data[i]; *(uint16 *)(cart.rom + action_replay.addr[i]) = action_replay.data[i];
else if (offset >= 0xe0) /* Work RAM */ else if (offset >= 0xe0) /* Work RAM */
*(uint16 *)(work_ram + (action_replay.addr[i]&0xffff)) = action_replay.data[i]; *(uint16 *)(work_ram + (action_replay.addr[i]&0xffff)) = action_replay.data[i];
} }
@ -180,7 +180,7 @@ void datel_switch(uint8 enable)
if (action_replay.data[i]) if (action_replay.data[i])
{ {
if (action_replay.addr[i] < 0x400000) if (action_replay.addr[i] < 0x400000)
*(uint16 *)(cart_rom + action_replay.addr[i]) = action_replay.old[i]; *(uint16 *)(cart.rom + action_replay.addr[i]) = action_replay.old[i];
else if (action_replay.addr[i] >= 0xe00000) else if (action_replay.addr[i] >= 0xe00000)
*(uint16 *)(work_ram + (action_replay.addr[i]&0xffff)) = action_replay.old[i]; *(uint16 *)(work_ram + (action_replay.addr[i]&0xffff)) = action_replay.old[i];
} }
@ -253,6 +253,6 @@ static void ar_write_regs(uint32 address, uint32 data)
/* reads are mapped to Cartridge ROM */ /* reads are mapped to Cartridge ROM */
/* NOTE: codes should be disabled on startup */ /* NOTE: codes should be disabled on startup */
m68k_memory_map[0].base = cart_rom; m68k_memory_map[0].base = cart.rom;
} }
} }

View File

@ -27,7 +27,7 @@ T_EEPROM eeprom;
typedef struct typedef struct
{ {
char game_id[14]; char game_id[16];
uint16 chk; uint16 chk;
T_EEPROM_TYPE type; T_EEPROM_TYPE type;
} T_GAME_ENTRY; } T_GAME_ENTRY;

View File

@ -117,8 +117,8 @@ void ggenie_switch(uint8 enable)
/* save old value and patch ROM if enabled */ /* save old value and patch ROM if enabled */
if (ggenie.regs[0] & (1 << i)) if (ggenie.regs[0] & (1 << i))
{ {
ggenie.old[i] = *(uint16 *)(cart_rom + ggenie.addr[i]); ggenie.old[i] = *(uint16 *)(cart.rom + ggenie.addr[i]);
*(uint16 *)(cart_rom + ggenie.addr[i]) = ggenie.data[i]; *(uint16 *)(cart.rom + ggenie.addr[i]) = ggenie.data[i];
} }
} }
} }
@ -131,7 +131,7 @@ void ggenie_switch(uint8 enable)
/* patch is enabled ? */ /* patch is enabled ? */
if (ggenie.regs[0] & (1 << i)) if (ggenie.regs[0] & (1 << i))
{ {
*(uint16 *)(cart_rom + ggenie.addr[i]) = ggenie.old[i]; *(uint16 *)(cart.rom + ggenie.addr[i]) = ggenie.old[i];
} }
} }
} }
@ -203,7 +203,7 @@ static void ggenie_write_regs(uint8 offset, uint32 data, uint8 type)
if (data & 0x400) if (data & 0x400)
{ {
/* $0000-$7ffff reads mapped to Cartridge ROM */ /* $0000-$7ffff reads mapped to Cartridge ROM */
m68k_memory_map[0].base = cart_rom; m68k_memory_map[0].base = cart.rom;
} }
else else
{ {
@ -249,6 +249,6 @@ static void ggenie_write_regs(uint8 offset, uint32 data, uint8 type)
static uint32 ggenie_read_regs(uint32 address) static uint32 ggenie_read_regs(uint32 address)
{ {
if (address < 0x40) return ggenie.regs[address >> 1]; if (address < 0x40) return ggenie.regs[address >> 1];
else return *(uint16 *)(cart_rom + address); /* is that correct ? */ else return *(uint16 *)(cart.rom + address); /* is that correct ? */
} }

View File

@ -45,12 +45,12 @@ void sram_init()
memset (&sram.sram[0], 0xFF, 0x10000); memset (&sram.sram[0], 0xFF, 0x10000);
sram.crc = crc32 (0, &sram.sram[0], 0x10000); sram.crc = crc32 (0, &sram.sram[0], 0x10000);
if ((READ_BYTE(cart_rom,0x1b0) == 0x52) && (READ_BYTE(cart_rom,0x1b1) == 0x41)) if ((READ_BYTE(cart.rom,0x1b0) == 0x52) && (READ_BYTE(cart.rom,0x1b1) == 0x41))
{ {
/* retrieve informations from headezr */ /* retrieve informations from headezr */
sram.detected = 1; sram.detected = 1;
sram.start = READ_WORD_LONG(cart_rom, 0x1b4); sram.start = READ_WORD_LONG(cart.rom, 0x1b4);
sram.end = READ_WORD_LONG(cart_rom, 0x1b8); sram.end = READ_WORD_LONG(cart.rom, 0x1b8);
/* fixe some bad header informations */ /* fixe some bad header informations */
if ((sram.start > sram.end) || ((sram.end - sram.start) >= 0x10000)) if ((sram.start > sram.end) || ((sram.end - sram.start) >= 0x10000))
@ -66,7 +66,7 @@ void sram_init()
} }
/* set SRAM ON by default when ROM is not mapped */ /* set SRAM ON by default when ROM is not mapped */
if (genromsize <= sram.start) if (cart.romsize <= sram.start)
{ {
sram.on = 1; sram.on = 1;
sram.write = 1; sram.write = 1;

View File

@ -262,7 +262,7 @@
// how is low word really affected by these? // how is low word really affected by these?
// nearly sure 'ld A' doesn't affect flags // nearly sure 'ld A' doesn't affect flags
#define OP_LDA(x) \ #define OP_LDA(x) \
rA = x rA = x
#define OP_LDA32(x) \ #define OP_LDA32(x) \
rA32 = x rA32 = x
@ -326,16 +326,16 @@
UPD_ACC_ZN UPD_ACC_ZN
#define OP_CHECK32(OP) { \ #define OP_CHECK32(OP) { \
if ((op & 0x0f) == SSP_P) { /* A <- P */ \ if ((op & 0x0f) == SSP_P) { /* A <- P */ \
read_P(); /* update P */ \ read_P(); /* update P */ \
OP(rP.v); \ OP(rP.v); \
break; \ break; \
} \ } \
if ((op & 0x0f) == SSP_A) { /* A <- A */ \ if ((op & 0x0f) == SSP_A) { /* A <- A */ \
OP(rA32); \ OP(rA32); \
break; \ break; \
} \ } \
} }
@ -553,14 +553,14 @@ static u32 pm_io(int reg, int write, u32 d)
{ {
#ifdef LOG_SVP #ifdef LOG_SVP
elprintf(EL_SVP, "ssp ROM r [%06x] %04x", CADDR, elprintf(EL_SVP, "ssp ROM r [%06x] %04x", CADDR,
((unsigned short *)cart_rom)[addr|((mode&0xf)<<16)]); ((unsigned short *)cart.rom)[addr|((mode&0xf)<<16)]);
#endif #endif
/*if ((signed int)ssp->pmac_read[reg] >> 16 == -1) ssp->pmac_read[reg]++; /*if ((signed int)ssp->pmac_read[reg] >> 16 == -1) ssp->pmac_read[reg]++;
ssp->pmac_read[reg] += 1<<16;*/ ssp->pmac_read[reg] += 1<<16;*/
if ((signed int)(ssp->pmac_read[reg] & 0xffff) == -1) ssp->pmac_read[reg] += 1<<16; if ((signed int)(ssp->pmac_read[reg] & 0xffff) == -1) ssp->pmac_read[reg] += 1<<16;
ssp->pmac_read[reg] ++; ssp->pmac_read[reg] ++;
d = ((unsigned short *)cart_rom)[addr|((mode&0xf)<<16)]; d = ((unsigned short *)cart.rom)[addr|((mode&0xf)<<16)];
} }
else if ((mode & 0x47ff) == 0x0018) // DRAM else if ((mode & 0x47ff) == 0x0018) // DRAM
{ {
@ -1106,7 +1106,7 @@ void ssp1601_run(int cycles)
if (op == ((SSP_A<<4)|SSP_P)) { // A <- P if (op == ((SSP_A<<4)|SSP_P)) { // A <- P
// not sure. MAME claims that only hi word is transfered. // not sure. MAME claims that only hi word is transfered.
read_P(); // update P read_P(); // update P
rA32 = rP.v; rA32 = rP.v;
} }
else else
{ {
@ -1194,7 +1194,7 @@ void ssp1601_run(int cycles)
if (!(op&0x100)) elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: no b bit @ %04x", GET_PPC_OFFS()); if (!(op&0x100)) elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: no b bit @ %04x", GET_PPC_OFFS());
#endif #endif
read_P(); // update P read_P(); // update P
rA32 -= rP.v; // maybe only upper word? rA32 -= rP.v; // maybe only upper word?
UPD_ACC_ZN // there checking flags after this UPD_ACC_ZN // there checking flags after this
rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?) rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj
@ -1206,7 +1206,7 @@ void ssp1601_run(int cycles)
if (!(op&0x100)) elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: no b bit @ %04x", GET_PPC_OFFS()); if (!(op&0x100)) elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: no b bit @ %04x", GET_PPC_OFFS());
#endif #endif
read_P(); // update P read_P(); // update P
rA32 += rP.v; // confirmed to be 32bit rA32 += rP.v; // confirmed to be 32bit
UPD_ACC_ZN // ? UPD_ACC_ZN // ?
rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?) rX = ptr1_read_(op&3, 0, (op<<1)&0x18); // ri (maybe rj?)
rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); // rj

View File

@ -17,13 +17,13 @@ int16 SVP_cycles = 850;
void svp_init(void) void svp_init(void)
{ {
svp = (void *) ((char *)cart_rom + 0x200000); svp = (void *) ((char *)cart.rom + 0x200000);
memset(svp, 0, sizeof(*svp)); memset(svp, 0, sizeof(*svp));
} }
void svp_reset(void) void svp_reset(void)
{ {
memcpy(svp->iram_rom + 0x800, cart_rom + 0x800, 0x20000 - 0x800); memcpy(svp->iram_rom + 0x800, cart.rom + 0x800, 0x20000 - 0x800);
ssp1601_reset(&svp->ssp1601); ssp1601_reset(&svp->ssp1601);
} }

View File

@ -30,7 +30,7 @@ t_input input;
* *
*****************************************************************************/ *****************************************************************************/
/* H counter values for a 256-pixel wide display (342 pixel max.) */ /* H counter values for a 256-pixel wide display (342 pixel max.) */
static uint8 hc_256[171] = { static const uint8 hc_256[171] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
@ -46,7 +46,7 @@ static uint8 hc_256[171] = {
}; };
/* H counter values for a 320-pixel wide display (420 pixels max.) */ /* H counter values for a 320-pixel wide display (420 pixels max.) */
static uint8 hc_320[210] = { static const uint8 hc_320[210] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
@ -80,7 +80,7 @@ static inline void lightgun_update(int num)
/* External Interrupt ? */ /* External Interrupt ? */
if (reg[11] & 0x08) irq_status = (irq_status & ~0x40) | 0x12; if (reg[11] & 0x08) irq_status = (irq_status & ~0x40) | 0x12;
/* HVC Latch: /* Horizontal Counter Latch:
1) some games does not set HVC latch but instead use bigger X offset 1) some games does not set HVC latch but instead use bigger X offset
2) for games using H40 mode, the gun routine scales up the Hcounter value, 2) for games using H40 mode, the gun routine scales up the Hcounter value,
H-Counter range is approx. 292 pixel clocks H-Counter range is approx. 292 pixel clocks
@ -136,7 +136,7 @@ uint32 justifier_read()
* SEGA MOUSE specific functions * SEGA MOUSE specific functions
* *
*****************************************************************************/ *****************************************************************************/
struct mega_mouse static struct mega_mouse
{ {
uint8 State; uint8 State;
uint8 Counter; uint8 Counter;
@ -258,7 +258,7 @@ uint32 mouse_read()
* GAMEPAD specific functions (2PLAYERS/4WAYPLAY) * GAMEPAD specific functions (2PLAYERS/4WAYPLAY)
* *
*****************************************************************************/ *****************************************************************************/
struct pad static struct pad
{ {
uint8 State; uint8 State;
uint8 Counter; uint8 Counter;
@ -387,22 +387,19 @@ static inline void gamepad_write(uint32 i, uint32 data)
* TEAMPLAYER adapter * TEAMPLAYER adapter
* *
*****************************************************************************/ *****************************************************************************/
struct teamplayer static struct teamplayer
{ {
uint8 State; uint8 State;
uint8 Counter; uint8 Counter;
uint8 Table[12]; uint8 Table[12];
} teamplayer[2]; } teamplayer[2];
static inline void teamplayer_reset(uint32 port) static inline void teamplayer_init(uint32 port)
{ {
int i; int i;
int index = 0; int index = 0;
int pad_input = 0; int pad_input = 0;
teamplayer[port].State = 0x60; /* TH = 1, TR = 1 */
teamplayer[port].Counter = 0;
/* this table determines which gamepad input should be returned during acquisition sequence /* this table determines which gamepad input should be returned during acquisition sequence
index = teamplayer read table index: 0=1st read, 1=2nd read, ... index = teamplayer read table index: 0=1st read, 1=2nd read, ...
pad_input = gamepad input 0-14: 0=P1_DIR, 1=P1_SABC, 2=P1_MXYZ, 4=P2_DIR, 5=P2_SABC, ... pad_input = gamepad input 0-14: 0=P1_DIR, 1=P1_SABC, 2=P1_MXYZ, 4=P2_DIR, 5=P2_SABC, ...
@ -424,6 +421,12 @@ static inline void teamplayer_reset(uint32 port)
} }
} }
static inline void teamplayer_reset(uint32 port)
{
teamplayer[port].State = 0x60; /* TH = 1, TR = 1 */
teamplayer[port].Counter = 0;
}
/* SEGA teamplayer returns successively: /* SEGA teamplayer returns successively:
- PAD1 inputs - PAD1 inputs
- PAD2 inputs - PAD2 inputs
@ -603,7 +606,7 @@ void teamplayer_2_write (uint32 data)
uint32 jcart_read(uint32 address) uint32 jcart_read(uint32 address)
{ {
return (gamepad_read(5) | ((gamepad_read(6)&0x3f) << 8)); /* fixes Micro Machines 2 (is it correct ?) */ return (gamepad_read(5) | ((gamepad_read(6)&0x3f) << 8)); /* fixes Micro Machines 2 */
} }
void jcart_write(uint32 address, uint32 data) void jcart_write(uint32 address, uint32 data)
@ -617,12 +620,11 @@ void jcart_write(uint32 address, uint32 data)
* Generic INPUTS Control * Generic INPUTS Control
* *
*****************************************************************************/ *****************************************************************************/
void input_reset () void input_init ()
{ {
int i,j; int i,j;
input.max = 0; input.max = 0;
input.current = 0;
for (i=0; i<MAX_DEVICES; i++) for (i=0; i<MAX_DEVICES; i++)
{ {
@ -636,14 +638,12 @@ void input_reset ()
if (input.max == MAX_INPUTS) return; if (input.max == MAX_INPUTS) return;
input.dev[0] = config.input[input.max].padtype; input.dev[0] = config.input[input.max].padtype;
input.max ++; input.max ++;
gamepad_reset(0);
break; break;
case SYSTEM_MOUSE: case SYSTEM_MOUSE:
if (input.max == MAX_INPUTS) return; if (input.max == MAX_INPUTS) return;
input.dev[0] = DEVICE_MOUSE; input.dev[0] = DEVICE_MOUSE;
input.max ++; input.max ++;
mouse_reset();
break; break;
case SYSTEM_WAYPLAY: case SYSTEM_WAYPLAY:
@ -652,7 +652,6 @@ void input_reset ()
if (input.max == MAX_INPUTS) return; if (input.max == MAX_INPUTS) return;
input.dev[j] = config.input[input.max].padtype; input.dev[j] = config.input[input.max].padtype;
input.max ++; input.max ++;
gamepad_reset(j);
} }
break; break;
@ -663,7 +662,7 @@ void input_reset ()
input.dev[j] = config.input[input.max].padtype; input.dev[j] = config.input[input.max].padtype;
input.max ++; input.max ++;
} }
teamplayer_reset(0); teamplayer_init(0);
break; break;
} }
@ -673,20 +672,17 @@ void input_reset ()
if (input.max == MAX_INPUTS) return; if (input.max == MAX_INPUTS) return;
input.dev[4] = config.input[input.max].padtype; input.dev[4] = config.input[input.max].padtype;
input.max ++; input.max ++;
gamepad_reset(4);
break; break;
case SYSTEM_MOUSE: case SYSTEM_MOUSE:
if (input.max == MAX_INPUTS) return; if (input.max == MAX_INPUTS) return;
input.dev[4] = DEVICE_MOUSE; input.dev[4] = DEVICE_MOUSE;
input.max ++; input.max ++;
mouse_reset();
break; break;
case SYSTEM_MENACER: case SYSTEM_MENACER:
if (input.max == MAX_INPUTS) return; if (input.max == MAX_INPUTS) return;
input.dev[4] = DEVICE_LIGHTGUN; input.dev[4] = DEVICE_LIGHTGUN;
lightgun_reset(0);
break; break;
case SYSTEM_JUSTIFIER: case SYSTEM_JUSTIFIER:
@ -694,7 +690,6 @@ void input_reset ()
{ {
if (input.max == MAX_INPUTS) return; if (input.max == MAX_INPUTS) return;
input.dev[j] = DEVICE_LIGHTGUN; input.dev[j] = DEVICE_LIGHTGUN;
lightgun_reset(j - 4);
input.max ++; input.max ++;
} }
break; break;
@ -706,21 +701,54 @@ void input_reset ()
input.dev[j] = config.input[input.max].padtype; input.dev[j] = config.input[input.max].padtype;
input.max ++; input.max ++;
} }
teamplayer_reset(1); teamplayer_init(1);
break; break;
} }
/* J-CART: add two gamepad inputs */ /* J-CART: add two gamepad inputs */
if (j_cart) if (cart.hw.jcart)
{ {
input.dev[5] = config.input[2].padtype; input.dev[5] = config.input[2].padtype;
input.dev[6] = config.input[3].padtype; input.dev[6] = config.input[3].padtype;
gamepad_reset(5);
gamepad_reset(6);
} }
} }
void input_update() void input_reset(void)
{
/* Reset Controller device */
int i;
for (i=0; i<MAX_INPUTS; i++)
{
switch (input.dev[i])
{
case DEVICE_3BUTTON:
case DEVICE_6BUTTON:
gamepad_reset(i);
break;
case DEVICE_LIGHTGUN:
lightgun_reset(i%4);
break;
case DEVICE_MOUSE:
mouse_reset();
default:
break;
}
}
/* Team Player */
if (input.system[0] == SYSTEM_TEAMPLAYER)
teamplayer_reset(0);
if (input.system[1] == SYSTEM_TEAMPLAYER)
teamplayer_reset(1);
/* 4-Way Play */
input.current = 0;
}
void input_update(void)
{ {
int i; int i;
switch (input.system[0]) switch (input.system[0])
@ -754,7 +782,7 @@ void input_update()
} }
} }
void input_raz() void input_raz(void)
{ {
int i; int i;
switch (input.system[0]) switch (input.system[0])

View File

@ -64,17 +64,18 @@ typedef struct
uint32 pad[MAX_DEVICES]; /* Can be any of the INPUT_* bitmasks */ uint32 pad[MAX_DEVICES]; /* Can be any of the INPUT_* bitmasks */
uint8 system[2]; /* Can be any of the SYSTEM_* bitmasks */ uint8 system[2]; /* Can be any of the SYSTEM_* bitmasks */
uint8 max; /* maximum number of connected devices */ uint8 max; /* maximum number of connected devices */
uint8 current; /* current PAD number (4WAYPLAY) */ uint8 current; /* current PAD number (4-Way Play) */
int analog[3][2]; /* analog devices */ int analog[3][2]; /* analog devices */
int x_offset; int x_offset; /* gun horizontal offset */
int y_offset; int y_offset; /* gun vertical offset */
} t_input; } t_input;
/* Global variables */ /* Global variables */
extern t_input input; extern t_input input;
/* Function prototypes */ /* Function prototypes */
extern void input_reset (void); extern void input_init(void);
extern void input_reset(void);
extern void input_update(void); extern void input_update(void);
extern void input_raz(void); extern void input_raz(void);

View File

@ -25,34 +25,108 @@
uint8 io_reg[0x10]; uint8 io_reg[0x10];
uint8 region_code = REGION_USA; uint8 region_code = REGION_USA;
int old_system[2] = {-1,-1};
/***************************************************************************** static struct port_t
* I/O chip functions *
* *
*****************************************************************************/
struct port_t
{ {
void (*data_w)(uint32 data); void (*data_w)(uint32 data);
uint32 (*data_r)(void); uint32 (*data_r)(void);
} port[3]; } port[3];
void io_reset(void) /*****************************************************************************
* I/O chip functions *
* *
*****************************************************************************/
void io_init(void)
{ {
/* I/O register default settings */ /* restore previous setting */
uint8 io_def[0x10] = if (old_system[0] != -1) input.system[0] = old_system[0];
if (old_system[1] != -1) input.system[1] = old_system[1];
/* initialize default GUN settings */
input.x_offset = 0x00;
input.y_offset = 0x00;
/**********************************************
SEGA MENACER
***********************************************/
if (strstr(rominfo.international,"MENACER") != NULL)
{ {
0xA0, /* save current setting */
0x7F, 0x7F, 0x7F, if (old_system[0] == -1) old_system[0] = input.system[0];
0x00, 0x00, 0x00, if (old_system[1] == -1) old_system[1] = input.system[1];
0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00,
0xFB, 0x00, 0x00,
};
/* Initialize I/O registers */ input.system[0] = NO_SYSTEM;
memcpy (io_reg, io_def, 0x10); 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];
/* Initialize Port handlers */ 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
***********************************************/
else if (strstr(rominfo.international,"LETHAL ENFORCERSII") != 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
***********************************************/
if (cart.hw.jcart)
{
/* 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];
/* set default settings */
input.system[0] = SYSTEM_GAMEPAD;
input.system[1] = SYSTEM_GAMEPAD;
}
/**********************************************
Initialize IO Port handlers
***********************************************/
switch (input.system[0]) switch (input.system[0])
{ {
case SYSTEM_GAMEPAD: case SYSTEM_GAMEPAD:
@ -124,6 +198,27 @@ void io_reset(void)
port[2].data_r = NULL; port[2].data_r = NULL;
/* Initialize Input Devices */ /* Initialize Input Devices */
input_init();
}
void io_reset(void)
{
/* I/O register default settings */
uint8 io_def[0x10] =
{
0xA0,
0x7F, 0x7F, 0x7F,
0x00, 0x00, 0x00,
0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00,
0xFB, 0x00, 0x00,
};
/* Reset I/O registers */
memcpy (io_reg, io_def, 0x10);
/* Reset Input Devices */
input_reset(); input_reset();
} }

View File

@ -32,9 +32,10 @@
/* Global variables */ /* Global variables */
extern uint8 io_reg[0x10]; extern uint8 io_reg[0x10];
extern uint8 region_code; extern uint8 region_code;
extern uint8 pad_type; extern int old_system[2];
/* Function prototypes */ /* Function prototypes */
extern void io_init(void);
extern void io_reset(void); extern void io_reset(void);
extern void io_write(uint32 offset, uint32 value); extern void io_write(uint32 offset, uint32 value);
extern uint32 io_read(uint32 offset); extern uint32 io_read(uint32 offset);

View File

@ -23,7 +23,6 @@
#include "shared.h" #include "shared.h"
uint8 *cart_rom; /* CART rom */
uint8 bios_rom[0x10000]; /* BIOS rom */ uint8 bios_rom[0x10000]; /* BIOS rom */
uint8 work_ram[0x10000]; /* 68K work RAM */ uint8 work_ram[0x10000]; /* 68K work RAM */
uint8 zram[0x2000]; /* Z80 work RAM */ uint8 zram[0x2000]; /* Z80 work RAM */
@ -33,7 +32,6 @@ uint8 zbusack; /* /BUSACK to Z80 */
uint8 zirq; /* /IRQ to Z80 */ uint8 zirq; /* /IRQ to Z80 */
uint32 zbank; /* Address of Z80 bank window */ uint32 zbank; /* Address of Z80 bank window */
uint8 gen_running; uint8 gen_running;
uint32 genromsize;
int32 resetline; int32 resetline;
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@ -159,6 +157,11 @@ void gen_reset (uint32 hard_reset)
gen_running = 1; gen_running = 1;
resetline = -1; resetline = -1;
#ifdef NGC
/* register SOFTRESET */
SYS_SetResetCallback(set_softreset);
#endif
zreset = 0; /* Z80 is reset */ zreset = 0; /* Z80 is reset */
zbusreq = 0; /* Z80 has control of the Z bus */ zbusreq = 0; /* Z80 has control of the Z bus */
zbusack = 1; /* Z80 is busy using the Z bus */ zbusack = 1; /* Z80 is busy using the Z bus */
@ -169,11 +172,7 @@ void gen_reset (uint32 hard_reset)
m68k_pulse_reset (); m68k_pulse_reset ();
z80_reset (); z80_reset ();
YM2612ResetChip(); YM2612ResetChip();
SN76489_Reset();
#ifdef NGC
/* register SOFTRESET */
SYS_SetResetCallback(set_softreset);
#endif
} }
void gen_shutdown (void) void gen_shutdown (void)

View File

@ -25,7 +25,6 @@
#define _GENESIS_H_ #define _GENESIS_H_
/* Global variables */ /* Global variables */
extern uint8 *cart_rom;
extern uint8 bios_rom[0x10000]; extern uint8 bios_rom[0x10000];
extern uint8 work_ram[0x10000]; extern uint8 work_ram[0x10000];
extern uint8 zram[0x2000]; extern uint8 zram[0x2000];
@ -35,7 +34,6 @@ extern uint8 zreset;
extern uint8 zirq; extern uint8 zirq;
extern uint32 zbank; extern uint32 zbank;
extern uint8 gen_running; extern uint8 gen_running;
extern uint32 genromsize;
extern int32 resetline; extern int32 resetline;
/* Function prototypes */ /* Function prototypes */

View File

@ -83,6 +83,7 @@ void config_default(void)
config.addr_error = 1; config.addr_error = 1;
config.bios_enabled = 0; config.bios_enabled = 0;
config.lock_on = 0; config.lock_on = 0;
config.romtype = 0;
/* video options */ /* video options */
config.xshift = 0; config.xshift = 0;
@ -107,12 +108,7 @@ void config_default(void)
gx_input_SetDefault(); gx_input_SetDefault();
/* menu options */ /* menu options */
#ifdef HW_RVL
/* let's assume we always have a FAT device by default */
config.sram_auto = 0;
#else
config.sram_auto = -1; config.sram_auto = -1;
#endif
config.state_auto = -1; config.state_auto = -1;
config.bg_color = 0; config.bg_color = 0;
config.screen_w = 658; config.screen_w = 658;

View File

@ -46,6 +46,7 @@ typedef struct
uint8 addr_error; uint8 addr_error;
uint8 bios_enabled; uint8 bios_enabled;
uint8 lock_on; uint8 lock_on;
uint8 romtype;
int16 xshift; int16 xshift;
int16 yshift; int16 yshift;
int16 xscale; int16 xscale;

View File

@ -236,7 +236,7 @@ void memfile_autosave(s8 autosram, s8 autostate)
****************************************************************************/ ****************************************************************************/
int ManageSRAM (u8 direction, u8 device) int ManageSRAM (u8 direction, u8 device)
{ {
if (!genromsize) return 0; if (!cart.romsize) return 0;
char filename[MAXJOLIET]; char filename[MAXJOLIET];
@ -436,7 +436,7 @@ int ManageSRAM (u8 direction, u8 device)
****************************************************************************/ ****************************************************************************/
int ManageState (u8 direction, u8 device) int ManageState (u8 direction, u8 device)
{ {
if (!genromsize) return 0; if (!cart.romsize) return 0;
char filename[MAXJOLIET]; char filename[MAXJOLIET];

View File

@ -134,7 +134,7 @@ void decode_ggcodes ()
if (ggpatch[i].address < 0x400000) if (ggpatch[i].address < 0x400000)
{ {
/*** Patching ROM space ONLY (Game Genie does NOT have access to other memory areas) ***/ /*** Patching ROM space ONLY (Game Genie does NOT have access to other memory areas) ***/
if (cart_rom) *(uint16 *)(cart_rom + ggpatch[i].address) = ggpatch[i].data & 0xffff; if (cart.rom) *(uint16 *)(cart.rom + ggpatch[i].address) = ggpatch[i].data & 0xffff;
} }
} }
} }

View File

@ -734,7 +734,7 @@ static void soundmenu ()
case 0: case 0:
config.hq_fm ^= 1; config.hq_fm ^= 1;
sprintf (items[0].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF"); sprintf (items[0].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF");
if (genromsize) if (cart.romsize)
{ {
unsigned char *temp = memalign(32,YM2612GetContextSize()); unsigned char *temp = memalign(32,YM2612GetContextSize());
if (temp) memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize()); if (temp) memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
@ -850,8 +850,9 @@ static void systemmenu ()
sprintf (items[1].text, "System Lockups: %s", config.force_dtack ? "OFF" : "ON"); sprintf (items[1].text, "System Lockups: %s", config.force_dtack ? "OFF" : "ON");
sprintf (items[2].text, "68k Address Error: %s", config.addr_error ? "ON" : "OFF"); sprintf (items[2].text, "68k Address Error: %s", config.addr_error ? "ON" : "OFF");
sprintf (items[3].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF"); sprintf (items[3].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF");
if (config.lock_on == GAME_GENIE) sprintf (items[4].text, "Lock-On: GAME GENIE"); if (config.lock_on == TYPE_GG) sprintf (items[4].text, "Lock-On: GAME GENIE");
else if (config.lock_on == ACTION_REPLAY) sprintf (items[4].text, "Lock-On: ACTION REPLAY"); else if (config.lock_on == TYPE_AR) sprintf (items[4].text, "Lock-On: ACTION REPLAY");
else if (config.lock_on == TYPE_SK) sprintf (items[4].text, "Lock-On: SONIC & KNUCKLES");
else sprintf (items[4].text, "Lock-On: OFF"); else sprintf (items[4].text, "Lock-On: OFF");
if (svp) if (svp)
@ -880,7 +881,7 @@ static void systemmenu ()
else if (config.region_detect == 1) sprintf (items[0].text, "Console Region: USA"); else if (config.region_detect == 1) sprintf (items[0].text, "Console Region: USA");
else if (config.region_detect == 2) sprintf (items[0].text, "Console Region: EUR"); else if (config.region_detect == 2) sprintf (items[0].text, "Console Region: EUR");
else if (config.region_detect == 3) sprintf (items[0].text, "Console Region: JAP"); else if (config.region_detect == 3) sprintf (items[0].text, "Console Region: JAP");
if (genromsize) if (cart.romsize)
{ {
/* force region & cpu mode */ /* force region & cpu mode */
set_region(); set_region();
@ -921,7 +922,7 @@ static void systemmenu ()
case 3: /*** BIOS support ***/ case 3: /*** BIOS support ***/
config.bios_enabled ^= 1; config.bios_enabled ^= 1;
sprintf (items[3].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF"); sprintf (items[3].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF");
if (genromsize) if (cart.romsize)
{ {
system_init (); system_init ();
system_reset (); system_reset ();
@ -930,10 +931,12 @@ static void systemmenu ()
case 4: /*** Cart Lock-On ***/ case 4: /*** Cart Lock-On ***/
config.lock_on++; config.lock_on++;
if (config.lock_on == GAME_GENIE) sprintf (items[4].text, "Lock-On: GAME GENIE"); if (config.lock_on > TYPE_SK) config.lock_on = 0;
else if (config.lock_on == ACTION_REPLAY) sprintf (items[4].text, "Lock-On: ACTION REPLAY"); if (config.lock_on == TYPE_GG) sprintf (items[4].text, "Lock-On: GAME GENIE");
else if (config.lock_on == TYPE_AR) sprintf (items[4].text, "Lock-On: ACTION REPLAY");
else if (config.lock_on == TYPE_SK) sprintf (items[4].text, "Lock-On: SONIC & KNUCKLES");
else sprintf (items[4].text, "Lock-On: OFF"); else sprintf (items[4].text, "Lock-On: OFF");
if (genromsize) if (cart.romsize)
{ {
system_reset (); /* clear any patches first */ system_reset (); /* clear any patches first */
system_init (); system_init ();
@ -1113,7 +1116,7 @@ static void ctrlmenu_raz(void)
m->buttons[i+2].data = &button_player_data; m->buttons[i+2].data = &button_player_data;
m->buttons[i+2].state |= BUTTON_ACTIVE; m->buttons[i+2].state |= BUTTON_ACTIVE;
sprintf(m->items[i+2].text,"%d",max + 1); sprintf(m->items[i+2].text,"%d",max + 1);
if (j_cart && (i > 4)) if (cart.hw.jcart && (i > 4))
sprintf(m->items[i+2].comment,"Configure Player %d (J-CART) settings", max + 1); sprintf(m->items[i+2].comment,"Configure Player %d (J-CART) settings", max + 1);
else else
sprintf(m->items[i+2].comment,"Configure Player %d settings", max + 1); sprintf(m->items[i+2].comment,"Configure Player %d settings", max + 1);
@ -1291,7 +1294,7 @@ static void ctrlmenu(void)
switch (m->selected) switch (m->selected)
{ {
case 0: /* update port 1 system */ case 0: /* update port 1 system */
if (j_cart) break; if (cart.hw.jcart) break;
if (input.system[0] == SYSTEM_MOUSE) input.system[0] +=3; /* lightguns are never used on Port 1 */ if (input.system[0] == SYSTEM_MOUSE) input.system[0] +=3; /* lightguns are never used on Port 1 */
else input.system[0] ++; else input.system[0] ++;
if ((input.system[0] == SYSTEM_MOUSE) && (input.system[1] == SYSTEM_MOUSE)) input.system[0] +=3; if ((input.system[0] == SYSTEM_MOUSE) && (input.system[1] == SYSTEM_MOUSE)) input.system[0] +=3;
@ -1339,7 +1342,7 @@ static void ctrlmenu(void)
break; break;
case 1: /* update port 2 system */ case 1: /* update port 2 system */
if (j_cart) break; if (cart.hw.jcart) break;
input.system[1] ++; input.system[1] ++;
if ((input.system[0] == SYSTEM_MOUSE) && (input.system[1] == SYSTEM_MOUSE)) input.system[1] ++; if ((input.system[0] == SYSTEM_MOUSE) && (input.system[1] == SYSTEM_MOUSE)) input.system[1] ++;
if (input.system[1] == SYSTEM_WAYPLAY) input.system[0] = SYSTEM_WAYPLAY; if (input.system[1] == SYSTEM_WAYPLAY) input.system[0] = SYSTEM_WAYPLAY;
@ -1466,7 +1469,7 @@ static void ctrlmenu(void)
GUI_DrawMenuFX(m, 20, 0); GUI_DrawMenuFX(m, 20, 0);
/* update title */ /* update title */
if (j_cart && (player > 1)) if (cart.hw.jcart && (player > 1))
sprintf(m->title,"Controller Settings (Player %d) (J-CART)",player+1); sprintf(m->title,"Controller Settings (Player %d) (J-CART)",player+1);
else else
sprintf(m->title,"Controller Settings (Player %d)",player+1); sprintf(m->title,"Controller Settings (Player %d)",player+1);
@ -1911,7 +1914,7 @@ static int loadmenu ()
if (DVD_Open()) if (DVD_Open())
{ {
GUI_DeleteMenu(m); GUI_DeleteMenu(m);
size = FileSelector(cart_rom,0); size = FileSelector(cart.rom,0);
if (size) return 1; if (size) return 1;
GUI_InitMenu(m); GUI_InitMenu(m);
} }
@ -1922,7 +1925,7 @@ static int loadmenu ()
if (FAT_Open(ret)) if (FAT_Open(ret))
{ {
GUI_DeleteMenu(m); GUI_DeleteMenu(m);
size = FileSelector(cart_rom,1); size = FileSelector(cart.rom,1);
if (size) return 1; if (size) return 1;
GUI_InitMenu(m); GUI_InitMenu(m);
} }
@ -2095,7 +2098,7 @@ void MainMenu (void)
if (!rom_loaded) if (!rom_loaded)
{ {
/* check if a game is running */ /* check if a game is running */
if (genromsize) if (cart.romsize)
{ {
m->screenshot = 1; m->screenshot = 1;
m->bg_images[0].state &= ~IMAGE_VISIBLE; m->bg_images[0].state &= ~IMAGE_VISIBLE;
@ -2124,7 +2127,7 @@ void MainMenu (void)
{ {
case -1: /*** Return to Game ***/ case -1: /*** Return to Game ***/
case 6: case 6:
if (!genromsize) break; if (!cart.romsize) break;
GUI_DrawMenuFX(m,10,1); GUI_DrawMenuFX(m,10,1);
GUI_DeleteMenu(m); GUI_DeleteMenu(m);
quit = 1; quit = 1;
@ -2178,7 +2181,7 @@ void MainMenu (void)
break; break;
case 3: /*** Memory Manager ***/ case 3: /*** Memory Manager ***/
if (!genromsize) break; if (!cart.romsize) break;
GUI_DeleteMenu(m); GUI_DeleteMenu(m);
quit = filemenu (); quit = filemenu ();
if (quit) break; if (quit) break;
@ -2186,7 +2189,7 @@ void MainMenu (void)
break; break;
case 4: /*** Emulator Reset ***/ case 4: /*** Emulator Reset ***/
if (!genromsize) break; if (!cart.romsize) break;
GUI_DrawMenuFX(m,10,1); GUI_DrawMenuFX(m,10,1);
GUI_DeleteMenu(m); GUI_DeleteMenu(m);
gxClearScreen ((GXColor)BLACK); gxClearScreen ((GXColor)BLACK);
@ -2196,19 +2199,19 @@ void MainMenu (void)
break; break;
case 5: /*** Game Genie ***/ case 5: /*** Game Genie ***/
if (!genromsize) break; if (!cart.romsize) break;
GUI_DeleteMenu(m); GUI_DeleteMenu(m);
GetGGEntries(); GetGGEntries();
GUI_InitMenu(m); GUI_InitMenu(m);
break; break;
case 7: /*** ROM Captrure ***/ case 7: /*** ROM Captrure ***/
if (!genromsize) break; if (!cart.romsize) break;
gx_video_Capture(); gx_video_Capture();
break; break;
case 8: /*** ROM Information ***/ case 8: /*** ROM Information ***/
if (!genromsize) break; if (!cart.romsize) break;
GUI_DeleteMenu(m); GUI_DeleteMenu(m);
showrominfo (); showrominfo ();
GUI_InitMenu(m); GUI_InitMenu(m);

View File

@ -1442,11 +1442,11 @@ void gx_video_Init(void)
*/ */
int *romptr = (int *)0x80700000; int *romptr = (int *)0x80700000;
StartARAM(); StartARAM();
genromsize = 0; cart.romsize = 0;
if (memcmp((char *)romptr,"GENPLUSR",8) == 0) if (memcmp((char *)romptr,"GENPLUSR",8) == 0)
{ {
genromsize = romptr[2]; cart.romsize = romptr[2];
ARAMPut((char *) 0x80700000 + 0x20, (char *) 0x8000, genromsize); ARAMPut((char *) 0x80700000 + 0x20, (char *) 0x8000, cart.romsize);
} }
/* Get the current VIDEO mode then : /* Get the current VIDEO mode then :

View File

@ -79,8 +79,8 @@ static void load_bios(void)
static void init_machine(void) static void init_machine(void)
{ {
/* Allocate cart_rom here ( 10 MBytes ) */ /* Allocate cart_rom here ( 10 MBytes ) */
cart_rom = memalign(32, MAXROMSIZE); cart.rom = memalign(32, MAXROMSIZE);
if (!cart_rom) if (!cart.rom)
{ {
FONT_writeCenter("Failed to allocate ROM buffer... Rebooting",18,0,640,200,(GXColor)WHITE); FONT_writeCenter("Failed to allocate ROM buffer... Rebooting",18,0,640,200,(GXColor)WHITE);
gxSetScreen(); gxSetScreen();
@ -121,7 +121,7 @@ static void init_machine(void)
***************************************************/ ***************************************************/
void reloadrom (int size, char *name) void reloadrom (int size, char *name)
{ {
genromsize = size; cart.romsize = size;
load_rom(name); /* Load ROM */ load_rom(name); /* Load ROM */
system_init (); /* Initialize System */ system_init (); /* Initialize System */
audio_init(48000); /* Audio System initialization */ audio_init(48000); /* Audio System initialization */
@ -138,7 +138,7 @@ void shutdown(void)
memfile_autosave(-1,config.state_auto); memfile_autosave(-1,config.state_auto);
system_shutdown(); system_shutdown();
audio_shutdown(); audio_shutdown();
free(cart_rom); free(cart.rom);
gx_audio_Shutdown(); gx_audio_Shutdown();
gx_video_Shutdown(); gx_video_Shutdown();
#ifdef HW_RVL #ifdef HW_RVL
@ -212,10 +212,10 @@ int main (int argc, char *argv[])
init_machine(); init_machine();
/* run any injected rom */ /* run any injected rom */
if (genromsize) if (cart.romsize)
{ {
ARAMFetch((char *)cart_rom, (void *)0x8000, genromsize); ARAMFetch((char *)cart.rom, (void *)0x8000, cart.romsize);
reloadrom (genromsize,"INJECT.bin"); reloadrom (cart.romsize,"INJECT.bin");
gx_video_Start(); gx_video_Start();
gx_audio_Start(); gx_audio_Start();
frameticker = 1; frameticker = 1;

View File

@ -29,11 +29,13 @@
#define GG_ROM "/genplus/ggenie.bin" #define GG_ROM "/genplus/ggenie.bin"
#define AR_ROM "/genplus/areplay.bin" #define AR_ROM "/genplus/areplay.bin"
#define OS_ROM "/genplus/bios.bin" #define OS_ROM "/genplus/bios.bin"
#define SK_ROM "/genplus/sk.bin"
#define SK_UPMEM "/genplus/sk2chip.bin"
#ifdef HW_RVL #ifdef HW_RVL
#define VERSION "version 1.3.3W" #define VERSION "version 1.4.0W"
#else #else
#define VERSION "version 1.3.3G" #define VERSION "version 1.4.0G"
#endif #endif
/* globals */ /* globals */

View File

@ -225,7 +225,7 @@ static void getrominfo (char *romheader)
memcpy (&rominfo.memo, romheader + ROMMEMO, 40); memcpy (&rominfo.memo, romheader + ROMMEMO, 40);
memcpy (&rominfo.country, romheader + ROMCOUNTRY, 16); memcpy (&rominfo.country, romheader + ROMCOUNTRY, 16);
realchecksum = GetRealChecksum (((uint8 *) cart_rom) + 0x200, genromsize - 0x200); realchecksum = GetRealChecksum (((uint8 *) cart.rom) + 0x200, cart.romsize - 0x200);
#ifdef LSB_FIRST #ifdef LSB_FIRST
rominfo.checksum = (rominfo.checksum >> 8) | ((rominfo.checksum & 0xff) << 8); rominfo.checksum = (rominfo.checksum >> 8) | ((rominfo.checksum & 0xff) << 8);
#endif #endif
@ -256,49 +256,49 @@ int load_rom(char *filename)
int i, size, offset = 0; int i, size, offset = 0;
#ifdef NGC #ifdef NGC
size = genromsize; size = cart.romsize;
sprintf(rom_filename,"%s",filename); sprintf(rom_filename,"%s",filename);
rom_filename[strlen(rom_filename) - 4] = 0; rom_filename[strlen(rom_filename) - 4] = 0;
#else #else
uint8 *ptr; uint8 *ptr;
ptr = load_archive(filename, &size); ptr = load_archive(filename, &size);
if(!ptr) return (0); if(!ptr) return (0);
memcpy(cart_rom, ptr + offset, size); memcpy(cart.rom, ptr + offset, size);
free(ptr); free(ptr);
#endif #endif
/* detect interleaved roms (.smd format) */ /* detect interleaved roms (.smd format) */
if (strncmp((char *)(cart_rom + 0x100),"SEGA", 4) && ((size / 512) & 1)) if (strncmp((char *)(cart.rom + 0x100),"SEGA", 4) && ((size / 512) & 1))
{ {
size -= 512; size -= 512;
offset += 512; offset += 512;
for (i = 0; i < (size / 0x4000); i += 1) for (i = 0; i < (size / 0x4000); i += 1)
{ {
deinterleave_block (cart_rom + offset + (i * 0x4000)); deinterleave_block (cart.rom + offset + (i * 0x4000));
} }
memcpy(cart_rom, cart_rom + offset, size); memcpy(cart.rom, cart.rom + offset, size);
} }
/* max. 10 MBytes supported */ /* max. 10 MBytes supported */
if (size > MAXROMSIZE) size = MAXROMSIZE; if (size > MAXROMSIZE) size = MAXROMSIZE;
genromsize = size; cart.romsize = size;
/* clear unused ROM space */ /* clear unused ROM space */
if (size < MAXROMSIZE) memset (cart_rom + size, 0x00, MAXROMSIZE - size); memset (cart.rom + size, 0xff, MAXROMSIZE - size);
getrominfo((char *)cart_rom); /* get infos from ROM header */ getrominfo((char *)cart.rom); /* get infos from ROM header */
set_region(); /* set game region (PAL/NTSC, JAP/USA/EUR) */ set_region(); /* set game region (PAL/NTSC, JAP/USA/EUR) */
#ifdef LSB_FIRST #ifdef LSB_FIRST
/* Byteswap ROM */ /* Byteswap ROM */
uint8 temp; uint8 temp;
for(i = 0; i < genromsize; i += 2) for(i = 0; i < size; i += 2)
{ {
temp = cart_rom[i]; temp = cart.rom[i];
cart_rom[i] = cart_rom[i+1]; cart.rom[i] = cart.rom[i+1];
cart_rom[i+1] = temp; cart.rom[i+1] = temp;
} }
#endif #endif
@ -307,11 +307,11 @@ int load_rom(char *filename)
((strstr(rominfo.product,"-K0109") != NULL) && (rominfo.checksum == 0x4f10))) ((strstr(rominfo.product,"-K0109") != NULL) && (rominfo.checksum == 0x4f10)))
{ {
uint8 temp; uint8 temp;
for(i = 0; i < genromsize; i += 2) for(i = 0; i < size; i += 2)
{ {
temp = cart_rom[i]; temp = cart.rom[i];
cart_rom[i] = cart_rom[i+1]; cart.rom[i] = cart.rom[i+1];
cart_rom[i+1] = temp; cart.rom[i+1] = temp;
} }
} }

View File

@ -112,13 +112,13 @@ static int pico_page[7] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F};
uint32 eeprom_read_byte(uint32 address) uint32 eeprom_read_byte(uint32 address)
{ {
if (address == eeprom.type.sda_out_adr) return eeprom_read(address, 0); if (address == eeprom.type.sda_out_adr) return eeprom_read(address, 0);
else return READ_BYTE(cart_rom, address); else return READ_BYTE(cart.rom, address);
} }
uint32 eeprom_read_word(uint32 address) uint32 eeprom_read_word(uint32 address)
{ {
if (address == (eeprom.type.sda_out_adr & 0xfffffe)) return eeprom_read(address, 1); if (address == (eeprom.type.sda_out_adr & 0xfffffe)) return eeprom_read(address, 1);
else return *(uint16 *)(cart_rom + address); else return *(uint16 *)(cart.rom + address);
} }
void eeprom_write_byte(uint32 address, uint32 data) void eeprom_write_byte(uint32 address, uint32 data)
@ -270,7 +270,8 @@ uint32 ctrl_io_read_byte(uint32 address)
else return ((m68k_read_pcrelative_8(REG_PC) & 0xfe) | zbusack); else return ((m68k_read_pcrelative_8(REG_PC) & 0xfe) | zbusack);
case 0x30: /* TIME */ case 0x30: /* TIME */
if (cart_hw.time_r) return cart_hw.time_r(address); if (cart.hw.time_r)
return ((address & 1) ? (cart.hw.time_r(address) & 0xff) : (cart.hw.time_r(address) >> 8));
else return m68k_read_bus_8(address); else return m68k_read_bus_8(address);
case 0x10: /* MEMORY MODE */ case 0x10: /* MEMORY MODE */
@ -302,7 +303,7 @@ uint32 ctrl_io_read_word(uint32 address)
return ((m68k_read_pcrelative_16(REG_PC) & 0xfeff) | (zbusack << 8)); return ((m68k_read_pcrelative_16(REG_PC) & 0xfeff) | (zbusack << 8));
case 0x30: /* TIME */ case 0x30: /* TIME */
if (cart_hw.time_r) return cart_hw.time_r(address); if (cart.hw.time_r) return cart.hw.time_r(address);
else return m68k_read_bus_16(address); else return m68k_read_bus_16(address);
case 0x50: /* SVP */ case 0x50: /* SVP */
@ -351,20 +352,20 @@ void ctrl_io_write_byte(uint32 address, uint32 data)
return; return;
case 0x30: /* TIME */ case 0x30: /* TIME */
cart_hw.time_w(address, data); cart.hw.time_w(address, data);
return; return;
case 0x41: /* BOOTROM */ case 0x41: /* BOOTROM */
if (address & 1) if (address & 1)
{ {
m68k_memory_map[0].base = (data & 1) ? default_rom : bios_rom; m68k_memory_map[0].base = (data & 1) ? cart.base : bios_rom;
/* autodetect BIOS ROM file */ /* autodetect BIOS ROM file */
if (!(config.bios_enabled & 2)) if (!(config.bios_enabled & 2))
{ {
config.bios_enabled |= 2; config.bios_enabled |= 2;
memcpy(bios_rom, cart_rom, 0x800); memcpy(bios_rom, cart.rom, 0x800);
memset(cart_rom, 0, genromsize); memset(cart.rom, 0xff, cart.romsize);
} }
} }
else m68k_unused_8_w (address, data); else m68k_unused_8_w (address, data);
@ -417,20 +418,20 @@ void ctrl_io_write_word(uint32 address, uint32 data)
return; return;
case 0x30: /* TIME */ case 0x30: /* TIME */
cart_hw.time_w(address & 0xfe, data >> 8); cart.hw.time_w(address & 0xfe, data >> 8);
cart_hw.time_w(address, data & 0xff); cart.hw.time_w(address, data & 0xff);
return; return;
case 0x41: /* BOOTROM */ case 0x41: /* BOOTROM */
m68k_memory_map[0].base = (data & 1) ? default_rom : bios_rom; m68k_memory_map[0].base = (data & 1) ? cart.base : bios_rom;
/* autodetect BIOS ROM file */ /* autodetect BIOS ROM file */
if (!(config.bios_enabled & 2)) if (!(config.bios_enabled & 2))
{ {
config.bios_enabled |= 2; config.bios_enabled |= 2;
memcpy(bios_rom, cart_rom, 0x800); memcpy(bios_rom, cart.rom, 0x800);
memset(cart_rom, 0, genromsize); memset(cart.rom, 0xff, cart.romsize);
} }
return; return;

View File

@ -73,7 +73,8 @@ uint32 zbank_read_ctrl_io(uint32 address)
else return (0xfe | zbusack); else return (0xfe | zbusack);
case 0x30: /* TIME */ case 0x30: /* TIME */
if (cart_hw.time_r) return cart_hw.time_r(address); if (cart.hw.time_r)
return ((address & 1) ? (cart.hw.time_r(address) & 0xff) : (cart.hw.time_r(address) >> 8));
else return zbank_unused_r(address); else return zbank_unused_r(address);
case 0x10: /* MEMORY MODE */ case 0x10: /* MEMORY MODE */
@ -110,21 +111,20 @@ void zbank_write_ctrl_io(uint32 address, uint32 data)
return; return;
case 0x30: /* TIME */ case 0x30: /* TIME */
if (cart_hw.time_w) cart_hw.time_w(address, data); cart.hw.time_w(address, data);
else zbank_unused_w(address, data);
return; return;
case 0x41: /* BOOTROM */ case 0x41: /* BOOTROM */
if (address & 1) if (address & 1)
{ {
m68k_memory_map[0].base = (data & 1) ? default_rom : bios_rom; m68k_memory_map[0].base = (data & 1) ? cart.base : bios_rom;
/* autodetect BIOS ROM file */ /* autodetect BIOS ROM file */
if (!(config.bios_enabled & 2)) if (!(config.bios_enabled & 2))
{ {
config.bios_enabled |= 2; config.bios_enabled |= 2;
memcpy(bios_rom, cart_rom, 0x800); memcpy(bios_rom, cart.rom, 0x800);
memset(cart_rom, 0, genromsize); memset(cart.rom, 0xff, cart.romsize);
} }
} }
else zbank_unused_w (address, data); else zbank_unused_w (address, data);

View File

@ -54,7 +54,7 @@ int state_load(unsigned char *buffer)
/* reset system */ /* reset system */
system_reset(); system_reset();
m68k_memory_map[0].base = default_rom; m68k_memory_map[0].base = cart.base;
// GENESIS // GENESIS
load_param(work_ram, sizeof(work_ram)); load_param(work_ram, sizeof(work_ram));

View File

@ -204,10 +204,14 @@ void audio_shutdown(void)
****************************************************************/ ****************************************************************/
void system_init (void) void system_init (void)
{ {
/* Cartridge hardware (should be done first !) */
cart_hw_init();
/* Genesis hardware */
gen_init (); gen_init ();
vdp_init (); vdp_init ();
render_init (); render_init ();
cart_hw_init(); io_init();
} }
/**************************************************************** /****************************************************************
@ -215,15 +219,14 @@ void system_init (void)
****************************************************************/ ****************************************************************/
void system_reset (void) void system_reset (void)
{ {
/* Cartridge Hardware (should be done first !) */ /* Cartridge hardware (should be done first !) */
cart_hw_reset(); cart_hw_reset();
/* Genesis Hardware */ /* Genesis hardware */
gen_reset (1); gen_reset (1);
vdp_reset (); vdp_reset ();
render_reset (); render_reset ();
io_reset(); io_reset();
SN76489_Reset();
/* Clear Sound Buffers */ /* Clear Sound Buffers */
if (snd.psg.buffer) memset (snd.psg.buffer, 0, SND_SIZE); if (snd.psg.buffer) memset (snd.psg.buffer, 0, SND_SIZE);

View File

@ -66,8 +66,8 @@ int main (int argc, char *argv[])
} }
error_init(); error_init();
cart_rom = malloc(0xA00000); cart.rom = malloc(0xA00000);
memset(cart_rom, 0, 0xA00000); memset(cart.rom, 0, 0xA00000);
if(!load_rom(argv[1])) if(!load_rom(argv[1]))
{ {
@ -146,7 +146,7 @@ int main (int argc, char *argv[])
trash_machine(); trash_machine();
system_shutdown(); system_shutdown();
error_shutdown(); error_shutdown();
free(cart_rom); free(cart.rom);
return (0); return (0);
} }

View File

@ -11,9 +11,11 @@ void set_config_defaults(void)
/* sound options */ /* sound options */
config.psg_preamp = 150; config.psg_preamp = 150;
config.fm_preamp = 100; config.fm_preamp = 100;
config.hq_fm = 1; config.hq_fm = 0;
config.psgBoostNoise = 0; config.psgBoostNoise = 0;
config.filter = 1; config.filter = 1;
config.low_freq = 200;
config.high_freq = 8000;
config.lg = 1.0; config.lg = 1.0;
config.mg = 1.0; config.mg = 1.0;
config.hg = 1.0; config.hg = 1.0;
@ -21,11 +23,14 @@ void set_config_defaults(void)
/* system options */ /* system options */
config.region_detect = 0; config.region_detect = 0;
config.force_dtack = 0; config.force_dtack = 0;
config.addr_error = 0;
config.bios_enabled = 0; config.bios_enabled = 0;
config.lock_on = 0;
config.romtype = 0;
/* display options */ /* display options */
config.overscan = 1; config.overscan = 1;
config.render = 1; config.render = 0;
/* controllers options */ /* controllers options */
input.system[0] = SYSTEM_GAMEPAD; input.system[0] = SYSTEM_GAMEPAD;

View File

@ -18,12 +18,17 @@ typedef struct
int32 psg_preamp; int32 psg_preamp;
int32 fm_preamp; int32 fm_preamp;
uint8 filter; uint8 filter;
uint16 low_freq;
uint16 high_freq;
float lg; float lg;
float mg; float mg;
float hg; float hg;
uint8 region_detect; uint8 region_detect;
uint8 force_dtack; uint8 force_dtack;
uint8 addr_error;
uint8 bios_enabled; uint8 bios_enabled;
uint8 lock_on;
uint8 romtype;
uint8 overscan; uint8 overscan;
uint8 render; uint8 render;
uint8 ntsc; uint8 ntsc;

View File

@ -133,7 +133,7 @@ Uint32 fps_callback(Uint32 interval)
if (region_code == REGION_USA) sprintf(region,"USA"); if (region_code == REGION_USA) sprintf(region,"USA");
else if (region_code == REGION_EUROPE) sprintf(region,"EUR"); else if (region_code == REGION_EUROPE) sprintf(region,"EUR");
else sprintf(region,"JAP"); else sprintf(region,"JAP");
sprintf(caption, "Genesis Plus/SDL - %s (%s) - %d fps - xoffset = %d", rominfo.international, region, fps,input.x_offset); sprintf(caption, "Genesis Plus/SDL - %s (%s) - %d fps - 0x%04X", rominfo.international, region, fps, realchecksum);
SDL_WM_SetCaption(caption, NULL); SDL_WM_SetCaption(caption, NULL);
frame_count = 0; frame_count = 0;
@ -177,8 +177,8 @@ int main (int argc, char **argv)
set_config_defaults(); set_config_defaults();
/* Load game */ /* Load game */
cart_rom = malloc(10*1024*1024); cart.rom = malloc(10*1024*1024);
memset(cart_rom, 0, 10*1024*1024); memset(cart.rom, 0, 10*1024*1024);
if(!load_rom(argv[1])) if(!load_rom(argv[1]))
{ {
char caption[256]; char caption[256];
@ -221,7 +221,7 @@ int main (int argc, char **argv)
/* load BIOS */ /* load BIOS */
memset(bios_rom, 0, sizeof(bios_rom)); memset(bios_rom, 0, sizeof(bios_rom));
FILE *f = fopen("./BIOS.bin", "rb"); FILE *f = fopen(OS_ROM, "rb");
if (f!=NULL) if (f!=NULL)
{ {
fread(&bios_rom, 0x800,1,f); fread(&bios_rom, 0x800,1,f);
@ -436,8 +436,9 @@ int main (int argc, char **argv)
SDL_FreeSurface(screen); SDL_FreeSurface(screen);
SDL_Quit(); SDL_Quit();
system_shutdown(); system_shutdown();
audio_shutdown();
error_shutdown(); error_shutdown();
free(cart_rom); free(cart.rom);
return 0; return 0;
} }

View File

@ -18,4 +18,10 @@
#include "unzip.h" #include "unzip.h"
#include "fileio.h" #include "fileio.h"
#define GG_ROM "./ggenie.bin"
#define AR_ROM "./areplay.bin"
#define OS_ROM "./bios.bin"
#define SK_ROM "./sk.bin"
#define SK_UPMEM "./sk2chip.bin"
#endif /* _OSD_H_ */ #endif /* _OSD_H_ */

View File

@ -76,21 +76,21 @@ uint8 fifo_latency; /* VDP write cycles latency */
uint8 odd_frame; /* 1: odd field, 0: even field */ uint8 odd_frame; /* 1: odd field, 0: even field */
uint8 im2_flag; /* 1= Interlace mode 2 is being used */ uint8 im2_flag; /* 1= Interlace mode 2 is being used */
uint8 interlaced; /* 1: Interlaced mode 1 or 2 */ uint8 interlaced; /* 1: Interlaced mode 1 or 2 */
uint8 vdp_pal = 0; /* 1: PAL , 0: NTSC (default) */ uint8 vdp_pal; /* 1: PAL , 0: NTSC (default) */
uint8 vdp_rate; /* PAL: 50hz, NTSC: 60hz */ uint8 vdp_rate; /* PAL: 50hz, NTSC: 60hz */
uint16 lines_per_frame; /* PAL: 313 lines, NTSC: 262 lines */ uint16 lines_per_frame; /* PAL: 313 lines, NTSC: 262 lines */
/* Tables that define the playfield layout */ /* Tables that define the playfield layout */
static const uint8 shift_table[] = { 6, 7, 0, 8 }; static const uint8 shift_table[] = { 6, 7, 0, 8 };
static const uint8 col_mask_table[] = { 0x0F, 0x1F, 0x0F, 0x3F }; static const uint8 col_mask_table[] = { 0x0F, 0x1F, 0x0F, 0x3F };
static const uint16 row_mask_table[] = { 0x0FF, 0x1FF, 0x2FF, 0x3FF }; static const uint16 row_mask_table[] = { 0x0FF, 0x1FF, 0x2FF, 0x3FF };
static const uint32 y_mask_table[] = { 0x1FC0, 0x1F80, 0x1FC0, 0x1F00 }; static const uint32 y_mask_table[] = { 0x1FC0, 0x1F80, 0x1FC0, 0x1F00 };
static uint16 sat_base_mask; /* Base bits of SAT */ static uint16 sat_base_mask; /* Base bits of SAT */
static uint16 sat_addr_mask; /* Index bits of SAT */ static uint16 sat_addr_mask; /* Index bits of SAT */
static uint32 dma_endCycles; /* 68k cycles to DMA end */ static uint32 dma_endCycles; /* 68k cycles to DMA end */
static uint8 dma_type; /* Type of DMA */ static uint8 dma_type; /* DMA mode */
/* DMA Timings /* DMA Timings
@ -159,8 +159,8 @@ void vdp_reset(void)
code = 0; code = 0;
pending = 0; pending = 0;
status = 0x200; /* fifo empty */ status = 0x200; /* fifo empty */
status |= vdp_pal; status |= vdp_pal; /* PAL/NTSC flag */
ntab = 0; ntab = 0;
ntbb = 0; ntbb = 0;