mirror of
https://github.com/holub/mame
synced 2025-05-21 13:18:56 +03:00
greatly simplified mapping and access for cart ROM. given the massive internal changes, please test once again
your favorite SNES games against previous code (or against latest release) and report regressions. thanks.
This commit is contained in:
parent
34cccc8e3b
commit
6452f2c685
@ -215,7 +215,7 @@ READ8_MEMBER(snesb_state::sb2b_6a6xxx_r)
|
||||
|
||||
READ8_MEMBER(snesb_state::sb2b_7xxx_r)
|
||||
{
|
||||
return snes_ram[0xc07000 + offset];
|
||||
return space.read_byte(0xc07000 + offset);
|
||||
}
|
||||
|
||||
|
||||
@ -806,8 +806,8 @@ DRIVER_INIT_MEMBER(snesb_state,sblast2b)
|
||||
|
||||
for (i =0; i < 0x80000 * 3; i++)
|
||||
{
|
||||
cipherText = src[i];
|
||||
plainText = data_substitution0[cipherText & 0xf] | data_substitution1[cipherText >> 4];
|
||||
cipherText = src[i];
|
||||
plainText = data_substitution0[cipherText & 0xf] | data_substitution1[cipherText >> 4];
|
||||
newAddress = (address_substitution_high[i >> 15] << 15) | (i & 0x7fc0) | (address_substitution_low[i & 0x3f]);
|
||||
|
||||
if (newAddress < 0x10000)
|
||||
|
@ -558,6 +558,7 @@ struct snes_cart_info
|
||||
UINT8 mode; /* ROM memory mode */
|
||||
UINT32 sram_max; /* Maximum amount sram in cart (based on ROM mode) */
|
||||
int slot_in_use; /* this is needed by Sufami Turbo slots (to check if SRAM has to be saved) */
|
||||
UINT8 rom_bank_map[0x100];
|
||||
};
|
||||
|
||||
struct snes_joypad
|
||||
@ -650,6 +651,7 @@ public:
|
||||
UINT8 m_has_addon_chip;
|
||||
UINT32 m_cart_size;
|
||||
snes_cart_info m_cart[2]; // the second one is used by MESS for Sufami Turbo and, eventually, BS-X
|
||||
void rom_map_setup(UINT32 size);
|
||||
|
||||
snes_ppu_class m_ppu;
|
||||
UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
@ -676,6 +676,31 @@ address | | | | | | |
|
||||
|
||||
*/
|
||||
|
||||
static UINT8 snes_rom_access(running_machine &machine, UINT32 offset)
|
||||
{
|
||||
snes_state *state = machine.driver_data<snes_state>();
|
||||
UINT32 addr;
|
||||
UINT8 value = 0xff;
|
||||
UINT8 base_bank = (offset < 0x800000) ? 0x80 : 0x00;
|
||||
|
||||
switch (state->m_cart[0].mode)
|
||||
{
|
||||
case SNES_MODE_20:
|
||||
case SNES_MODE_22:
|
||||
addr = (state->m_cart[0].rom_bank_map[offset/0x10000] * 0x8000) + (offset & 0x7fff);
|
||||
value = state->m_cart[0].m_rom[addr];
|
||||
break;
|
||||
case SNES_MODE_21:
|
||||
case SNES_MODE_25:
|
||||
offset &= 0x3fffff;
|
||||
addr = (state->m_cart[0].rom_bank_map[base_bank + (offset/0x8000)] * 0x8000) + (offset & 0x7fff);
|
||||
value = state->m_cart[0].m_rom[addr];
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* 0x000000 - 0x7dffff */
|
||||
READ8_HANDLER( snes_r_bank1 )
|
||||
{
|
||||
@ -702,14 +727,14 @@ READ8_HANDLER( snes_r_bank1 )
|
||||
value = snes_open_bus_r(space, 0); /* Reserved */
|
||||
}
|
||||
else
|
||||
value = snes_ram[offset]; //ROM
|
||||
value = snes_rom_access(space.machine(), offset); //ROM
|
||||
}
|
||||
else if (offset < 0x700000)
|
||||
{
|
||||
if (state->m_cart[0].mode & 5 && address < 0x8000) /* Mode 20 & 22 in 0x0000-0x7fff */
|
||||
value = snes_open_bus_r(space, 0);
|
||||
else
|
||||
value = snes_ram[offset]; //ROM
|
||||
value = snes_rom_access(space.machine(), offset); //ROM
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -734,9 +759,9 @@ READ8_HANDLER( snes_r_bank1 )
|
||||
}
|
||||
}
|
||||
else
|
||||
value = snes_ram[offset]; //ROM
|
||||
value = snes_rom_access(space.machine(), offset); //ROM
|
||||
}
|
||||
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -753,7 +778,7 @@ READ8_HANDLER( snes_r_bank2 )
|
||||
if (address < 0x8000)
|
||||
value = space.read_byte(offset);
|
||||
else
|
||||
value = snes_ram[0x800000 + offset]; //ROM
|
||||
value = snes_rom_access(space.machine(), 0x800000 + offset); //ROM
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -783,9 +808,9 @@ READ8_HANDLER( snes_r_bank2 )
|
||||
}
|
||||
}
|
||||
else
|
||||
value = snes_ram[0x800000 + offset]; //ROM
|
||||
value = snes_rom_access(space.machine(), 0x800000 + offset); //ROM
|
||||
}
|
||||
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -813,7 +838,7 @@ WRITE8_HANDLER( snes_w_bank1 )
|
||||
}
|
||||
else
|
||||
logerror("(PC=%06x) snes_w_bank1: Attempt to write to reserved address: %X = %02X\n", space.device().safe_pc(), offset, data);
|
||||
}
|
||||
}
|
||||
else
|
||||
logerror("(PC=%06x) Attempt to write to ROM address: %X\n", space.device().safe_pc(), offset);
|
||||
}
|
||||
@ -853,7 +878,7 @@ WRITE8_HANDLER( snes_w_bank2 )
|
||||
{
|
||||
snes_state *state = space.machine().driver_data<snes_state>();
|
||||
UINT16 address = offset & 0xffff;
|
||||
|
||||
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x8000)
|
||||
@ -1158,18 +1183,36 @@ MACHINE_RESET( snes )
|
||||
}
|
||||
|
||||
|
||||
void snes_state::rom_map_setup(UINT32 size)
|
||||
{
|
||||
int i;
|
||||
// setup the rom_bank_map array to faster ROM read
|
||||
for (i = 0; i < size / 0x8000; i++)
|
||||
m_cart[0].rom_bank_map[i] = i;
|
||||
|
||||
// fill up remaining blocks with mirrors
|
||||
while (i % 256)
|
||||
{
|
||||
int j = 0, repeat_banks;
|
||||
while ((i % (256 >> j)) && j < 8)
|
||||
j++;
|
||||
repeat_banks = i % (256 >> (j - 1));
|
||||
for (int k = 0; k < repeat_banks; k++)
|
||||
m_cart[0].rom_bank_map[i + k] = m_cart[0].rom_bank_map[i + k - repeat_banks];
|
||||
i += repeat_banks;
|
||||
}
|
||||
}
|
||||
|
||||
/* for mame we use an init, maybe we will need more for the different games */
|
||||
DRIVER_INIT_MEMBER(snes_state,snes)
|
||||
{
|
||||
UINT16 total_blocks, read_blocks;
|
||||
UINT8 *rom;
|
||||
|
||||
rom = memregion("user3")->base();
|
||||
UINT8 *rom = memregion("user3")->base();
|
||||
snes_ram = auto_alloc_array_clear(machine(), UINT8, 0x1400000);
|
||||
|
||||
m_cart[0].m_rom_size = memregion("user3")->bytes();
|
||||
m_cart[0].m_rom = auto_alloc_array_clear(machine(), UINT8, m_cart[0].m_rom_size);
|
||||
memcpy(m_cart[0].m_rom, rom, m_cart[0].m_rom_size);
|
||||
rom_map_setup(m_cart[0].m_rom_size);
|
||||
|
||||
m_cart[0].m_nvram_size = 0;
|
||||
if (rom[0x7fd8] > 0)
|
||||
@ -1185,61 +1228,18 @@ DRIVER_INIT_MEMBER(snes_state,snes)
|
||||
/* all NSS games seem to use MODE 20 */
|
||||
m_cart[0].mode = SNES_MODE_20;
|
||||
m_has_addon_chip = HAS_NONE;
|
||||
|
||||
/* Find the number of blocks in this ROM */
|
||||
total_blocks = (memregion("user3")->bytes() / 0x8000);
|
||||
read_blocks = 0;
|
||||
|
||||
/* Loading all the data blocks from cart, we only partially cover banks 0x00 to 0x7f. Therefore, we
|
||||
* have to mirror the blocks until we reach the end. E.g. for a 11Mbits image (44 blocks), we proceed
|
||||
* as follows:
|
||||
* 11 Mbits = 8 Mbits (blocks 1->32) + 2 Mbits (blocks 33->40) + 1 Mbit (blocks 41->44).
|
||||
* Hence, we fill memory up to 16 Mbits (banks 0x00 to 0x3f) mirroring the final part:
|
||||
* 8 Mbits (blocks 1->32) + 2 Mbits (blocks 33->40) + 1 Mbit (blocks 41->44) + 1 Mbit (blocks 41->44)
|
||||
* + 2 Mbits (blocks 33->40) + 1 Mbit (blocks 41->44) + 1 Mbit (blocks 41->44).
|
||||
* And we repeat the same blocks in the second half of the banks (banks 0x40 to 0x7f).
|
||||
* This is likely what happens in the real SNES as well, because the unit cannot be aware of the exact
|
||||
* size of data in the cart (procedure confirmed by byuu)
|
||||
*/
|
||||
|
||||
/* LoROM carts load data in banks 0x00 to 0x7f at address 0x8000 (actually up to 0x7d, because 0x7e and
|
||||
* 0x7f are overwritten by WRAM). Each block is also mirrored in banks 0x80 to 0xff (up to 0xff for real)
|
||||
*/
|
||||
while (read_blocks < 128 && read_blocks < total_blocks)
|
||||
{
|
||||
/* Loading data */
|
||||
memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &rom[read_blocks * 0x08000], 0x8000);
|
||||
/* Mirroring */
|
||||
memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0x8000 + read_blocks * 0x10000], 0x8000);
|
||||
read_blocks++;
|
||||
}
|
||||
/* Filling banks up to 0x7f and their mirrors */
|
||||
while (read_blocks % 128)
|
||||
{
|
||||
int j = 0, repeat_blocks;
|
||||
while ((read_blocks % (128 >> j)) && j < 7)
|
||||
j++;
|
||||
repeat_blocks = read_blocks % (128 >> (j - 1));
|
||||
|
||||
memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[0x800000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
|
||||
read_blocks += repeat_blocks;
|
||||
}
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(snes_state,snes_hirom)
|
||||
{
|
||||
UINT16 total_blocks, read_blocks;
|
||||
UINT8 *rom;
|
||||
|
||||
rom = memregion("user3")->base();
|
||||
UINT8 *rom = memregion("user3")->base();
|
||||
snes_ram = auto_alloc_array(machine(), UINT8, 0x1400000);
|
||||
memset(snes_ram, 0, 0x1400000);
|
||||
|
||||
m_cart[0].m_rom_size = memregion("user3")->bytes();
|
||||
m_cart[0].m_rom = auto_alloc_array_clear(machine(), UINT8, m_cart[0].m_rom_size);
|
||||
memcpy(m_cart[0].m_rom, rom, m_cart[0].m_rom_size);
|
||||
rom_map_setup(m_cart[0].m_rom_size);
|
||||
|
||||
m_cart[0].m_nvram_size = 0;
|
||||
if (rom[0xffd8] > 0)
|
||||
@ -1254,41 +1254,6 @@ DRIVER_INIT_MEMBER(snes_state,snes_hirom)
|
||||
|
||||
m_cart[0].mode = SNES_MODE_21;
|
||||
m_has_addon_chip = HAS_NONE;
|
||||
|
||||
/* Find the number of blocks in this ROM */
|
||||
total_blocks = (memregion("user3")->bytes() / 0x10000);
|
||||
read_blocks = 0;
|
||||
|
||||
/* See above for details about the way we fill banks 0x00 to 0x7f */
|
||||
|
||||
/* HiROM carts load data in banks 0xc0 to 0xff. Each bank is fully mirrored in banks 0x40 to 0x7f
|
||||
* (actually up to 0x7d, because 0x7e and 0x7f are overwritten by WRAM). The top half (address
|
||||
* range 0x8000 - 0xffff) of each bank is also mirrored in banks 0x00 to 0x3f and 0x80 to 0xbf.
|
||||
*/
|
||||
while (read_blocks < 64 && read_blocks < total_blocks)
|
||||
{
|
||||
/* Loading data */
|
||||
memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &rom[read_blocks * 0x10000], 0x10000);
|
||||
/* Mirroring */
|
||||
memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
|
||||
memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0xc00000 + read_blocks * 0x10000], 0x10000);
|
||||
memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
|
||||
read_blocks++;
|
||||
}
|
||||
/* Filling banks up to 0x7f and their mirrors */
|
||||
while (read_blocks % 64)
|
||||
{
|
||||
int j = 0, repeat_blocks;
|
||||
while ((read_blocks % (64 >> j)) && j < 6)
|
||||
j++;
|
||||
repeat_blocks = read_blocks % (64 >> (j - 1));
|
||||
|
||||
memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &snes_ram[0xc00000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0x400000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[0x800000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
read_blocks += repeat_blocks;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,6 +61,8 @@ public:
|
||||
DECLARE_READ8_MEMBER( superfx_r_bank2 );
|
||||
DECLARE_READ8_MEMBER( superfx_r_bank3 );
|
||||
DECLARE_WRITE8_MEMBER( superfx_w_bank3 );
|
||||
DECLARE_READ8_MEMBER( sufami_r );
|
||||
DECLARE_WRITE8_MEMBER( sufami_w );
|
||||
CUSTOM_INPUT_MEMBER( snes_mouse_speed_input );
|
||||
CUSTOM_INPUT_MEMBER( snes_superscope_offscreen_input );
|
||||
TIMER_CALLBACK_MEMBER( lightgun_tick );
|
||||
@ -138,7 +140,6 @@ void snes_console_state::st010_write_ram(UINT16 addr, UINT8 data)
|
||||
m_upd96050->dataram_w(addr/2, temp);
|
||||
}
|
||||
|
||||
|
||||
READ8_MEMBER( snes_console_state::sfx_r )
|
||||
{
|
||||
UINT16 address = offset & 0xffff;
|
||||
@ -156,12 +157,12 @@ READ8_MEMBER( snes_console_state::sfx_r )
|
||||
else if (address < 0x8000)
|
||||
return superfx_access_ram(m_superfx) ? m_sfx_ram[offset & 0x1fff] : snes_open_bus_r(space, 0);
|
||||
else
|
||||
return snes_ram[offset];
|
||||
return m_cart[0].m_rom[m_cart[0].rom_bank_map[offset / 0x10000] * 0x8000 + (offset & 0x7fff)];
|
||||
}
|
||||
else if (offset < 0x600000)
|
||||
{
|
||||
if (superfx_access_rom(m_superfx))
|
||||
return snes_ram[offset];
|
||||
return m_cart[0].m_rom[m_cart[0].rom_bank_map[(offset - 0x400000) / 0x8000] * 0x8000 + (offset & 0x7fff)];
|
||||
else
|
||||
{
|
||||
static const UINT8 sfx_data[16] = {
|
||||
@ -468,21 +469,96 @@ WRITE8_MEMBER( snes_console_state::snes_hi_w )
|
||||
snes_w_bank2(space, offset, data, 0xff);
|
||||
}
|
||||
|
||||
READ8_MEMBER( snes_console_state::sufami_r )
|
||||
{
|
||||
UINT16 address = offset & 0xffff;
|
||||
if (offset < 0x200000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
else if (address < 0x6000)
|
||||
return snes_r_io(space, address);
|
||||
else if (address < 0x8000)
|
||||
return snes_open_bus_r(space, 0);
|
||||
else
|
||||
{
|
||||
UINT8 *ROM = memregion("sufami")->base();
|
||||
int bank = (offset / 0x10000) & 7;
|
||||
return ROM[bank * 0x8000 + (offset & 0x7fff)]; // SUFAMI ROM
|
||||
}
|
||||
}
|
||||
else if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
else if (address < 0x6000)
|
||||
return snes_r_io(space, address);
|
||||
else if (address < 0x8000)
|
||||
return snes_open_bus_r(space, 0);
|
||||
else if (m_cart[0].slot_in_use)
|
||||
{
|
||||
int bank = (offset - 0x200000) / 0x10000;
|
||||
return m_cart[0].m_rom[m_cart[0].rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; // SUFAMI SLOT1
|
||||
}
|
||||
}
|
||||
else if (offset < 0x600000)
|
||||
{
|
||||
if (address < 0x8000)
|
||||
return snes_open_bus_r(space, 0);
|
||||
else if (m_cart[1].slot_in_use)
|
||||
{
|
||||
int bank = (offset - 0x400000) / 0x10000;
|
||||
return m_cart[1].m_rom[m_cart[1].rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; // SUFAMI SLOT2
|
||||
}
|
||||
}
|
||||
else if (address >= 0x8000 && ((offset >= 0x600000 && offset < 0x640000) || (offset >= 0x700000 && offset < 0x740000)))
|
||||
{
|
||||
int slot_id = (offset & 0x100000) ? 1 : 0;
|
||||
if (m_cart[slot_id].slot_in_use)
|
||||
{
|
||||
int bank = (offset & 0x3ffff) / 0x10000;
|
||||
return m_cart[slot_id].m_nvram[bank * 0x8000 + (offset & 0x7fff)]; // SLOT RAM
|
||||
}
|
||||
}
|
||||
return snes_open_bus_r(space, 0);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( snes_console_state::sufami_w )
|
||||
{
|
||||
UINT16 address = offset & 0xffff;
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
space.write_byte(0x7e0000 + address, data);
|
||||
else if (address < 0x6000)
|
||||
snes_w_io(space, address, data);
|
||||
}
|
||||
else if (address >= 0x8000 && ((offset >= 0x600000 && offset < 0x640000) || (offset >= 0x700000 && offset < 0x740000)))
|
||||
{
|
||||
int slot_id = (offset & 0x100000) ? 1 : 0;
|
||||
if (m_cart[slot_id].slot_in_use)
|
||||
{
|
||||
int bank = (offset & 0x3ffff) / 0x10000;
|
||||
m_cart[slot_id].m_nvram[bank * 0x8000 + (offset & 0x7fff)] = data; // SLOT RAM
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER( snes_console_state::superfx_r_bank1 )
|
||||
{
|
||||
return snes_ram[offset | 0x8000];
|
||||
return m_cart[0].m_rom[m_cart[0].rom_bank_map[offset / 0x10000] * 0x8000 + (offset & 0x7fff)];
|
||||
}
|
||||
|
||||
READ8_MEMBER( snes_console_state::superfx_r_bank2 )
|
||||
{
|
||||
return snes_ram[0x400000 + offset];
|
||||
return m_cart[0].m_rom[m_cart[0].rom_bank_map[offset / 0x8000] * 0x8000 + (offset & 0x7fff)];
|
||||
}
|
||||
|
||||
READ8_MEMBER( snes_console_state::superfx_r_bank3 )
|
||||
{
|
||||
/* IMPORTANT: SFX RAM sits in 0x600000-0x7fffff, and it's mirrored in 0xe00000-0xffffff. However, SNES
|
||||
has only access to 0x600000-0x7dffff (because there is WRAM after that). */
|
||||
//printf("superfx_r_bank3: %08x = %02x\n", offset, snes_ram[0xe00000 + offset]);
|
||||
//printf("superfx_r_bank3: %08x = %02x\n", offset, m_sfx_ram[offset & 0xfffff]);
|
||||
return m_sfx_ram[offset & 0xfffff];
|
||||
}
|
||||
|
||||
@ -506,6 +582,12 @@ static ADDRESS_MAP_START( snes_map, AS_PROGRAM, 8, snes_console_state )
|
||||
AM_RANGE(0x800000, 0xffffff) AM_READWRITE(snes_hi_r, snes_hi_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( snesst_map, AS_PROGRAM, 8, snes_console_state )
|
||||
AM_RANGE(0x000000, 0x7dffff) AM_READWRITE(sufami_r, sufami_w)
|
||||
AM_RANGE(0x7e0000, 0x7fffff) AM_RAM /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
|
||||
AM_RANGE(0x800000, 0xffffff) AM_READWRITE(sufami_r, sufami_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( superfx_map, AS_PROGRAM, 8, snes_console_state )
|
||||
AM_RANGE(0x000000, 0x3fffff) AM_READ(superfx_r_bank1)
|
||||
AM_RANGE(0x400000, 0x5fffff) AM_READ(superfx_r_bank2)
|
||||
@ -1295,6 +1377,8 @@ static MACHINE_CONFIG_DERIVED( snespdsp, snespal )
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( snesst, snes_base )
|
||||
MCFG_CPU_MODIFY( "maincpu" )
|
||||
MCFG_CPU_PROGRAM_MAP(snesst_map)
|
||||
|
||||
MCFG_MACHINE_START(snesst)
|
||||
|
||||
@ -1584,7 +1668,7 @@ WRITE8_MEMBER( snsnew_state::snes20_hi_w )
|
||||
|
||||
if (m_type == SNES_SUFAMITURBO && address >= 0x8000 && ((offset >= 0x600000 && offset < 0x640000) || (offset >= 0x700000 && offset < 0x740000)))
|
||||
{ m_slotcart->m_cart->write_h(space, offset, data); return; }
|
||||
|
||||
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
@ -1631,7 +1715,7 @@ READ8_MEMBER( snsnew_state::snes20_lo_r )
|
||||
{
|
||||
if (m_type == SNES_SUFAMITURBO && address >= 0x8000 && offset < 0x740000)
|
||||
return m_slotcart->m_cart->read_l(space, offset);
|
||||
|
||||
|
||||
// here usually there is SRAM mirrored in the whole range, but if ROM is very large then arrives here too (see tokimeki and wizardg4)
|
||||
if (m_slotcart->m_cart->get_rom_size() > 0x200000 && address >= 0x8000)
|
||||
return m_slotcart->m_cart->read_l(space, offset);
|
||||
@ -1741,7 +1825,7 @@ READ8_MEMBER( snsnew_state::snes21_hi_r )
|
||||
int mask = (m_slotcart->m_cart->get_nvram_size() - 1) & 0x7fff;
|
||||
return m_slotcart->m_cart->read_ram(space, (offset - 0x6000) & mask);
|
||||
}
|
||||
|
||||
|
||||
if (m_slotcart->m_cart->get_nvram_size() && offset >= 0x300000)
|
||||
{
|
||||
/* Donkey Kong Country checks this and detects a copier if 0x800 is not masked out due to sram size */
|
||||
@ -1805,7 +1889,7 @@ READ8_MEMBER( snsnew_state::snesfx_hi_r )
|
||||
}
|
||||
else if (address < 0x8000)
|
||||
return m_slotcart->m_cart->read_ram(space, offset & 0x1fff);
|
||||
else
|
||||
else
|
||||
return m_slotcart->m_cart->read_h(space, offset);
|
||||
}
|
||||
else if (offset < 0x600000)
|
||||
@ -1986,7 +2070,7 @@ READ8_MEMBER( snsnew_state::snesdd1_lo_r )
|
||||
}
|
||||
else if (offset >= 0x700000 && address < 0x8000 && m_slotcart->m_cart->get_nvram_size()) // NVRAM access
|
||||
return m_slotcart->m_cart->read_ram(space, offset);
|
||||
else // ROM access
|
||||
else // ROM access
|
||||
return m_slotcart->m_cart->read_l(space, offset);
|
||||
}
|
||||
|
||||
@ -2096,7 +2180,7 @@ WRITE8_MEMBER( snsnew_state::snesbsx_hi_w )
|
||||
READ8_MEMBER( snsnew_state::snesbsx_lo_r )
|
||||
{
|
||||
UINT16 address = offset & 0xffff;
|
||||
|
||||
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
@ -2458,23 +2542,23 @@ static MACHINE_START( snesnew )
|
||||
switch (state->m_type)
|
||||
{
|
||||
case SNES_MODE21:
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes21_hi_r),state), write8_delegate(FUNC(snsnew_state::snes21_hi_w),state));
|
||||
// set_5a22_map(*state->m_maincpu);
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes21_hi_r),state), write8_delegate(FUNC(snsnew_state::snes21_hi_w),state));
|
||||
// set_5a22_map(*state->m_maincpu);
|
||||
break;
|
||||
case SNES_DSP_MODE21:
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes21_hi_r),state), write8_delegate(FUNC(snsnew_state::snes21_hi_w),state));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x006000, 0x007fff, 0, 0x9f0000, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x006000, 0x007fff, 0, 0x9f0000, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
|
||||
// set_5a22_map(*state->m_maincpu);
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes21_hi_r),state), write8_delegate(FUNC(snsnew_state::snes21_hi_w),state));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x006000, 0x007fff, 0, 0x9f0000, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x006000, 0x007fff, 0, 0x9f0000, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
|
||||
// set_5a22_map(*state->m_maincpu);
|
||||
break;
|
||||
case SNES_SRTC:
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes21_hi_r),state), write8_delegate(FUNC(snsnew_state::snes21_hi_w),state));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x002800, 0x002800, 0, 0xbf0000, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x002801, 0x002801, 0, 0xbf0000, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
|
||||
// set_5a22_map(*state->m_maincpu);
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes21_hi_r),state), write8_delegate(FUNC(snsnew_state::snes21_hi_w),state));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x002800, 0x002800, 0, 0xbf0000, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
|
||||
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x002801, 0x002801, 0, 0xbf0000, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
|
||||
// set_5a22_map(*state->m_maincpu);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -128,82 +128,49 @@ static void snes_load_sram(running_machine &machine)
|
||||
}
|
||||
|
||||
/* Saves the battery backed RAM from the appropriate memory area */
|
||||
static void snes_save_sram(running_machine &machine)
|
||||
{
|
||||
snes_state *state = machine.driver_data<snes_state>();
|
||||
device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("cart"));
|
||||
image->battery_save(state->m_cart[0].m_nvram, state->m_cart[0].m_nvram_size);
|
||||
}
|
||||
|
||||
void snes_machine_stop(running_machine &machine)
|
||||
{
|
||||
snes_state *state = machine.driver_data<snes_state>();
|
||||
|
||||
/* Save SRAM */
|
||||
if (state->m_cart[0].m_nvram_size > 0)
|
||||
snes_save_sram(machine);
|
||||
{
|
||||
device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("cart"));
|
||||
image->battery_save(state->m_cart[0].m_nvram, state->m_cart[0].m_nvram_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void sufami_load_sram(running_machine &machine, const char *cart_tag)
|
||||
{
|
||||
UINT8 ii;
|
||||
UINT8 *battery_ram, *ptr;
|
||||
int st_sram_offset = 0;
|
||||
|
||||
battery_ram = (UINT8*)malloc(0x20000);
|
||||
ptr = battery_ram;
|
||||
snes_state *state = machine.driver_data<snes_state>();
|
||||
int slot_id = 0;
|
||||
device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device(cart_tag));
|
||||
image->battery_load(battery_ram, 0x20000, 0);
|
||||
|
||||
if (strcmp(cart_tag, ":slot_a") == 0)
|
||||
st_sram_offset = 0x608000;
|
||||
slot_id = 0;
|
||||
|
||||
if (strcmp(cart_tag, ":slot_b") == 0)
|
||||
st_sram_offset = 0x708000;
|
||||
slot_id = 1;
|
||||
|
||||
/* Cart RAM is at 0x60-0x63:0x8000-0xffff (+0x10 for slot2) */
|
||||
for (ii = 0; ii < 4; ii++)
|
||||
{
|
||||
/* loading */
|
||||
memcpy(&snes_ram[st_sram_offset + (ii * 0x010000)], ptr + (ii * 0x8000), 0x8000);
|
||||
/* mirroring */
|
||||
memcpy(&snes_ram[0x800000 + st_sram_offset + (ii * 0x010000)], &snes_ram[st_sram_offset + (ii * 0x010000)], 0x8000);
|
||||
}
|
||||
|
||||
free(battery_ram);
|
||||
image->battery_load(state->m_cart[slot_id].m_nvram, state->m_cart[slot_id].m_nvram_size, 0xff);
|
||||
}
|
||||
|
||||
void sufami_machine_stop(running_machine &machine)
|
||||
{
|
||||
snes_state *state = machine.driver_data<snes_state>();
|
||||
UINT8 ii;
|
||||
UINT8 *battery_ram, *ptr;
|
||||
|
||||
battery_ram = (UINT8*)malloc(0x20000);
|
||||
ptr = battery_ram;
|
||||
|
||||
if (state->m_cart[0].slot_in_use)
|
||||
if (state->m_cart[0].slot_in_use && state->m_cart[0].m_nvram_size)
|
||||
{
|
||||
for (ii = 0; ii < 4; ii++)
|
||||
{
|
||||
memmove(ptr + ii * 0x8000, &snes_ram[0x608000 + (ii * 0x010000)], 0x8000);
|
||||
}
|
||||
device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("slot_a"));
|
||||
image->battery_save(battery_ram, 0x20000);
|
||||
image->battery_save(state->m_cart[0].m_nvram, state->m_cart[0].m_nvram_size);
|
||||
}
|
||||
|
||||
if (state->m_cart[1].slot_in_use)
|
||||
if (state->m_cart[1].slot_in_use && state->m_cart[1].m_nvram_size)
|
||||
{
|
||||
for (ii = 0; ii < 4; ii++)
|
||||
{
|
||||
memmove(ptr + ii * 0x8000, &snes_ram[0x708000 + (ii * 0x010000)], 0x8000);
|
||||
}
|
||||
device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("slot_b"));
|
||||
image->battery_save(battery_ram, 0x20000);
|
||||
image->battery_save(state->m_cart[1].m_nvram, state->m_cart[1].m_nvram_size);
|
||||
}
|
||||
|
||||
free(battery_ram);
|
||||
}
|
||||
|
||||
|
||||
@ -594,7 +561,7 @@ static int snes_find_addon_chip( running_machine &machine, UINT8 *buffer, UINT32
|
||||
return supported_type;
|
||||
}
|
||||
|
||||
static void snes_cart_log_info( running_machine &machine, UINT8* ROM, int total_blocks, int supported )
|
||||
static void snes_cart_log_info( running_machine &machine, UINT8* ROM, int supported )
|
||||
{
|
||||
snes_state *state = machine.driver_data<snes_state>();
|
||||
device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("cart"));
|
||||
@ -602,7 +569,7 @@ static void snes_cart_log_info( running_machine &machine, UINT8* ROM, int total_
|
||||
int i, company, has_ram = 0, has_sram = 0;
|
||||
UINT32 offset = snes_skip_header(*image, state->m_cart_size);
|
||||
UINT32 hilo_mode = snes_find_hilo_mode(*image, ROM, offset, 0);
|
||||
|
||||
|
||||
/* Company */
|
||||
for (i = 0; i < 2; i++)
|
||||
company_id[i] = ROM[hilo_mode - 0x10 + i];
|
||||
@ -631,6 +598,8 @@ static void snes_cart_log_info( running_machine &machine, UINT8* ROM, int total_
|
||||
((ROM[hilo_mode + 0x16] & 0xf) == 6))
|
||||
has_sram = 1;
|
||||
|
||||
int total_blocks = (state->m_cart[0].m_rom_size - offset) / (state->m_cart[0].mode & 0xa5 ? 0x8000 : 0x10000);
|
||||
|
||||
logerror( "ROM DETAILS\n" );
|
||||
logerror( "===========\n\n" );
|
||||
logerror( "\tTotal blocks: %d (%dmb)\n", total_blocks, total_blocks / (state->m_cart[0].mode & 5 ? 32 : 16) );
|
||||
@ -662,8 +631,8 @@ static void snes_cart_log_info( running_machine &machine, UINT8* ROM, int total_
|
||||
logerror( "\tVersion: 1.%d\n", ROM[hilo_mode + 0x1b] );
|
||||
logerror( "\tInv Checksum: %X %X\n", ROM[hilo_mode + 0x1d], ROM[hilo_mode + 0x1c] );
|
||||
logerror( "\tChecksum: %X %X\n", ROM[hilo_mode + 0x1f], ROM[hilo_mode + 0x1e] );
|
||||
logerror( "\tNMI Address: %2X%2Xh\n", ROM[hilo_mode + 0x3b], ROM[hilo_mode + 0x3a]);
|
||||
logerror( "\tStart Address: %2X%2Xh\n\n", ROM[hilo_mode + 0x3d], ROM[hilo_mode + 0x3c]);
|
||||
logerror( "\tNMI Address: %2X%2Xh\n", ROM[hilo_mode + 0x3b], ROM[hilo_mode + 0x3a] );
|
||||
logerror( "\tStart Address: %2X%2Xh\n\n", ROM[hilo_mode + 0x3d], ROM[hilo_mode + 0x3c] );
|
||||
|
||||
logerror( "\tMode: %d\n", state->m_cart[0].mode);
|
||||
|
||||
@ -675,7 +644,7 @@ DEVICE_IMAGE_LOAD_MEMBER( snes_state,snes_cart )
|
||||
{
|
||||
int supported_type = 1;
|
||||
running_machine &machine = image.device().machine();
|
||||
int total_blocks, read_blocks, has_bsx_slot = 0, st_bios = 0;
|
||||
int has_bsx_slot = 0, st_bios = 0;
|
||||
UINT32 offset, int_header_offs;
|
||||
UINT8 *ROM = memregion("cart")->base();
|
||||
|
||||
@ -700,6 +669,7 @@ DEVICE_IMAGE_LOAD_MEMBER( snes_state,snes_cart )
|
||||
m_cart[0].m_rom_size = m_cart_size;
|
||||
m_cart[0].m_rom = auto_alloc_array_clear(machine, UINT8, m_cart[0].m_rom_size);
|
||||
memcpy(m_cart[0].m_rom, ROM, m_cart[0].m_rom_size - offset);
|
||||
rom_map_setup(m_cart[0].m_rom_size);
|
||||
|
||||
/* First, look if the cart is HiROM or LoROM (and set snes_cart accordingly) */
|
||||
int_header_offs = snes_find_hilo_mode(image, ROM, offset, 0);
|
||||
@ -760,248 +730,6 @@ DEVICE_IMAGE_LOAD_MEMBER( snes_state,snes_cart )
|
||||
|
||||
if (SNES_CART_DEBUG) mame_printf_error("mode %d\n", m_cart[0].mode);
|
||||
|
||||
/* FIXME: Insert crc check here? */
|
||||
|
||||
/* How many blocks of data are available to be loaded? */
|
||||
total_blocks = ((m_cart_size - offset) / (m_cart[0].mode & 0xa5 ? 0x8000 : 0x10000));
|
||||
read_blocks = 0;
|
||||
|
||||
if (SNES_CART_DEBUG) mame_printf_error("blocks %d\n", total_blocks);
|
||||
|
||||
/* Loading all the data blocks from cart, we only partially cover banks 0x00 to 0x7f. Therefore, we
|
||||
* have to mirror the blocks until we reach the end. E.g. for a 11Mbits image (44 blocks), we proceed
|
||||
* as follows:
|
||||
* 11 Mbits = 8 Mbits (blocks 1->32) + 2 Mbits (blocks 33->40) + 1 Mbit (blocks 41->44).
|
||||
* Hence, we fill memory up to 16 Mbits (banks 0x00 to 0x3f) mirroring as follows
|
||||
* 8 Mbits (blocks 1->32) + 2 Mbits (blocks 33->40) + 1 Mbit (blocks 41->44) + 1 Mbit (blocks 41->44)
|
||||
* + 2 Mbits (blocks 33->40) + 1 Mbit (blocks 41->44) + 1 Mbit (blocks 41->44)
|
||||
* and we repeat the same blocks in the second half of the banks (banks 0x40 to 0x7f).
|
||||
* This is likely what happens in the real SNES as well, because the unit cannot be aware of the exact
|
||||
* size of data in the cart (procedure confirmed by byuu)
|
||||
*/
|
||||
switch (m_cart[0].mode)
|
||||
{
|
||||
case SNES_MODE_21:
|
||||
/* HiROM carts load data in banks 0xc0 to 0xff. Each bank is fully mirrored in banks 0x40 to 0x7f
|
||||
* (actually up to 0x7d, because 0x7e and 0x7f are overwritten by WRAM). The top half (address
|
||||
* range 0x8000 - 0xffff) of each bank is also mirrored in banks 0x00 to 0x3f and 0x80 to 0xbf.
|
||||
*/
|
||||
/* SPC7110 games needs this different loading routine */
|
||||
if ((ROM[0x00ffd6] == 0xf9 || ROM[0x00ffd6] == 0xf5) && (ROM[0x00ffd5] == 0x3a))
|
||||
{
|
||||
while (read_blocks < 16 && read_blocks < total_blocks)
|
||||
{
|
||||
/* Loading data */
|
||||
memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
|
||||
/* Mirroring */
|
||||
memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
|
||||
memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
|
||||
read_blocks++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (read_blocks < 64 && read_blocks < total_blocks)
|
||||
{
|
||||
/* Loading data */
|
||||
memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
|
||||
/* Mirroring */
|
||||
memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
|
||||
memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0xc00000 + read_blocks * 0x10000], 0x10000);
|
||||
memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
|
||||
read_blocks++;
|
||||
}
|
||||
/* Filling banks up to 0xff and their mirrors */
|
||||
while (read_blocks % 64)
|
||||
{
|
||||
int j = 0, repeat_blocks;
|
||||
while ((read_blocks % (64 >> j)) && j < 6)
|
||||
j++;
|
||||
repeat_blocks = read_blocks % (64 >> (j - 1));
|
||||
|
||||
memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &snes_ram[0xc00000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0x400000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[0x800000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
read_blocks += repeat_blocks;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SNES_MODE_25:
|
||||
/* Extendend HiROM carts start to load data in banks 0xc0 to 0xff. However, they exceed the
|
||||
* available space in these banks, and continue loading at banks 0x40 to 0x7f. The top half
|
||||
* (address range 0x8000 - 0xffff) of each bank is also mirrored either to banks 0x00 to 0x3f
|
||||
* (for data in banks 0x40 to 0x7f) or to banks 0x80 to 0xbf (for data in banks 0xc0 to 0xff).
|
||||
* Notice that banks 0x7e and 0x7f are overwritten by WRAM, but they could contain data at
|
||||
* address > 0x8000 because the mirrors at 0x3e and 0x3f are not overwritten.
|
||||
*/
|
||||
/* Reading the first 64 blocks */
|
||||
while (read_blocks < 64 && read_blocks < total_blocks)
|
||||
{
|
||||
/* Loading data */
|
||||
memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
|
||||
/* Mirroring */
|
||||
memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0xc08000 + read_blocks * 0x10000], 0x8000);
|
||||
read_blocks++;
|
||||
}
|
||||
/* ExHiROMs are supposed to be larger than 32Mbits! */
|
||||
if (read_blocks < 64)
|
||||
{
|
||||
logerror("This image has been identified as ExHiROM, but it's too small!\n");
|
||||
logerror("Please verify if it's corrupted. If it's not please report this as a bug.\n");
|
||||
return IMAGE_INIT_FAIL;
|
||||
}
|
||||
/* Scaling down the counter */
|
||||
read_blocks -= 64;
|
||||
/* Reading the next blocks */
|
||||
while (read_blocks < 64 && read_blocks < (total_blocks - 64))
|
||||
{
|
||||
/* Loading data */
|
||||
memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &ROM[0x400000 + read_blocks * 0x10000], 0x10000);
|
||||
/* Mirroring */
|
||||
memcpy(&snes_ram[0x8000 + read_blocks * 0x10000], &snes_ram[0x408000 + read_blocks * 0x10000], 0x8000);
|
||||
read_blocks++;
|
||||
}
|
||||
/* Filling banks up to 0x7f and their mirrors */
|
||||
while (read_blocks % 64)
|
||||
{
|
||||
int j = 0, repeat_blocks;
|
||||
while ((read_blocks % (64 >> j)) && j < 6)
|
||||
j++;
|
||||
repeat_blocks = read_blocks % (64 >> (j - 1));
|
||||
|
||||
memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0x400000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
read_blocks += repeat_blocks;
|
||||
}
|
||||
break;
|
||||
|
||||
case SNES_MODE_22:
|
||||
/* "Extendend LoROM" carts have their data loaded in banks 0x00 to 0x3f at address 0x8000.
|
||||
* These are then mirrored in banks 0x40 to 0x7f, both at address 0x0000 and at address
|
||||
* 0x8000, in banks 0x80 to 0xbf at address 0x8000 and in banks 0xc0 to 0xff, both at address
|
||||
* 0x0000 and at address 0x8000. Notice that SDD-1 games (Star Ocean and Street Fighter Zero 2)
|
||||
* use SNES_MODE_22
|
||||
*/
|
||||
while (read_blocks < 64 && read_blocks < total_blocks)
|
||||
{
|
||||
/* Loading and mirroring data */
|
||||
memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
|
||||
memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
|
||||
memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
|
||||
memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x10000], 0x10000);
|
||||
read_blocks++;
|
||||
}
|
||||
/* Filling banks up to 0x3f and their mirrors */
|
||||
while (read_blocks % 64)
|
||||
{
|
||||
int j = 0, repeat_blocks;
|
||||
while ((read_blocks % (64 >> j)) && j < 6)
|
||||
j++;
|
||||
repeat_blocks = read_blocks % (64 >> (j - 1));
|
||||
|
||||
memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[0x800000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[0x400000 + read_blocks * 0x10000], &snes_ram[0x400000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[0xc00000 + read_blocks * 0x10000], &snes_ram[0xc00000 + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
read_blocks += repeat_blocks;
|
||||
}
|
||||
break;
|
||||
|
||||
case SNES_MODE_ST:
|
||||
if (!st_bios)
|
||||
{
|
||||
mame_printf_error("This is a Sufami Turbo data cart and cannot be loaded for snes/snespal in MESS.\n");
|
||||
mame_printf_error("Please use snesst driver to load it, instead.\n");
|
||||
return IMAGE_INIT_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The Base ST cart consists of 8 * 0x8000 block which have to be loaded (and mirrored)
|
||||
// at 0x00-0x1f:0x8000-0xffff and 0x80-0x9f:0x8000-0xffff
|
||||
int i = 0;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
/* Loading data */
|
||||
memcpy(&snes_ram[0x008000 + i * 0x10000], &ROM[0x000000 + i * 0x8000], 0x8000);
|
||||
/* Mirroring */
|
||||
memcpy(&snes_ram[0x808000 + i * 0x10000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
|
||||
|
||||
/* Additional mirrors (to fill snes_ram up to 0x1fffff) */
|
||||
int j = 0;
|
||||
for (j = 1; j < 4; j++)
|
||||
{
|
||||
memcpy(&snes_ram[0x008000 + i * 0x10000 + j * 0x80000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
|
||||
memcpy(&snes_ram[0x808000 + i * 0x10000 + j * 0x80000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SNES_MODE_BSX:
|
||||
case SNES_MODE_BSLO:
|
||||
case SNES_MODE_BSHI:
|
||||
/* not handled yet */
|
||||
mame_printf_error("This is a BS-X Satellaview image: MESS does not support these yet, sorry.\n");
|
||||
/* so treat it like MODE_20 */
|
||||
m_cart[0].mode = SNES_MODE_20;
|
||||
/* and load it as such... */
|
||||
|
||||
default:
|
||||
case SNES_MODE_20:
|
||||
/* LoROM carts load data in banks 0x00 to 0x7f at address 0x8000 (actually up to 0x7d, because 0x7e and
|
||||
* 0x7f are overwritten by WRAM). Each block is also mirrored in banks 0x80 to 0xff (up to 0xff for real)
|
||||
*/
|
||||
/* SuperFX games needs this different loading routine */
|
||||
if (((ROM[0x007fd6] >= 0x13 && ROM[0x007fd6] <= 0x15) || ROM[0x007fd6] == 0x1a) && (ROM[0x007fd5] == 0x20))
|
||||
{
|
||||
while (read_blocks < 64 && read_blocks < total_blocks)
|
||||
{
|
||||
/* Loading data primary: banks 0-3f from 8000-ffff*/
|
||||
memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
|
||||
/* Mirroring at banks 80-bf from 8000-ffff */
|
||||
memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0x8000 + (read_blocks * 0x10000)], 0x8000);
|
||||
/* Mirroring at banks 40-5f and c0-df */
|
||||
memcpy(&snes_ram[0x400000 + read_blocks * 0x8000], &snes_ram[0x8000 + (read_blocks * 0x10000)], total_blocks * 0x8000);
|
||||
memcpy(&snes_ram[0xc00000 + read_blocks * 0x8000], &snes_ram[0x8000 + (read_blocks * 0x10000)], total_blocks * 0x8000);
|
||||
|
||||
read_blocks++;
|
||||
}
|
||||
/* SuperFX games are supposed to contain 64 blocks! */
|
||||
if (read_blocks < total_blocks)
|
||||
{
|
||||
logerror("This image has been identified as a SuperFX game, but it's too large!\n");
|
||||
logerror("Please verify if it's corrupted. If it's not please report this as a bug.\n");
|
||||
return IMAGE_INIT_FAIL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (read_blocks < 128 && read_blocks < total_blocks)
|
||||
{
|
||||
/* Loading data */
|
||||
memcpy(&snes_ram[0x008000 + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
|
||||
/* Mirroring */
|
||||
memcpy(&snes_ram[0x808000 + read_blocks * 0x10000], &snes_ram[0x8000 + (read_blocks * 0x10000)], 0x8000);
|
||||
read_blocks++;
|
||||
}
|
||||
/* Filling banks up to 0x7f and their mirrors */
|
||||
while (read_blocks % 128)
|
||||
{
|
||||
int j = 0, repeat_blocks;
|
||||
while ((read_blocks % (128 >> j)) && j < 7)
|
||||
j++;
|
||||
repeat_blocks = read_blocks % (128 >> (j - 1));
|
||||
|
||||
memcpy(&snes_ram[read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[0x800000 + read_blocks * 0x10000], &snes_ram[(read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
read_blocks += repeat_blocks;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Detect special chips */
|
||||
supported_type = snes_find_addon_chip(machine, ROM, int_header_offs);
|
||||
|
||||
@ -1013,7 +741,7 @@ DEVICE_IMAGE_LOAD_MEMBER( snes_state,snes_cart )
|
||||
if ((m_has_addon_chip != HAS_SUPERFX))
|
||||
nvram_size = ROM[int_header_offs + 0x18];
|
||||
else
|
||||
nvram_size = (ROM[0x00ffbd] & 0x07);
|
||||
nvram_size = (ROM[0x007fbd] & 0x07);
|
||||
|
||||
if (nvram_size > 0)
|
||||
{
|
||||
@ -1044,7 +772,7 @@ DEVICE_IMAGE_LOAD_MEMBER( snes_state,snes_cart )
|
||||
m_cart[0].m_nvram = auto_alloc_array_clear(machine, UINT8, m_cart[0].m_nvram_size);
|
||||
|
||||
/* Log snes_cart information */
|
||||
snes_cart_log_info(machine, ROM, total_blocks, supported_type);
|
||||
snes_cart_log_info(machine, ROM, supported_type);
|
||||
|
||||
/* Load SRAM */
|
||||
if (m_cart[0].m_nvram_size > 0)
|
||||
@ -1057,24 +785,15 @@ DEVICE_IMAGE_LOAD_MEMBER( snes_state,snes_cart )
|
||||
DEVICE_IMAGE_LOAD_MEMBER( snes_state,sufami_cart )
|
||||
{
|
||||
running_machine &machine = image.device().machine();
|
||||
int total_blocks, read_blocks;
|
||||
int st_bios = 0, slot_id = 0;
|
||||
UINT32 offset, st_data_offset = 0;
|
||||
UINT32 offset;
|
||||
UINT8 *ROM = image.device().machine().root_device().memregion(image.device().tag())->base();
|
||||
|
||||
snes_ram = memregion("maincpu")->base();
|
||||
|
||||
if (strcmp(image.device().tag(), ":slot_a") == 0)
|
||||
{
|
||||
st_data_offset = 0x200000;
|
||||
slot_id = 0;
|
||||
}
|
||||
|
||||
if (strcmp(image.device().tag(), ":slot_b") == 0)
|
||||
{
|
||||
st_data_offset = 0x400000;
|
||||
slot_id = 1;
|
||||
}
|
||||
|
||||
if (image.software_entry() == NULL)
|
||||
m_cart_size = image.length();
|
||||
@ -1115,51 +834,19 @@ DEVICE_IMAGE_LOAD_MEMBER( snes_state,sufami_cart )
|
||||
return IMAGE_INIT_FAIL;
|
||||
}
|
||||
|
||||
/* FIXME: Insert crc check here? */
|
||||
|
||||
/* How many blocks of data are available to be loaded? */
|
||||
total_blocks = (m_cart_size - offset) / 0x8000;
|
||||
read_blocks = 0;
|
||||
m_cart[slot_id].m_rom_size = m_cart_size;
|
||||
m_cart[slot_id].m_rom = auto_alloc_array_clear(machine, UINT8, m_cart[0].m_rom_size);
|
||||
memcpy(m_cart[slot_id].m_rom, ROM, m_cart[slot_id].m_rom_size - offset);
|
||||
rom_map_setup(m_cart[slot_id].m_rom_size);
|
||||
|
||||
if (SNES_CART_DEBUG)
|
||||
mame_printf_error("blocks %d\n", total_blocks);
|
||||
|
||||
// actually load the cart
|
||||
while (read_blocks < 32 && read_blocks < total_blocks)
|
||||
{
|
||||
/* Loading data */
|
||||
// CART (either A or B)
|
||||
memcpy(&snes_ram[0x008000 + st_data_offset + read_blocks * 0x10000], &ROM[0x000000 + read_blocks * 0x8000], 0x8000);
|
||||
/* Mirroring */
|
||||
memcpy(&snes_ram[0x808000 + st_data_offset + read_blocks * 0x10000], &snes_ram[0x8000 + st_data_offset + (read_blocks * 0x10000)], 0x8000);
|
||||
|
||||
read_blocks++;
|
||||
}
|
||||
|
||||
/* Filling banks up to 0x1f and their mirrors */
|
||||
while (read_blocks % 32)
|
||||
{
|
||||
int j = 0, repeat_blocks;
|
||||
while ((read_blocks % (32 >> j)) && j < 5)
|
||||
j++;
|
||||
repeat_blocks = read_blocks % (32 >> (j - 1));
|
||||
|
||||
memcpy(&snes_ram[st_data_offset + read_blocks * 0x10000], &snes_ram[st_data_offset + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
memcpy(&snes_ram[0x800000 + st_data_offset + read_blocks * 0x10000], &snes_ram[st_data_offset + (read_blocks - repeat_blocks) * 0x10000], repeat_blocks * 0x10000);
|
||||
read_blocks += repeat_blocks;
|
||||
}
|
||||
|
||||
// currently we still use snes_ram for STROM ram...
|
||||
// m_cart[slot_id].m_nvram_size = 0x20000;
|
||||
// m_cart[slot_id].m_nvram = auto_alloc_array_clear(machine, UINT8, m_cart[slot_id].m_nvram_size);
|
||||
m_cart[slot_id].m_nvram_size = 0;
|
||||
m_cart[slot_id].m_nvram_size = 0x20000;
|
||||
m_cart[slot_id].m_nvram = auto_alloc_array_clear(machine, UINT8, m_cart[slot_id].m_nvram_size);
|
||||
|
||||
sufami_load_sram(machine, image.device().tag());
|
||||
|
||||
m_cart[slot_id].slot_in_use = 1; // aknowledge the cart in this slot, for saving sram at exit
|
||||
|
||||
auto_free(image.device().machine(), ROM);
|
||||
|
||||
return IMAGE_INIT_PASS;
|
||||
}
|
||||
|
||||
@ -1212,31 +899,10 @@ DRIVER_INIT_MEMBER(snes_state,snes_mess)
|
||||
|
||||
DRIVER_INIT_MEMBER(snes_state,snesst)
|
||||
{
|
||||
UINT8 *STBIOS = memregion("sufami")->base();
|
||||
int i, j;
|
||||
|
||||
m_cart[0].slot_in_use = 0;
|
||||
m_cart[1].slot_in_use = 0;
|
||||
|
||||
DRIVER_INIT_CALL(snes_mess);
|
||||
|
||||
// the Base ST cart consists of 8 * 0x8000 block which have to be loaded (and mirrored)
|
||||
// at 0x00-0x1f:0x8000-0xffff and 0x80-0x9f:0x8000-0xffff
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
/* Loading data */
|
||||
memcpy(&snes_ram[0x008000 + i * 0x10000], &STBIOS[0x000000 + i * 0x8000], 0x8000);
|
||||
/* Mirroring */
|
||||
memcpy(&snes_ram[0x808000 + i * 0x10000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
|
||||
|
||||
/* Additional mirrors (to fill snes_ram up to 0x1fffff) */
|
||||
for (j = 1; j < 4; j++)
|
||||
{
|
||||
memcpy(&snes_ram[0x008000 + i * 0x10000 + j * 0x80000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
|
||||
memcpy(&snes_ram[0x808000 + i * 0x10000 + j * 0x80000], &snes_ram[0x8000 + (i * 0x10000)], 0x8000);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// add-on chip emulators
|
||||
|
Loading…
Reference in New Issue
Block a user