vsnes.c: Reworked VROM banking to avoid pointing beyond the last bank. Also, changed the use of memory_set_bankptr into memory_set_bank. [Fabio Priuli]

Finally, this patch also updates PPU regs latching according to NEStopia behavior. but I'm still investigating if this change is 100% correct or if some further modification is required...
This commit is contained in:
Fabio Priuli 2010-06-06 14:08:21 +00:00
parent 631fd6601b
commit 821f2c55b9
2 changed files with 69 additions and 63 deletions

View File

@ -31,13 +31,16 @@ static UINT8* vram = NULL;
static UINT8* vrom[2];
static UINT8* nt_ram[2];
static UINT8* nt_page[2][4]; // because mirroring is used.
static UINT32 vrom_size[2];
static int vrom_banks;
/* Prototypes for mapping board components to PPU bus */
static WRITE8_HANDLER( vsnes_nt0_w );
static WRITE8_HANDLER( vsnes_nt1_w );
static READ8_HANDLER( vsnes_nt0_r );
static READ8_HANDLER( vsnes_nt1_r );
static void v_set_videorom_bank( running_machine* machine, int start, int count, int bank, int bank_size_in_kb );
static const char * const chr_banknames[] = { "bank2", "bank3", "bank4", "bank5", "bank6", "bank7", "bank8", "bank9" };
/*************************************
*
@ -179,9 +182,27 @@ MACHINE_RESET( vsdual )
*
*************************************/
static void v_set_videorom_bank( running_machine* machine, int start, int count, int vrom_start_bank )
{
int i;
assert(start + count < 8);
vrom_start_bank &= (vrom_banks - 1);
assert(vrom_start_bank + count < vrom_banks);
/* bank_size_in_kb is used to determine how large the "bank" parameter is */
/* count determines the size of the area mapped */
for (i = 0; i < count; i++)
{
memory_set_bank(machine, chr_banknames[i + start], vrom_start_bank + i);
}
}
MACHINE_START( vsnes )
{
const address_space *ppu1_space = cpu_get_address_space(devtag_get_device(machine, "ppu1"), ADDRESS_SPACE_PROGRAM);
int i;
/* establish nametable ram */
nt_ram[0] = auto_alloc_array(machine, UINT8, 0x1000);
@ -194,21 +215,20 @@ MACHINE_START( vsnes )
memory_install_readwrite8_handler(ppu1_space, 0x2000, 0x3eff, 0, 0, vsnes_nt0_r, vsnes_nt0_w);
vrom[0] = memory_region(machine, "gfx1");
vrom_size[0] = memory_region_length(machine, "gfx1");
vrom_banks = vrom_size[0] / 0x400;
/* establish chr banks */
/* bank 1 is used already! */
/* DRIVER_INIT is called first - means we can handle this different for VRAM games! */
if (NULL != vrom[0])
{
memory_install_read_bank(ppu1_space, 0x0000, 0x03ff, 0, 0, "bank2");
memory_install_read_bank(ppu1_space, 0x0400, 0x07ff, 0, 0, "bank3");
memory_install_read_bank(ppu1_space, 0x0800, 0x0bff, 0, 0, "bank4");
memory_install_read_bank(ppu1_space, 0x0c00, 0x0fff, 0, 0, "bank5");
memory_install_read_bank(ppu1_space, 0x1000, 0x13ff, 0, 0, "bank6");
memory_install_read_bank(ppu1_space, 0x1400, 0x17ff, 0, 0, "bank7");
memory_install_read_bank(ppu1_space, 0x1800, 0x1bff, 0, 0, "bank8");
memory_install_read_bank(ppu1_space, 0x1c00, 0x1fff, 0, 0, "bank9");
v_set_videorom_bank(machine, 0, 8, 0, 8);
for (i = 0; i < 8; i++)
{
memory_install_read_bank(ppu1_space, 0x0400 * i, 0x0400 * i + 0x03ff, 0, 0, chr_banknames[i]);
memory_configure_bank(machine, chr_banknames[i], 0, vrom_banks, vrom[0], 0x400);
}
v_set_videorom_bank(machine, 0, 8, 0);
}
else
{
@ -216,16 +236,12 @@ MACHINE_START( vsnes )
}
}
/*************************************
*
* Init machine
*
*************************************/
MACHINE_START( vsdual )
{
vrom[0] = memory_region(machine, "gfx1");
vrom[1] = memory_region(machine, "gfx2");
vrom_size[0] = memory_region_length(machine, "gfx1");
vrom_size[1] = memory_region_length(machine, "gfx2");
/* establish nametable ram */
nt_ram[0] = auto_alloc_array(machine, UINT8, 0x1000);
@ -246,8 +262,10 @@ MACHINE_START( vsdual )
memory_install_read_bank(cpu_get_address_space(devtag_get_device(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x0000, 0x1fff, 0, 0, "bank2");
// read only!
memory_install_read_bank(cpu_get_address_space(devtag_get_device(machine, "ppu2"), ADDRESS_SPACE_PROGRAM), 0x0000, 0x1fff, 0, 0, "bank3");
memory_set_bankptr(machine, "bank2", vrom[0]);
memory_set_bankptr(machine, "bank3", vrom[1]);
memory_configure_bank(machine, "bank2", 0, vrom_size[0] / 0x2000, vrom[0], 0x2000);
memory_configure_bank(machine, "bank3", 0, vrom_size[1] / 0x2000, vrom[1], 0x2000);
memory_set_bank(machine, "bank2", 0);
memory_set_bank(machine, "bank3", 0);
}
/*************************************
@ -313,20 +331,6 @@ static void v_set_mirroring( int ppu, int mirroring )
}
static const char * const banknames[] = { "bank2", "bank3", "bank4", "bank5", "bank6", "bank7", "bank8", "bank9" };
static void v_set_videorom_bank( running_machine* machine, int start, int count, int bank, int bank_size_in_kb )
{
int i;
int offset = bank * (bank_size_in_kb * 0x400);
/* bank_size_in_kb is used to determine how large the "bank" parameter is */
/* count determines the size of the area mapped */
for (i = 0; i < count; i++, offset += 0x400)
{
memory_set_bankptr(machine, banknames[i + start], vrom[0] + offset);
}
}
/**********************************************************************************
*
* Game and Board-specific initialization
@ -339,7 +343,7 @@ static void v_set_videorom_bank( running_machine* machine, int start, int count,
static WRITE8_HANDLER( vsnormal_vrom_banking )
{
/* switch vrom */
v_set_videorom_bank(space->machine, 0, 8, (data & 4) ? 1 : 0, 8);
v_set_videorom_bank(space->machine, 0, 8, (data & 4) ? 8 : 0);
/* bit 1 ( data & 2 ) enables writes to extra ram, we ignore it */
@ -364,7 +368,7 @@ static WRITE8_HANDLER( gun_in0_w )
if (vsnes_do_vrom_bank)
{
/* switch vrom */
v_set_videorom_bank(space->machine, 0, 8, (data & 4) ? 1 : 0, 8);
v_set_videorom_bank(space->machine, 0, 8, (data & 4) ? 8 : 0);
}
/* here we do things a little different */
@ -431,11 +435,11 @@ static WRITE8_HANDLER( vskonami_rom_banking )
break;
case 6: /* vrom bank 0 */
v_set_videorom_bank(space->machine, 0, 4, data, 4);
v_set_videorom_bank(space->machine, 0, 4, data * 4);
break;
case 7: /* vrom bank 1 */
v_set_videorom_bank(space->machine, 4, 4, data, 4);
v_set_videorom_bank(space->machine, 4, 4, data * 4);
break;
}
}
@ -559,12 +563,12 @@ static WRITE8_HANDLER( drmario_rom_banking )
case 1: /* video rom banking - bank 0 - 4k or 8k */
if (!vram)
v_set_videorom_bank(space->machine, 0, (vrom4k) ? 4 : 8, drmario_shiftreg, (vrom4k) ? 4 : 8);
v_set_videorom_bank(space->machine, 0, (vrom4k) ? 4 : 8, drmario_shiftreg * 4);
break;
case 2: /* video rom banking - bank 1 - 4k only */
if (vrom4k && !vram)
v_set_videorom_bank(space->machine, 4, 4, drmario_shiftreg, 4);
v_set_videorom_bank(space->machine, 4, 4, drmario_shiftreg * 4);
break;
case 3: /* program banking */
@ -661,14 +665,14 @@ static void mapper4_set_chr( running_machine *machine )
{
UINT8 chr_page = (MMC3_cmd & 0x80) >> 5;
v_set_videorom_bank(machine, chr_page ^ 0, 1, MMC3_chr_bank[0] & ~0x01, 1);
v_set_videorom_bank(machine, chr_page ^ 1, 1, MMC3_chr_bank[0] | 0x01, 1);
v_set_videorom_bank(machine, chr_page ^ 2, 1, MMC3_chr_bank[1] & ~0x01, 1);
v_set_videorom_bank(machine, chr_page ^ 3, 1, MMC3_chr_bank[1] | 0x01, 1);
v_set_videorom_bank(machine, chr_page ^ 4, 1, MMC3_chr_bank[2], 1);
v_set_videorom_bank(machine, chr_page ^ 5, 1, MMC3_chr_bank[3], 1);
v_set_videorom_bank(machine, chr_page ^ 6, 1, MMC3_chr_bank[4], 1);
v_set_videorom_bank(machine, chr_page ^ 7, 1, MMC3_chr_bank[5], 1);
v_set_videorom_bank(machine, chr_page ^ 0, 1, MMC3_chr_bank[0] & ~0x01);
v_set_videorom_bank(machine, chr_page ^ 1, 1, MMC3_chr_bank[0] | 0x01);
v_set_videorom_bank(machine, chr_page ^ 2, 1, MMC3_chr_bank[1] & ~0x01);
v_set_videorom_bank(machine, chr_page ^ 3, 1, MMC3_chr_bank[1] | 0x01);
v_set_videorom_bank(machine, chr_page ^ 4, 1, MMC3_chr_bank[2]);
v_set_videorom_bank(machine, chr_page ^ 5, 1, MMC3_chr_bank[3]);
v_set_videorom_bank(machine, chr_page ^ 6, 1, MMC3_chr_bank[4]);
v_set_videorom_bank(machine, chr_page ^ 7, 1, MMC3_chr_bank[5]);
}
#define BOTTOM_VISIBLE_SCANLINE 239 /* The bottommost visible scanline */
@ -940,19 +944,19 @@ static WRITE8_HANDLER( mapper68_rom_banking )
switch (offset & 0x7000)
{
case 0x0000:
v_set_videorom_bank(space->machine, 0, 2, data, 2);
v_set_videorom_bank(space->machine, 0, 2, data * 2);
break;
case 0x1000:
v_set_videorom_bank(space->machine, 2, 2, data, 2);
v_set_videorom_bank(space->machine, 2, 2, data * 2);
break;
case 0x2000:
v_set_videorom_bank(space->machine, 4, 2, data, 2);
v_set_videorom_bank(space->machine, 4, 2, data * 2);
break;
case 0x3000: /* ok? */
v_set_videorom_bank(space->machine, 6, 2, data, 2);
v_set_videorom_bank(space->machine, 6, 2, data * 2);
break;
@ -1018,7 +1022,7 @@ static WRITE8_HANDLER( vsdual_vrom_banking )
running_device *other_cpu = (space->cpu == devtag_get_device(space->machine, "maincpu")) ? devtag_get_device(space->machine, "sub") : devtag_get_device(space->machine, "maincpu");
/* switch vrom */
(space->cpu == devtag_get_device(space->machine, "maincpu")) ? memory_set_bankptr(space->machine, "bank2", (data & 4) ? vrom[0] + 0x2000 : vrom[0]) : memory_set_bankptr(space->machine, "bank3", (data & 4) ? vrom[1] + 0x2000 : vrom[1]);
(space->cpu == devtag_get_device(space->machine, "maincpu")) ? memory_set_bank(space->machine, "bank2", BIT(data, 2)) : memory_set_bank(space->machine, "bank3", BIT(data, 2));
/* bit 1 ( data & 2 ) triggers irq on the other cpu */
cpu_set_input_line(other_cpu, 0, (data & 2) ? CLEAR_LINE : ASSERT_LINE);

View File

@ -966,14 +966,14 @@ READ8_DEVICE_HANDLER( ppu2c0x_r )
if (offset >= PPU_MAX_REG)
{
logerror("PPU %s(r): Attempting to read past the chip\n", device->tag());
logerror("PPU %s: Attempting to read past the chip: offset %x\n", device->tag(), offset);
offset &= PPU_MAX_REG - 1;
}
// see which register to read
switch (offset & 7)
{
case PPU_STATUS:
case PPU_STATUS: /* 2 */
// The top 3 bits of the status register are the only ones that report data. The
// remainder contain whatever was last in the PPU data latch, except on the RC2C05 (protection)
if (ppu2c0x->security_value)
@ -989,11 +989,11 @@ READ8_DEVICE_HANDLER( ppu2c0x_r )
ppu2c0x->regs[PPU_STATUS] &= 0x60;
break;
case PPU_SPRITE_DATA:
case PPU_SPRITE_DATA: /* 4 */
ppu2c0x->data_latch = ppu2c0x->spriteram[ppu2c0x->regs[PPU_SPRITE_ADDRESS]];
break;
case PPU_DATA:
case PPU_DATA: /* 7 */
if (ppu_latch)
(*ppu_latch)(device, ppu2c0x->videomem_addr & 0x3fff);
@ -1035,7 +1035,7 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w )
if (offset >= PPU_MAX_REG)
{
logerror("PPU: Attempting to write past the chip\n");
logerror("PPU %s: Attempting to write past the chip: offset %x, data %x\n", device->tag(), offset, data);
offset &= PPU_MAX_REG - 1;
}
@ -1053,7 +1053,7 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w )
switch (offset & 7)
{
case PPU_CONTROL0:
case PPU_CONTROL0: /* 0 */
ppu2c0x->regs[PPU_CONTROL0] = data;
/* update the name table number on our refresh latches */
@ -1068,7 +1068,7 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w )
// logerror("control0 write: %02x (scanline: %d)\n", data, ppu2c0x->scanline);
break;
case PPU_CONTROL1:
case PPU_CONTROL1: /* 1 */
/* if color intensity has changed, change all the color tables to reflect them */
if ((data & PPU_CONTROL1_COLOR_EMPHASIS) != (ppu2c0x->regs[PPU_CONTROL1] & PPU_CONTROL1_COLOR_EMPHASIS))
{
@ -1085,11 +1085,11 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w )
ppu2c0x->regs[PPU_CONTROL1] = data;
break;
case PPU_SPRITE_ADDRESS:
case PPU_SPRITE_ADDRESS: /* 3 */
ppu2c0x->regs[PPU_SPRITE_ADDRESS] = data;
break;
case PPU_SPRITE_DATA:
case PPU_SPRITE_DATA: /* 4 */
// If the PPU is currently rendering the screen, 0xff is written instead of the desired data.
if (ppu2c0x->scanline <= PPU_BOTTOM_VISIBLE_SCANLINE)
data = 0xff;
@ -1097,7 +1097,7 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w )
ppu2c0x->regs[PPU_SPRITE_ADDRESS] = (ppu2c0x->regs[PPU_SPRITE_ADDRESS] + 1) & 0xff;
break;
case PPU_SCROLL:
case PPU_SCROLL: /* 5 */
if (ppu2c0x->toggle)
{
/* second write */
@ -1119,7 +1119,7 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w )
ppu2c0x->toggle ^= 1;
break;
case PPU_ADDRESS:
case PPU_ADDRESS: /* 6 */
if (ppu2c0x->toggle)
{
/* second write */
@ -1141,7 +1141,7 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w )
ppu2c0x->toggle ^= 1;
break;
case PPU_DATA:
case PPU_DATA: /* 7 */
{
int tempAddr = ppu2c0x->videomem_addr & 0x3fff;
@ -1172,6 +1172,8 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w )
/* ignore other registers writes */
break;
}
ppu2c0x->data_latch = data;
}
/*************************************