From 821f2c55b95748934d4c23770297dacd5d473743 Mon Sep 17 00:00:00 2001 From: Fabio Priuli Date: Sun, 6 Jun 2010 14:08:21 +0000 Subject: [PATCH] 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... --- src/mame/machine/vsnes.c | 106 ++++++++++++++++++++------------------- src/mame/video/ppu2c0x.c | 26 +++++----- 2 files changed, 69 insertions(+), 63 deletions(-) diff --git a/src/mame/machine/vsnes.c b/src/mame/machine/vsnes.c index 0951a3a1f7c..03b9e48b614 100644 --- a/src/mame/machine/vsnes.c +++ b/src/mame/machine/vsnes.c @@ -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); diff --git a/src/mame/video/ppu2c0x.c b/src/mame/video/ppu2c0x.c index 92a77afecd0..d44e0752cf8 100644 --- a/src/mame/video/ppu2c0x.c +++ b/src/mame/video/ppu2c0x.c @@ -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; } /*************************************