From fd631b29b6eb078828a6f404491bf608820a71d7 Mon Sep 17 00:00:00 2001 From: Fabio Priuli Date: Fri, 31 Jul 2009 09:10:31 +0000 Subject: [PATCH] Commit of Robert Bohms' NES PPU updates (please refer to his -emails for details) Also, not worth mention, I've done some readability tweaks and fixed some crashes in cham24 and multigam (due to wrong copy and paste in the original diffs). multigam.c games still have some issues (which I'm trying to fix with Rob's help) --- src/mame/drivers/cham24.c | 105 +++-- src/mame/drivers/multigam.c | 226 +++++++--- src/mame/drivers/playch10.c | 2 + src/mame/drivers/vsnes.c | 2 + src/mame/includes/playch10.h | 2 + src/mame/includes/vsnes.h | 2 + src/mame/machine/playch10.c | 493 ++++++++++++++------- src/mame/machine/vsnes.c | 480 ++++++++++++++------- src/mame/video/ppu2c0x.c | 813 +++++++++++++++-------------------- src/mame/video/ppu2c0x.h | 3 - 10 files changed, 1260 insertions(+), 868 deletions(-) diff --git a/src/mame/drivers/cham24.c b/src/mame/drivers/cham24.c index 18985b16a89..313162cbe53 100644 --- a/src/mame/drivers/cham24.c +++ b/src/mame/drivers/cham24.c @@ -60,10 +60,58 @@ Notes: #include "sound/nes_apu.h" #include "video/ppu2c0x.h" +static UINT8* nt_ram; +static UINT8* nt_page[4]; + +void cham24_set_mirroring( int mirroring ) +{ + switch(mirroring) + { + case PPU_MIRROR_LOW: + nt_page[0] = nt_page[1] = nt_page[2] = nt_page[3] = nt_ram; + break; + case PPU_MIRROR_HIGH: + nt_page[0] = nt_page[1] = nt_page[2] = nt_page[3] = nt_ram + 0x400; + break; + case PPU_MIRROR_HORZ: + nt_page[0] = nt_ram; + nt_page[1] = nt_ram; + nt_page[2] = nt_ram + 0x400; + nt_page[3] = nt_ram + 0x400; + break; + case PPU_MIRROR_VERT: + nt_page[0] = nt_ram; + nt_page[1] = nt_ram + 0x400; + nt_page[2] = nt_ram; + nt_page[3] = nt_ram + 0x400; + break; + case PPU_MIRROR_NONE: + default: + nt_page[0] = nt_ram; + nt_page[1] = nt_ram + 0x400; + nt_page[2] = nt_ram + 0x800; + nt_page[3] = nt_ram + 0xc00; + break; + } +} + +static WRITE8_HANDLER( nt_w ) +{ + int page = ((offset & 0xc00) >> 10); + nt_page[page][offset & 0x3ff] = data; +} + +static READ8_HANDLER( nt_r ) +{ + int page = ((offset & 0xc00) >> 10); + return nt_page[page][offset & 0x3ff]; + +} + static WRITE8_HANDLER( sprite_dma_w ) { - int source = ( data & 7 ); - ppu2c0x_spriteram_dma( space, devtag_get_device(space->machine, "ppu"), source ); + int source = (data & 7); + ppu2c0x_spriteram_dma(space, devtag_get_device(space->machine, "ppu"), source); } static READ8_DEVICE_HANDLER( psg_4015_r ) @@ -93,12 +141,12 @@ static READ8_HANDLER( cham24_IN0_r ) static WRITE8_HANDLER( cham24_IN0_w ) { - if ( data & 0xfe ) + if (data & 0xfe) { - //logerror( "Unhandled cham24_IN0_w write: data = %02X\n", data ); + //logerror("Unhandled cham24_IN0_w write: data = %02X\n", data); } - if ( data & 0x01 ) + if (data & 0x01) { return; } @@ -123,36 +171,35 @@ static WRITE8_HANDLER( cham24_mapper_w ) UINT32 prg_bank = (offset >> 7) & 0x1f; UINT32 prg_bank_page_size = (offset >> 12) & 0x01; UINT32 gfx_mirroring = (offset >> 13) & 0x01; - const device_config *ppu = devtag_get_device(space->machine, "ppu"); - UINT8* dst = memory_region( space->machine, "maincpu" ); - UINT8* src = memory_region( space->machine, "user1" ); + UINT8* dst = memory_region(space->machine, "maincpu"); + UINT8* src = memory_region(space->machine, "user1"); // switch PPU VROM bank - ppu2c0x_set_videorom_bank( ppu, 0, 8, gfx_bank, 512 ); + memory_set_bankptr(space->machine, 1, memory_region(space->machine, "gfx1") + (0x2000 * gfx_bank)); // set gfx mirroring - ppu2c0x_set_mirroring( ppu, gfx_mirroring != 0 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT ); + cham24_set_mirroring(gfx_mirroring != 0 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); // switch PRG bank - if ( prg_bank_page_size == 0 ) + if (prg_bank_page_size == 0) { // 32K - memcpy( &dst[0x8000], &src[prg_bank * 0x8000], 0x8000 ); + memcpy(&dst[0x8000], &src[prg_bank * 0x8000], 0x8000); } else { - if ( prg_16k_bank_page == 1 ) + if (prg_16k_bank_page == 1) { // upper half of 32K page - memcpy( &dst[0x8000], &src[(prg_bank * 0x8000) + 0x4000], 0x4000 ); - memcpy( &dst[0xC000], &src[(prg_bank * 0x8000) + 0x4000], 0x4000 ); + memcpy(&dst[0x8000], &src[(prg_bank * 0x8000) + 0x4000], 0x4000); + memcpy(&dst[0xC000], &src[(prg_bank * 0x8000) + 0x4000], 0x4000); } else { // lower half of 32K page - memcpy( &dst[0x8000], &src[(prg_bank * 0x8000)], 0x4000 ); - memcpy( &dst[0xC000], &src[(prg_bank * 0x8000)], 0x4000 ); + memcpy(&dst[0x8000], &src[(prg_bank * 0x8000)], 0x4000); + memcpy(&dst[0xC000], &src[(prg_bank * 0x8000)], 0x4000); } } } @@ -188,7 +235,6 @@ static INPUT_PORTS_START( cham24 ) PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) - INPUT_PORTS_END static const nes_interface cham24_interface_1 = @@ -199,21 +245,21 @@ static const nes_interface cham24_interface_1 = static MACHINE_RESET( cham24 ) { /* switch PRG rom */ - UINT8* dst = memory_region( machine, "maincpu" ); - UINT8* src = memory_region( machine, "user1" ); + UINT8* dst = memory_region(machine, "maincpu"); + UINT8* src = memory_region(machine, "user1"); - memcpy( &dst[0x8000], &src[0x0f8000], 0x4000 ); - memcpy( &dst[0xc000], &src[0x0f8000], 0x4000 ); + memcpy(&dst[0x8000], &src[0x0f8000], 0x4000); + memcpy(&dst[0xc000], &src[0x0f8000], 0x4000); } static PALETTE_INIT( cham24 ) { - ppu2c0x_init_palette(machine, 0 ); + ppu2c0x_init_palette(machine, 0); } static void ppu_irq( const device_config *device, int *ppu_regs ) { - cputag_set_input_line(device->machine, "maincpu", INPUT_LINE_NMI, PULSE_LINE ); + cputag_set_input_line(device->machine, "maincpu", INPUT_LINE_NMI, PULSE_LINE); } /* our ppu interface */ @@ -233,12 +279,21 @@ static VIDEO_START( cham24 ) static VIDEO_UPDATE( cham24 ) { /* render the ppu */ - ppu2c0x_render( devtag_get_device(screen->machine, "ppu"), bitmap, 0, 0, 0, 0 ); + ppu2c0x_render(devtag_get_device(screen->machine, "ppu"), bitmap, 0, 0, 0, 0); return 0; } static DRIVER_INIT( cham24 ) { + /* uses 8K swapping, all ROM!*/ + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x0000, 0x1fff, 0, 0, SMH_BANK(1), 0); + memory_set_bankptr(machine, 1, memory_region(machine, "gfx1")); + + /* need nametable ram, though. I doubt this uses more than 2k, but it starts up configured for 4 */ + nt_ram = auto_alloc_array(machine, UINT8, 0x1000); + + /* and read/write handlers */ + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x2000, 0x3eff, 0, 0, nt_r, nt_w); } static GFXDECODE_START( cham24 ) diff --git a/src/mame/drivers/multigam.c b/src/mame/drivers/multigam.c index 1a4bda8aec8..7d63e862fe5 100644 --- a/src/mame/drivers/multigam.c +++ b/src/mame/drivers/multigam.c @@ -45,6 +45,69 @@ #include "sound/nes_apu.h" #include "video/ppu2c0x.h" +/****************************************************** + + PPU external bus interface + +*******************************************************/ +static UINT8* nt_ram; +static UINT8* nt_page[4]; + +void set_mirroring(int mirroring) +{ + switch(mirroring) + { + case PPU_MIRROR_LOW: + nt_page[0] = nt_page[1] = nt_page[2] = nt_page[3] = nt_ram; + break; + case PPU_MIRROR_HIGH: + nt_page[0] = nt_page[1] = nt_page[2] = nt_page[3] = nt_ram + 0x400; + break; + case PPU_MIRROR_HORZ: + nt_page[0] = nt_ram; + nt_page[1] = nt_ram; + nt_page[2] = nt_ram + 0x400; + nt_page[3] = nt_ram + 0x400; + break; + case PPU_MIRROR_VERT: + nt_page[0] = nt_ram; + nt_page[1] = nt_ram + 0x400; + nt_page[2] = nt_ram; + nt_page[3] = nt_ram + 0x400; + break; + case PPU_MIRROR_NONE: + default: + nt_page[0] = nt_ram; + nt_page[1] = nt_ram + 0x400; + nt_page[2] = nt_ram + 0x800; + nt_page[3] = nt_ram + 0xc00; + break; + } +} +static WRITE8_HANDLER (multigam_nt_w) +{ + int page = ((offset & 0xc00) >> 10); + nt_page[page][offset & 0x3ff] = data; +} +static READ8_HANDLER (multigam_nt_r) +{ + int page = ((offset & 0xc00) >> 10); + return nt_page[page][offset & 0x3ff]; +} + +void set_videorom_bank(running_machine* machine, int start, int count, int bank, int bank_size_in_kb) +{ + int i, j; + 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 in KB */ + for (i = 0; i < count; i++) + { + j = i + start + 1; + memory_set_bankptr(machine, j, memory_region(machine, "gfx1") + offset); + } +} + /****************************************************** NES interface @@ -53,8 +116,8 @@ static WRITE8_HANDLER( sprite_dma_w ) { - int source = ( data & 7 ); - ppu2c0x_spriteram_dma( space, devtag_get_device(space->machine, "ppu"), source ); + int source = (data & 7); + ppu2c0x_spriteram_dma(space, devtag_get_device(space->machine, "ppu"), source); } static READ8_DEVICE_HANDLER( psg_4015_r ) @@ -92,7 +155,7 @@ static READ8_HANDLER( multigam_IN0_r ) static WRITE8_HANDLER( multigam_IN0_w ) { - if ( data & 0x01 ) + if (data & 0x01) { return; } @@ -131,43 +194,41 @@ static int multigam_game_gfx_bank = 0; static WRITE8_HANDLER(multigam_switch_prg_rom) { /* switch PRG rom */ - UINT8* dst = memory_region( space->machine, "maincpu" ); - UINT8* src = memory_region( space->machine, "user1" ); + UINT8* dst = memory_region(space->machine, "maincpu"); + UINT8* src = memory_region(space->machine, "user1"); - if ( data & 0x80 ) + if (data & 0x80) { - if ( data & 0x01 ) + if (data & 0x01) { data &= ~0x01; } - memcpy( &dst[0x8000], &src[(data & 0x7f) * 0x4000], 0x8000 ); + memcpy(&dst[0x8000], &src[(data & 0x7f) * 0x4000], 0x8000); } else { - memcpy( &dst[0x8000], &src[data*0x4000], 0x4000 ); - memcpy( &dst[0xc000], &src[data*0x4000], 0x4000 ); + memcpy(&dst[0x8000], &src[data*0x4000], 0x4000); + memcpy(&dst[0xc000], &src[data*0x4000], 0x4000); } }; static WRITE8_HANDLER(multigam_switch_gfx_rom) { - const device_config *ppu = devtag_get_device(space->machine, "ppu"); - ppu2c0x_set_videorom_bank( ppu, 0, 8, data /*& 0x3f*/, 512 ); - ppu2c0x_set_mirroring( ppu, data & 0x40 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT ); + memory_set_bankptr(space->machine, 1, memory_region(space->machine, "gfx1") + (0x2000 * data)); + set_mirroring(data & 0x40 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); multigam_game_gfx_bank = data; }; static WRITE8_HANDLER(multigam_mapper2_w) { - if ( multigam_game_gfx_bank & 0x80 ) + if (multigam_game_gfx_bank & 0x80) { - const device_config *ppu = devtag_get_device(space->machine, "ppu"); - ppu2c0x_set_videorom_bank( ppu, 0, 8, multigam_game_gfx_bank + (data & 0xf), 512 ); + memory_set_bankptr(space->machine, 1, memory_region(space->machine, "gfx1") + (0x2000 * ((data & 0xf) + multigam_game_gfx_bank))); } else { - logerror( "Unmapped multigam_mapper2_w: offset = %04X, data = %02X\n", offset, data ); + logerror("Unmapped multigam_mapper2_w: offset = %04X, data = %02X\n", offset, data); } } @@ -210,9 +271,9 @@ static UINT8* multigmc_mmc3_6000_ram; static void multigam3_mmc3_scanline_cb( const device_config *device, int scanline, int vblank, int blanked ) { - if ( !vblank && !blanked ) + if (!vblank && !blanked) { - if ( --multigam3_mmc3_scanline_counter == -1 ) + if (--multigam3_mmc3_scanline_counter == -1) { multigam3_mmc3_scanline_counter = multigam3_mmc3_scanline_latch; generic_pulse_irq_line(cputag_get_cpu(device->machine, "maincpu"), 0); @@ -227,38 +288,38 @@ static WRITE8_HANDLER( multigam3_mmc3_rom_switch_w ) /* basically, a MMC3 mapper from the nes */ static int multigam3_mmc3_command; - switch( offset & 0x7001 ) + switch(offset & 0x7001) { case 0x0000: multigam3_mmc3_command = data; - if ( multigam3_mmc3_last_bank != ( data & 0xc0 ) ) + if (multigam3_mmc3_last_bank != (data & 0xc0)) { int bank; - UINT8 *prg = memory_region( space->machine, "maincpu" ); - UINT8 *src = memory_region( space->machine, "user1" ); + UINT8 *prg = memory_region(space->machine, "maincpu"); + UINT8 *src = memory_region(space->machine, "user1"); /* reset the banks */ - if ( multigam3_mmc3_command & 0x40 ) + if (multigam3_mmc3_command & 0x40) { /* high bank */ bank = multigam3_mmc3_banks[0] * 0x2000 + 0xa0000; - memcpy( &prg[0x0c000], &src[bank], 0x2000 ); - memcpy( &prg[0x08000], &src[0xa0000 + 0x3c000], 0x2000 ); + memcpy(&prg[0x0c000], &src[bank], 0x2000); + memcpy(&prg[0x08000], &src[0xa0000 + 0x3c000], 0x2000); } else { /* low bank */ bank = multigam3_mmc3_banks[0] * 0x2000 + 0xa0000; - memcpy( &prg[0x08000], &src[bank], 0x2000 ); - memcpy( &prg[0x0c000], &src[0xa0000 + 0x3c000], 0x2000 ); + memcpy(&prg[0x08000], &src[bank], 0x2000); + memcpy(&prg[0x0c000], &src[0xa0000 + 0x3c000], 0x2000); } /* mid bank */ bank = multigam3_mmc3_banks[1] * 0x2000 + 0xa0000; - memcpy( &prg[0x0a000], &src[bank], 0x2000 ); + memcpy(&prg[0x0a000], &src[bank], 0x2000); multigam3_mmc3_last_bank = data & 0xc0; } @@ -267,16 +328,16 @@ static WRITE8_HANDLER( multigam3_mmc3_rom_switch_w ) case 0x0001: { UINT8 cmd = multigam3_mmc3_command & 0x07; - int page = ( multigam3_mmc3_command & 0x80 ) >> 5; + int page = (multigam3_mmc3_command & 0x80) >> 5; int bank; - switch( cmd ) + switch (cmd) { case 0: /* char banking */ case 1: /* char banking */ data &= 0xfe; - page ^= ( cmd << 1 ); - ppu2c0x_set_videorom_bank( ppu, page, 2, 0x180 + data, 64 ); + page ^= (cmd << 1); + set_videorom_bank(space->machine, page, 2, 0x180 + data, 1); break; case 2: /* char banking */ @@ -284,30 +345,30 @@ static WRITE8_HANDLER( multigam3_mmc3_rom_switch_w ) case 4: /* char banking */ case 5: /* char banking */ page ^= cmd + 2; - ppu2c0x_set_videorom_bank( ppu, page, 1, 0x180 + data, 64 ); + set_videorom_bank(space->machine, page, 1, 0x180 + data, 1); break; case 6: /* program banking */ { - UINT8 *prg = memory_region( space->machine, "maincpu" ); - UINT8 *src = memory_region( space->machine, "user1" ); - if ( multigam3_mmc3_command & 0x40 ) + UINT8 *prg = memory_region(space->machine, "maincpu"); + UINT8 *src = memory_region(space->machine, "user1"); + if (multigam3_mmc3_command & 0x40) { /* high bank */ multigam3_mmc3_banks[0] = data & 0x1f; - bank = ( multigam3_mmc3_banks[0] ) * 0x2000 + 0xa0000; + bank = (multigam3_mmc3_banks[0]) * 0x2000 + 0xa0000; - memcpy( &prg[0x0c000], &src[bank], 0x2000 ); - memcpy( &prg[0x08000], &src[0xa0000 + 0x3c000], 0x2000 ); + memcpy(&prg[0x0c000], &src[bank], 0x2000); + memcpy(&prg[0x08000], &src[0xa0000 + 0x3c000], 0x2000); } else { /* low bank */ multigam3_mmc3_banks[0] = data & 0x1f; - bank = ( multigam3_mmc3_banks[0] ) * 0x2000 + 0xa0000; + bank = (multigam3_mmc3_banks[0]) * 0x2000 + 0xa0000; - memcpy( &prg[0x08000], &src[bank], 0x2000 ); - memcpy( &prg[0x0c000], &src[0xa0000 + 0x3c000], 0x2000 ); + memcpy(&prg[0x08000], &src[bank], 0x2000); + memcpy(&prg[0x0c000], &src[0xa0000 + 0x3c000], 0x2000); } } break; @@ -315,13 +376,13 @@ static WRITE8_HANDLER( multigam3_mmc3_rom_switch_w ) case 7: /* program banking */ { /* mid bank */ - UINT8 *prg = memory_region( space->machine, "maincpu" ); - UINT8 *src = memory_region( space->machine, "user1" ); + UINT8 *prg = memory_region(space->machine, "maincpu"); + UINT8 *src = memory_region(space->machine, "user1"); multigam3_mmc3_banks[1] = data & 0x1f; bank = multigam3_mmc3_banks[1] * 0x2000 + 0xa0000; - memcpy( &prg[0x0a000], &src[bank], 0x2000 ); + memcpy(&prg[0x0a000], &src[bank], 0x2000); } break; } @@ -329,12 +390,12 @@ static WRITE8_HANDLER( multigam3_mmc3_rom_switch_w ) break; case 0x2000: /* mirroring */ - if( !multigam3_mmc3_4screen ) + if (!multigam3_mmc3_4screen) { - if ( data & 0x40 ) - ppu2c0x_set_mirroring( ppu, PPU_MIRROR_HIGH ); + if (data & 0x40) + set_mirroring(PPU_MIRROR_HIGH); else - ppu2c0x_set_mirroring( ppu, ( data & 1 ) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT ); + set_mirroring((data & 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); } break; @@ -351,19 +412,19 @@ static WRITE8_HANDLER( multigam3_mmc3_rom_switch_w ) break; case 0x6000: /* disable irqs */ - ppu2c0x_set_scanline_callback( ppu, 0 ); + ppu2c0x_set_scanline_callback(ppu, 0); break; case 0x6001: /* enable irqs */ - ppu2c0x_set_scanline_callback( ppu, multigam3_mmc3_scanline_cb ); + ppu2c0x_set_scanline_callback(ppu, multigam3_mmc3_scanline_cb); break; } } static void multigam_init_smb3(running_machine *machine) { - UINT8* dst = memory_region( machine, "maincpu" ); - UINT8* src = memory_region( machine, "user1" ); + UINT8* dst = memory_region(machine, "maincpu"); + UINT8* src = memory_region(machine, "user1"); memcpy(&dst[0x8000], &src[0xa0000 + 0x3c000], 0x4000); memcpy(&dst[0xc000], &src[0xa0000 + 0x3c000], 0x4000); @@ -383,24 +444,23 @@ static void multigam_init_smb3(running_machine *machine) static WRITE8_HANDLER(multigm3_mapper2_w) { - if ( multigam_game_gfx_bank & 0x80 ) + if (multigam_game_gfx_bank & 0x80) { - const device_config *ppu = devtag_get_device(space->machine, "ppu"); - ppu2c0x_set_videorom_bank( ppu, 0, 8, (multigam_game_gfx_bank & 0xfc) + (data & 0x3), 512 ); + set_videorom_bank(space->machine, 0, 8, (multigam_game_gfx_bank & 0xfc) + (data & 0x3), 8); } else { - logerror( "Unmapped multigam_mapper2_w: offset = %04X, data = %02X\n", offset, data ); + logerror("Unmapped multigam_mapper2_w: offset = %04X, data = %02X\n", offset, data); } }; static WRITE8_HANDLER(multigm3_switch_prg_rom) { /* switch PRG rom */ - UINT8* dst = memory_region( space->machine, "maincpu" ); - UINT8* src = memory_region( space->machine, "user1" ); + UINT8* dst = memory_region(space->machine, "maincpu"); + UINT8* src = memory_region(space->machine, "user1"); - if ( data == 0xa8 ) + if (data == 0xa8) { multigam_init_smb3(space->machine); return; @@ -411,18 +471,18 @@ static WRITE8_HANDLER(multigm3_switch_prg_rom) memory_set_bankptr(space->machine, 1, memory_region(space->machine, "maincpu") + 0x6000); } - if ( data & 0x80 ) + if (data & 0x80) { - if ( data & 0x01 ) + if (data & 0x01) { data &= ~0x01; } - memcpy( &dst[0x8000], &src[(data & 0x7f) * 0x4000], 0x8000 ); + memcpy(&dst[0x8000], &src[(data & 0x7f) * 0x4000], 0x8000); } else { - memcpy( &dst[0x8000], &src[data*0x4000], 0x4000 ); - memcpy( &dst[0xc000], &src[data*0x4000], 0x4000 ); + memcpy(&dst[0x8000], &src[data*0x4000], 0x4000); + memcpy(&dst[0xc000], &src[data*0x4000], 0x4000); } }; @@ -530,12 +590,12 @@ static const nes_interface multigam_interface_1 = static PALETTE_INIT( multigam ) { - ppu2c0x_init_palette(machine, 0 ); + ppu2c0x_init_palette(machine, 0); } static void ppu_irq( const device_config *device, int *ppu_regs ) { - cputag_set_input_line(device->machine, "maincpu", INPUT_LINE_NMI, PULSE_LINE ); + cputag_set_input_line(device->machine, "maincpu", INPUT_LINE_NMI, PULSE_LINE); } /* our ppu interface */ @@ -555,7 +615,7 @@ static VIDEO_START( multigam ) static VIDEO_UPDATE( multigam ) { /* render the ppu */ - ppu2c0x_render( devtag_get_device(screen->machine, "ppu"), bitmap, 0, 0, 0, 0 ); + ppu2c0x_render(devtag_get_device(screen->machine, "ppu"), bitmap, 0, 0, 0, 0); return 0; } @@ -580,6 +640,28 @@ static MACHINE_RESET( multigm3 ) multigm3_switch_prg_rom(space, 0, 0x01 ); }; +static MACHINE_START( multigam ) +{ + nt_ram = auto_alloc_array(machine, UINT8, 0x1000); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x2000, 0x3eff, 0, 0, multigam_nt_r, multigam_nt_w); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x0000, 0x1fff, 0, 0, SMH_BANK(1), 0); + memory_set_bankptr(machine, 1, memory_region(machine, "gfx1")); +} + +static MACHINE_START( multigm3 ) +{ + nt_ram = auto_alloc_array(machine, UINT8, 0x1000); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x2000, 0x3eff, 0, 0, multigam_nt_r, multigam_nt_w); + + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x0000, 0x03ff, 0, 0, SMH_BANK(1), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x0400, 0x07ff, 0, 0, SMH_BANK(2), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x0800, 0x0bff, 0, 0, SMH_BANK(3), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x0c00, 0x0fff, 0, 0, SMH_BANK(4), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x1000, 0x13ff, 0, 0, SMH_BANK(5), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x1400, 0x17ff, 0, 0, SMH_BANK(6), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x1800, 0x1bff, 0, 0, SMH_BANK(7), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x1c00, 0x1fff, 0, 0, SMH_BANK(8), 0); +}; static MACHINE_DRIVER_START( multigam ) /* basic machine hardware */ @@ -587,6 +669,7 @@ static MACHINE_DRIVER_START( multigam ) MDRV_CPU_PROGRAM_MAP(multigam_map) MDRV_MACHINE_RESET( multigam ) + MDRV_MACHINE_START( multigam ) /* video hardware */ MDRV_SCREEN_ADD("screen", RASTER) @@ -620,6 +703,7 @@ static MACHINE_DRIVER_START( multigm3 ) MDRV_CPU_MODIFY("maincpu") MDRV_CPU_PROGRAM_MAP(multigm3_map) + MDRV_MACHINE_START( multigm3 ) MDRV_MACHINE_RESET( multigm3 ) MACHINE_DRIVER_END @@ -704,7 +788,7 @@ ROM_END static DRIVER_INIT( multigam ) { const address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); - multigam_switch_prg_rom( space, 0x0, 0x01 ); + multigam_switch_prg_rom(space, 0x0, 0x01); } static void multigm3_decrypt(UINT8* mem, int memsize, const UINT8* decode_nibble) @@ -727,7 +811,7 @@ static DRIVER_INIT(multigm3) multigmc_mmc3_6000_ram = auto_alloc_array(machine, UINT8, 0x2000); - multigam_switch_prg_rom( space, 0x0, 0x01 ); + multigam_switch_prg_rom(space, 0x0, 0x01); } GAME( 1992, multigam, 0, multigam, multigam, multigam, ROT0, "unknown", "Multi Game (set 1)", 0 ) diff --git a/src/mame/drivers/playch10.c b/src/mame/drivers/playch10.c index 78e4d4d8b64..df7b6c38331 100644 --- a/src/mame/drivers/playch10.c +++ b/src/mame/drivers/playch10.c @@ -702,6 +702,7 @@ static MACHINE_DRIVER_START( playch10 ) MDRV_CPU_PROGRAM_MAP(cart_map) MDRV_MACHINE_RESET(pc10) + MDRV_MACHINE_START(pc10) // video hardware MDRV_GFXDECODE(playch10) @@ -746,6 +747,7 @@ MACHINE_DRIVER_END static MACHINE_DRIVER_START( playch10_hboard ) MDRV_IMPORT_FROM(playch10) MDRV_VIDEO_START(playch10_hboard) + MDRV_MACHINE_START(playch10_hboard) MDRV_DEVICE_REMOVE("ppu") MDRV_PPU2C03B_ADD("ppu", playch10_ppu_interface) diff --git a/src/mame/drivers/vsnes.c b/src/mame/drivers/vsnes.c index ca667e3eecd..edf3fbcffb7 100644 --- a/src/mame/drivers/vsnes.c +++ b/src/mame/drivers/vsnes.c @@ -1768,6 +1768,7 @@ static MACHINE_DRIVER_START( vsnes ) MDRV_CPU_PROGRAM_MAP(vsnes_cpu1_map) /* some carts also trigger IRQs */ MDRV_MACHINE_RESET(vsnes) + MDRV_MACHINE_START(vsnes) /* video hardware */ MDRV_SCREEN_ADD("screen", RASTER) @@ -1806,6 +1807,7 @@ static MACHINE_DRIVER_START( vsdual ) MDRV_CPU_PROGRAM_MAP(vsnes_cpu2_map) /* some carts also trigger IRQs */ MDRV_MACHINE_RESET(vsdual) + MDRV_MACHINE_START(vsdual) /* video hardware */ MDRV_PALETTE_LENGTH(2*8*4*16) diff --git a/src/mame/includes/playch10.h b/src/mame/includes/playch10.h index 56f66b64a43..fde6b271a29 100644 --- a/src/mame/includes/playch10.h +++ b/src/mame/includes/playch10.h @@ -1,6 +1,8 @@ /*----------- defined in machine/playch10.c -----------*/ MACHINE_RESET( pc10 ); +MACHINE_START( pc10 ); +MACHINE_START( playch10_hboard ); DRIVER_INIT( playch10 ); /* standard games */ DRIVER_INIT( pc_gun ); /* gun games */ DRIVER_INIT( pc_hrz ); /* horizontal games */ diff --git a/src/mame/includes/vsnes.h b/src/mame/includes/vsnes.h index f356d18f7b7..38e647348bb 100644 --- a/src/mame/includes/vsnes.h +++ b/src/mame/includes/vsnes.h @@ -15,6 +15,8 @@ extern const ppu2c0x_interface vsnes_ppu_interface_2; MACHINE_RESET( vsnes ); MACHINE_RESET( vsdual ); +MACHINE_START( vsnes ); +MACHINE_START( vsdual ); DRIVER_INIT( suprmrio ); DRIVER_INIT( excitebk ); DRIVER_INIT( excitbkj ); diff --git a/src/mame/machine/playch10.c b/src/mame/machine/playch10.c index cd642fbb5ee..56876a5b4c6 100644 --- a/src/mame/machine/playch10.c +++ b/src/mame/machine/playch10.c @@ -3,6 +3,22 @@ #include "machine/rp5h01.h" #include "includes/playch10.h" +/* prototypes */ +void pc10_set_mirroring( int mirroring ); +WRITE8_HANDLER( pc10_nt_w ); +READ8_HANDLER( pc10_nt_r ); +WRITE8_HANDLER( pc10_chr_w ); +READ8_HANDLER( pc10_chr_r ); +void pc10_set_videorom_bank( running_machine *machine, int first, int count, int bank, int size ); +void set_videoram_bank( running_machine *machine, int first, int count, int bank, int size ); + +typedef struct +{ + int writable; // 1 for RAM, 0 for ROM + UINT8* chr; // direct access to the memory +} chr_bank; + + /* Globals */ int pc10_sdcs; /* ShareD Chip Select */ int pc10_dispmask; /* Display Mask */ @@ -21,14 +37,20 @@ static int mirroring; static int MMC2_bank[4], MMC2_bank_latch[2]; +static UINT8* vrom; // used for games with cart gfx loaded (a,c,e,f,g,h) +static UINT8* vram = NULL; // used for boards h, b, d, i, k (Presumably, 8K. 16K didn't work in MESS) +static UINT8* nametable[4]; // For non-mirroring boards, this can be moved to a direct mapping +static UINT8* nt_ram = NULL; // Per-board size! Some boards clearly need 4K. Some MAY use 2K. Research needed. +static chr_bank chr_page[8]; // Simple wrapper for ROM/RAM, since we could be banking either (Hboard) + /************************************* * * Init machine * *************************************/ + MACHINE_RESET( pc10 ) { - const device_config *ppu = devtag_get_device(machine, "ppu"); const device_config *rp5h01 = devtag_get_device(machine, "rp5h01"); /* initialize latches and flip-flops */ @@ -51,7 +73,39 @@ MACHINE_RESET( pc10 ) rp5h01_reset_w(rp5h01, 0, 1); rp5h01_enable_w(rp5h01, 0, 1); - ppu2c0x_set_mirroring( ppu, mirroring ); + pc10_set_mirroring(mirroring); +} + +MACHINE_START( pc10 ) +{ + vrom = memory_region(machine, "gfx2"); + + /* allocate 4K of nametable ram here */ + /* move to individual boards as documentation of actual boards allows */ + nt_ram = auto_alloc_array(machine, UINT8, 0x1000); + + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0, 0x1fff, 0, 0, pc10_chr_r, pc10_chr_w); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x2000, 0x3eff, 0, 0, pc10_nt_r, pc10_nt_w); + + if (NULL != vram) + set_videoram_bank(machine, 0, 8, 0, 8); + else pc10_set_videorom_bank(machine, 0, 8, 0, 8); + +} + +MACHINE_START( playch10_hboard ) +{ + vrom = memory_region(machine, "gfx2"); + + /* allocate 4K of nametable ram here */ + /* move to individual boards as documentation of actual boards allows */ + nt_ram = auto_alloc_array(machine, UINT8, 0x1000); + /* allocate vram */ + + vram = auto_alloc_array(machine, UINT8, 0x2000); + + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0, 0x1fff, 0, 0, pc10_chr_r, pc10_chr_w); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x2000, 0x3eff, 0, 0, pc10_nt_r, pc10_nt_w); } /************************************* @@ -103,17 +157,17 @@ WRITE8_HANDLER( pc10_DOGDI_w ) WRITE8_HANDLER( pc10_GAMERES_w ) { - cputag_set_input_line(space->machine, "cart", INPUT_LINE_RESET, ( data & 1 ) ? CLEAR_LINE : ASSERT_LINE ); + cputag_set_input_line(space->machine, "cart", INPUT_LINE_RESET, (data & 1) ? CLEAR_LINE : ASSERT_LINE ); } WRITE8_HANDLER( pc10_GAMESTOP_w ) { - cputag_set_input_line(space->machine, "cart", INPUT_LINE_HALT, ( data & 1 ) ? CLEAR_LINE : ASSERT_LINE ); + cputag_set_input_line(space->machine, "cart", INPUT_LINE_HALT, (data & 1) ? CLEAR_LINE : ASSERT_LINE ); } WRITE8_HANDLER( pc10_PPURES_w ) { - if ( data & 1 ) + if (data & 1) devtag_reset(space->machine, "ppu"); } @@ -126,8 +180,8 @@ READ8_HANDLER( pc10_detectclr_r ) WRITE8_HANDLER( pc10_CARTSEL_w ) { - cart_sel &= ~( 1 << offset ); - cart_sel |= ( data & 1 ) << offset; + cart_sel &= ~(1 << offset); + cart_sel |= (data & 1) << offset; } @@ -136,6 +190,7 @@ WRITE8_HANDLER( pc10_CARTSEL_w ) * RP5H01 handling * *************************************/ + READ8_HANDLER( pc10_prot_r ) { const device_config *rp5h01 = devtag_get_device(space->machine, "rp5h01"); @@ -179,10 +234,11 @@ WRITE8_HANDLER( pc10_prot_w ) * Input Ports * *************************************/ + WRITE8_HANDLER( pc10_in0_w ) { /* Toggling bit 0 high then low resets both controllers */ - if ( data & 1 ) + if (data & 1) return; /* load up the latches */ @@ -190,7 +246,7 @@ WRITE8_HANDLER( pc10_in0_w ) input_latch[1] = input_port_read(space->machine, "P2"); /* apply any masking from the BIOS */ - if ( cntrl_mask ) + if (cntrl_mask) { /* mask out select and start */ input_latch[0] &= ~0x0c; @@ -199,7 +255,7 @@ WRITE8_HANDLER( pc10_in0_w ) READ8_HANDLER( pc10_in0_r ) { - int ret = ( input_latch[0] ) & 1; + int ret = (input_latch[0]) & 1; /* shift */ input_latch[0] >>= 1; @@ -213,13 +269,13 @@ READ8_HANDLER( pc10_in0_r ) READ8_HANDLER( pc10_in1_r ) { - int ret = ( input_latch[1] ) & 1; + int ret = (input_latch[1]) & 1; /* shift */ input_latch[1] >>= 1; /* do the gun thing */ - if ( pc10_gun_controller ) + if (pc10_gun_controller) { const device_config *ppu = devtag_get_device(space->machine, "ppu"); int trigger = input_port_read(space->machine, "P1"); @@ -231,22 +287,22 @@ READ8_HANDLER( pc10_in1_r ) ret |= 0x08; /* get the pixel at the gun position */ - pix = ppu2c0x_get_pixel( ppu, x, y ); + pix = ppu2c0x_get_pixel(ppu, x, y); /* get the color base from the ppu */ - color_base = ppu2c0x_get_colorbase( ppu ); + color_base = ppu2c0x_get_colorbase(ppu); /* look at the screen and see if the cursor is over a bright pixel */ - if ( ( pix == color_base+0x20 ) || ( pix == color_base+0x30 ) || - ( pix == color_base+0x33 ) || ( pix == color_base+0x34 ) ) + if ((pix == color_base + 0x20) || (pix == color_base + 0x30) || + (pix == color_base + 0x33) || (pix == color_base + 0x34)) { ret &= ~0x08; /* sprite hit */ } /* now, add the trigger if not masked */ - if ( !cntrl_mask ) + if (!cntrl_mask) { - ret |= ( trigger & 2 ) << 3; + ret |= (trigger & 2) << 3; } } @@ -256,15 +312,135 @@ READ8_HANDLER( pc10_in1_r ) return ret; } +/************************************* + * + * PPU External bus handlers + * + *************************************/ +WRITE8_HANDLER( pc10_nt_w ) +{ + int page = ((offset & 0xc00) >> 10); + nametable[page][offset & 0x3ff] = data; +} + +READ8_HANDLER( pc10_nt_r ) +{ + int page = ((offset & 0xc00) >> 10); + return nametable[page][offset & 0x3ff]; +} + +WRITE8_HANDLER( pc10_chr_w ) +{ + int bank = offset >> 10; + if (chr_page[bank].writable) + { + chr_page[bank].chr[offset & 0x3ff] = data; + } +} + +READ8_HANDLER( pc10_chr_r ) +{ + int bank = offset >> 10; + return chr_page[bank].chr[offset & 0x3ff]; +} + + +void pc10_set_mirroring( int mirroring ) +{ + switch (mirroring) + { + case PPU_MIRROR_LOW: + nametable[0] = nametable[1] = nametable[2] = nametable[3] = nt_ram; + break; + case PPU_MIRROR_HIGH: + nametable[0] = nametable[1] = nametable[2] = nametable[3] = nt_ram + 0x400; + break; + case PPU_MIRROR_HORZ: + nametable[0] = nt_ram; + nametable[1] = nt_ram; + nametable[2] = nt_ram + 0x400; + nametable[3] = nt_ram + 0x400; + break; + case PPU_MIRROR_VERT: + nametable[0] = nt_ram; + nametable[1] = nt_ram + 0x400; + nametable[2] = nt_ram; + nametable[3] = nt_ram + 0x400; + break; + case PPU_MIRROR_NONE: + default: + nametable[0] = nt_ram; + nametable[1] = nt_ram + 0x400; + nametable[2] = nt_ram + 0x800; + nametable[3] = nt_ram + 0xc00; + break; + } +} + +/* SIZE MAPPINGS *\ + * old new * + * 512 8 * + * 256 4 * + * 128 2 * + * 64 1 * +\*****************/ + +void pc10_set_videorom_bank( running_machine *machine, int first, int count, int bank, int size ) +{ + int i, len; + /* first = first bank to map */ + /* count = number of 1K banks to map */ + /* bank = index of the bank */ + /* size = size of indexed banks (in KB) */ + /* note that this follows the original PPU banking and might be overly complex */ + + /* yeah, this is probably a horrible assumption to make.*/ + /* but the driver is 100% consistant */ + + len = memory_region_length(machine, "gfx2"); + len /= 0x400; // convert to KB + len /= size; // convert to bank resolution + len--; // convert to mask + bank &= len; // should be the right mask + + for (i = 0; i < count; i++) + { + chr_page[i + first].writable = 0; + chr_page[i + first].chr=vrom + (i * 0x400) + (bank * size * 0x400); + } +} + +void set_videoram_bank( running_machine *machine, int first, int count, int bank, int size ) +{ + int i; + /* first = first bank to map */ + /* count = number of 1K banks to map */ + /* bank = index of the bank */ + /* size = size of indexed banks (in KB) */ + /* note that this follows the original PPU banking and might be overly complex */ + + /* assumes 8K of vram */ + /* need 8K to fill address space */ + /* only pinbot (8k) banks at all */ + + for (i = 0; i < count; i++) + { + chr_page[i + first].writable = 1; + chr_page[i + first].chr = vram + (((i * 0x400) + (bank * size * 0x400)) & 0x1fff); + } +} /************************************* * * Common init for all games * *************************************/ + DRIVER_INIT( playch10 ) { + vram = NULL; + /* set the controller to default */ pc10_gun_controller = 0; @@ -285,6 +461,9 @@ DRIVER_INIT( pc_gun ) /* common init */ DRIVER_INIT_CALL(playch10); + /* we have no vram, make sure switching games doesn't point to an old allocation */ + vram = NULL; + /* set the control type */ pc10_gun_controller = 1; } @@ -312,10 +491,10 @@ static WRITE8_HANDLER( mmc1_rom_switch_w ) /* basically, a MMC1 mapper from the nes */ static int size16k, switchlow, vrom4k; - int reg = ( offset >> 13 ); + int reg = (offset >> 13); /* reset mapper */ - if ( data & 0x80 ) + if (data & 0x80) { mmc1_shiftreg = mmc1_shiftcount = 0; @@ -327,23 +506,21 @@ static WRITE8_HANDLER( mmc1_rom_switch_w ) } /* see if we need to clock in data */ - if ( mmc1_shiftcount < 5 ) + if (mmc1_shiftcount < 5) { mmc1_shiftreg >>= 1; - mmc1_shiftreg |= ( data & 1 ) << 4; + mmc1_shiftreg |= (data & 1) << 4; mmc1_shiftcount++; } /* are we done shifting? */ - if ( mmc1_shiftcount == 5 ) + if (mmc1_shiftcount == 5) { - const device_config *ppu = devtag_get_device(space->machine, "ppu"); - /* reset count */ mmc1_shiftcount = 0; /* apply data to registers */ - switch( reg ) + switch (reg) { case 0: /* mirroring and options */ { @@ -353,7 +530,7 @@ static WRITE8_HANDLER( mmc1_rom_switch_w ) size16k = mmc1_shiftreg & 0x08; switchlow = mmc1_shiftreg & 0x04; - switch( mmc1_shiftreg & 3 ) + switch (mmc1_shiftreg & 3) { case 0: _mirroring = PPU_MIRROR_LOW; @@ -374,41 +551,41 @@ static WRITE8_HANDLER( mmc1_rom_switch_w ) } /* apply mirroring */ - ppu2c0x_set_mirroring( ppu, _mirroring ); + pc10_set_mirroring(_mirroring); } break; case 1: /* video rom banking - bank 0 - 4k or 8k */ - ppu2c0x_set_videorom_bank( ppu, 0, ( vrom4k ) ? 4 : 8, ( mmc1_shiftreg & 0x1f ), 256 ); + pc10_set_videorom_bank(space->machine, 0, (vrom4k) ? 4 : 8, (mmc1_shiftreg & 0x1f), 4); break; case 2: /* video rom banking - bank 1 - 4k only */ - if ( vrom4k ) - ppu2c0x_set_videorom_bank( ppu, 4, 4, ( mmc1_shiftreg & 0x1f ), 256 ); + if (vrom4k) + pc10_set_videorom_bank(space->machine, 4, 4, (mmc1_shiftreg & 0x1f), 4); break; case 3: /* program banking */ { - int bank = ( mmc1_shiftreg & mmc1_rom_mask ) * 0x4000; - UINT8 *prg = memory_region( space->machine, "cart" ); + int bank = (mmc1_shiftreg & mmc1_rom_mask) * 0x4000; + UINT8 *prg = memory_region(space->machine, "cart"); - if ( !size16k ) + if (!size16k) { /* switch 32k */ - memcpy( &prg[0x08000], &prg[0x010000+bank], 0x8000 ); + memcpy(&prg[0x08000], &prg[0x010000 + bank], 0x8000); } else { /* switch 16k */ - if ( switchlow ) + if (switchlow) { /* low */ - memcpy( &prg[0x08000], &prg[0x010000+bank], 0x4000 ); + memcpy(&prg[0x08000], &prg[0x010000 + bank], 0x4000); } else { /* high */ - memcpy( &prg[0x0c000], &prg[0x010000+bank], 0x4000 ); + memcpy(&prg[0x0c000], &prg[0x010000 + bank], 0x4000); } } } @@ -418,13 +595,11 @@ static WRITE8_HANDLER( mmc1_rom_switch_w ) } /**********************************************************************************/ - /* A Board games (Track & Field, Gradius) */ static WRITE8_HANDLER( aboard_vrom_switch_w ) { - const device_config *ppu = devtag_get_device(space->machine, "ppu"); - ppu2c0x_set_videorom_bank( ppu, 0, 8, ( data & 3 ), 512 ); + pc10_set_videorom_bank(space->machine, 0, 8, (data & 3), 8); } DRIVER_INIT( pcaboard ) @@ -437,27 +612,29 @@ DRIVER_INIT( pcaboard ) /* set the mirroring here */ mirroring = PPU_MIRROR_VERT; + + /* we have no vram, make sure switching games doesn't point to an old allocation */ + vram = NULL; } /**********************************************************************************/ - /* B Board games (Contra, Rush N' Attach, Pro Wrestling) */ static WRITE8_HANDLER( bboard_rom_switch_w ) { - int bankoffset = 0x10000 + ( ( data & 7 ) * 0x4000 ); - UINT8 *prg = memory_region( space->machine, "cart" ); + int bankoffset = 0x10000 + ((data & 7) * 0x4000); + UINT8 *prg = memory_region(space->machine, "cart"); - memcpy( &prg[0x08000], &prg[bankoffset], 0x4000 ); + memcpy(&prg[0x08000], &prg[bankoffset], 0x4000); } DRIVER_INIT( pcbboard ) { - UINT8 *prg = memory_region( machine, "cart" ); + UINT8 *prg = memory_region(machine, "cart"); /* We do manual banking, in case the code falls through */ /* Copy the initial banks */ - memcpy( &prg[0x08000], &prg[0x28000], 0x8000 ); + memcpy(&prg[0x08000], &prg[0x28000], 0x8000); /* Roms are banked at $8000 to $bfff */ memory_install_write8_handler(cputag_get_address_space(machine, "cart", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, bboard_rom_switch_w ); @@ -465,18 +642,21 @@ DRIVER_INIT( pcbboard ) /* common init */ DRIVER_INIT_CALL(playch10); + /* allocate vram */ + vram = auto_alloc_array(machine, UINT8, 0x2000); + /* set the mirroring here */ mirroring = PPU_MIRROR_VERT; + /* special init */ + set_videoram_bank(machine, 0, 8, 0, 8); } /**********************************************************************************/ - /* C Board games (The Goonies) */ static WRITE8_HANDLER( cboard_vrom_switch_w ) { - const device_config *ppu = devtag_get_device(space->machine, "ppu"); - ppu2c0x_set_videorom_bank( ppu, 0, 8, ( ( data >> 1 ) & 1 ), 512 ); + pc10_set_videorom_bank(space->machine, 0, 8, ((data >> 1) & 1), 8); } DRIVER_INIT( pccboard ) @@ -484,29 +664,36 @@ DRIVER_INIT( pccboard ) /* switches vrom with writes to $6000 */ memory_install_write8_handler(cputag_get_address_space(machine, "cart", ADDRESS_SPACE_PROGRAM), 0x6000, 0x6000, 0, 0, cboard_vrom_switch_w ); + /* we have no vram, make sure switching games doesn't point to an old allocation */ + vram = NULL; + /* common init */ DRIVER_INIT_CALL(playch10); } /**********************************************************************************/ - /* D Board games (Rad Racer) */ DRIVER_INIT( pcdboard ) { - UINT8 *prg = memory_region( machine, "cart" ); + UINT8 *prg = memory_region(machine, "cart"); /* We do manual banking, in case the code falls through */ /* Copy the initial banks */ - memcpy( &prg[0x08000], &prg[0x28000], 0x8000 ); + memcpy(&prg[0x08000], &prg[0x28000], 0x8000); mmc1_rom_mask = 0x07; /* MMC mapper at writes to $8000-$ffff */ memory_install_write8_handler(cputag_get_address_space(machine, "cart", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, mmc1_rom_switch_w ); + /* common init */ DRIVER_INIT_CALL(playch10); + /* allocate vram */ + vram = auto_alloc_array(machine, UINT8, 0x2000); + /* special init */ + set_videoram_bank(machine, 0, 8, 0, 8); } /* D Board games with extra ram (Metroid) */ @@ -519,79 +706,81 @@ DRIVER_INIT( pcdboard_2 ) /* common init */ DRIVER_INIT_CALL(pcdboard); + + /* allocate vram */ + vram = auto_alloc_array(machine, UINT8, 0x2000); + /* special init */ + set_videoram_bank(machine, 0, 8, 0, 8); } /**********************************************************************************/ - /* E Board games (Mike Tyson's Punchout) - BROKEN - FIX ME */ /* callback for the ppu_latch */ static void mapper9_latch( const device_config *ppu, offs_t offset ) { - if( (offset & 0x1ff0) == 0x0fd0 && MMC2_bank_latch[0] != 0xfd ) + if((offset & 0x1ff0) == 0x0fd0 && MMC2_bank_latch[0] != 0xfd) { MMC2_bank_latch[0] = 0xfd; - ppu2c0x_set_videorom_bank( ppu, 0, 4, MMC2_bank[0], 256 ); + pc10_set_videorom_bank(ppu->space[0]->machine, 0, 4, MMC2_bank[0], 4); } - else if( (offset & 0x1ff0) == 0x0fe0 && MMC2_bank_latch[0] != 0xfe ) + else if((offset & 0x1ff0) == 0x0fe0 && MMC2_bank_latch[0] != 0xfe) { MMC2_bank_latch[0] = 0xfe; - ppu2c0x_set_videorom_bank( ppu, 0, 4, MMC2_bank[1], 256 ); + pc10_set_videorom_bank(ppu->space[0]->machine, 0, 4, MMC2_bank[1], 4); } - else if( (offset & 0x1ff0) == 0x1fd0 && MMC2_bank_latch[1] != 0xfd ) + else if((offset & 0x1ff0) == 0x1fd0 && MMC2_bank_latch[1] != 0xfd) { MMC2_bank_latch[1] = 0xfd; - ppu2c0x_set_videorom_bank( ppu, 4, 4, MMC2_bank[2], 256 ); + pc10_set_videorom_bank(ppu->space[0]->machine, 4, 4, MMC2_bank[2], 4); } - else if( (offset & 0x1ff0) == 0x1fe0 && MMC2_bank_latch[1] != 0xfe ) + else if((offset & 0x1ff0) == 0x1fe0 && MMC2_bank_latch[1] != 0xfe) { MMC2_bank_latch[1] = 0xfe; - ppu2c0x_set_videorom_bank( ppu, 4, 4, MMC2_bank[3], 256 ); + pc10_set_videorom_bank(ppu->space[0]->machine, 4, 4, MMC2_bank[3], 4); } } static WRITE8_HANDLER( eboard_rom_switch_w ) { - const device_config *ppu = devtag_get_device(space->machine, "ppu"); - /* a variation of mapper 9 on a nes */ - switch( offset & 0x7000 ) + switch (offset & 0x7000) { case 0x2000: /* code bank switching */ { - int bankoffset = 0x10000 + ( data & 0x0f ) * 0x2000; - UINT8 *prg = memory_region( space->machine, "cart" ); - memcpy( &prg[0x08000], &prg[bankoffset], 0x2000 ); + int bankoffset = 0x10000 + (data & 0x0f) * 0x2000; + UINT8 *prg = memory_region(space->machine, "cart"); + memcpy(&prg[0x08000], &prg[bankoffset], 0x2000); } break; case 0x3000: /* gfx bank 0 - 4k */ MMC2_bank[0] = data; - if( MMC2_bank_latch[0] == 0xfd ) - ppu2c0x_set_videorom_bank( ppu, 0, 4, data, 256 ); + if (MMC2_bank_latch[0] == 0xfd) + pc10_set_videorom_bank(space->machine, 0, 4, data, 4); break; case 0x4000: /* gfx bank 0 - 4k */ MMC2_bank[1] = data; - if( MMC2_bank_latch[0] == 0xfe ) - ppu2c0x_set_videorom_bank( ppu, 0, 4, data, 256 ); + if (MMC2_bank_latch[0] == 0xfe) + pc10_set_videorom_bank(space->machine, 0, 4, data, 4); break; case 0x5000: /* gfx bank 1 - 4k */ MMC2_bank[2] = data; - if( MMC2_bank_latch[1] == 0xfd ) - ppu2c0x_set_videorom_bank( ppu, 4, 4, data, 256 ); + if (MMC2_bank_latch[1] == 0xfd) + pc10_set_videorom_bank(space->machine, 4, 4, data, 4); break; case 0x6000: /* gfx bank 1 - 4k */ MMC2_bank[3] = data; - if( MMC2_bank_latch[1] == 0xfe ) - ppu2c0x_set_videorom_bank( ppu, 4, 4, data, 256 ); + if (MMC2_bank_latch[1] == 0xfe) + pc10_set_videorom_bank(space->machine, 4, 4, data, 4); break; case 0x7000: /* mirroring */ - ppu2c0x_set_mirroring( ppu, data ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT ); + pc10_set_mirroring(data ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); break; } @@ -599,11 +788,14 @@ static WRITE8_HANDLER( eboard_rom_switch_w ) DRIVER_INIT( pceboard ) { - UINT8 *prg = memory_region( machine, "cart" ); + UINT8 *prg = memory_region(machine, "cart"); + + /* we have no vram, make sure switching games doesn't point to an old allocation */ + vram = NULL; /* We do manual banking, in case the code falls through */ /* Copy the initial banks */ - memcpy( &prg[0x08000], &prg[0x28000], 0x8000 ); + memcpy(&prg[0x08000], &prg[0x28000], 0x8000); /* basically a mapper 9 on a nes */ memory_install_write8_handler(cputag_get_address_space(machine, "cart", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, eboard_rom_switch_w ); @@ -620,16 +812,18 @@ DRIVER_INIT( pceboard ) } /**********************************************************************************/ - /* F Board games (Ninja Gaiden, Double Dragon) */ DRIVER_INIT( pcfboard ) { - UINT8 *prg = memory_region( machine, "cart" ); + UINT8 *prg = memory_region(machine, "cart"); + + /* we have no vram, make sure switching games doesn't point to an old allocation */ + vram = NULL; /* We do manual banking, in case the code falls through */ /* Copy the initial banks */ - memcpy( &prg[0x08000], &prg[0x28000], 0x8000 ); + memcpy(&prg[0x08000], &prg[0x28000], 0x8000); mmc1_rom_mask = 0x07; @@ -648,12 +842,13 @@ DRIVER_INIT( pcfboard_2 ) memory_install_readwrite8_handler(cputag_get_address_space(machine, "cart", ADDRESS_SPACE_PROGRAM), 0x6000, 0x6fff, 0, 0, (read8_space_func)SMH_BANK(1), (write8_space_func)SMH_BANK(1) ); memory_set_bankptr(machine, 1, auto_alloc_array(machine, UINT8, 0x1000)); + vram = NULL; + /* common init */ DRIVER_INIT_CALL(pcfboard); } /**********************************************************************************/ - /* G Board games (Super Mario Bros. 3) */ static int gboard_scanline_counter; @@ -665,9 +860,9 @@ static int gboard_command; static void gboard_scanline_cb( const device_config *device, int scanline, int vblank, int blanked ) { - if ( !vblank && !blanked ) + if (!vblank && !blanked) { - if ( --gboard_scanline_counter == -1 ) + if (--gboard_scanline_counter == -1) { gboard_scanline_counter = gboard_scanline_latch; generic_pulse_irq_line(cputag_get_cpu(device->machine, "cart"), 0); @@ -681,37 +876,37 @@ static WRITE8_HANDLER( gboard_rom_switch_w ) /* basically, a MMC3 mapper from the nes */ - switch( offset & 0x7001 ) + switch (offset & 0x7001) { case 0x0000: gboard_command = data; - if ( gboard_last_bank != ( data & 0xc0 ) ) + if (gboard_last_bank != (data & 0xc0)) { int bank; - UINT8 *prg = memory_region( space->machine, "cart" ); + UINT8 *prg = memory_region(space->machine, "cart"); /* reset the banks */ - if ( gboard_command & 0x40 ) + if (gboard_command & 0x40) { /* high bank */ bank = gboard_banks[0] * 0x2000 + 0x10000; - memcpy( &prg[0x0c000], &prg[bank], 0x2000 ); - memcpy( &prg[0x08000], &prg[0x4c000], 0x2000 ); + memcpy(&prg[0x0c000], &prg[bank], 0x2000); + memcpy(&prg[0x08000], &prg[0x4c000], 0x2000); } else { /* low bank */ bank = gboard_banks[0] * 0x2000 + 0x10000; - memcpy( &prg[0x08000], &prg[bank], 0x2000 ); - memcpy( &prg[0x0c000], &prg[0x4c000], 0x2000 ); + memcpy(&prg[0x08000], &prg[bank], 0x2000); + memcpy(&prg[0x0c000], &prg[0x4c000], 0x2000); } /* mid bank */ bank = gboard_banks[1] * 0x2000 + 0x10000; - memcpy( &prg[0x0a000], &prg[bank], 0x2000 ); + memcpy(&prg[0x0a000], &prg[bank], 0x2000); gboard_last_bank = data & 0xc0; } @@ -720,16 +915,16 @@ static WRITE8_HANDLER( gboard_rom_switch_w ) case 0x0001: { UINT8 cmd = gboard_command & 0x07; - int page = ( gboard_command & 0x80 ) >> 5; + int page = (gboard_command & 0x80) >> 5; int bank; - switch( cmd ) + switch (cmd) { case 0: /* char banking */ case 1: /* char banking */ data &= 0xfe; - page ^= ( cmd << 1 ); - ppu2c0x_set_videorom_bank( ppu, page, 2, data, 64 ); + page ^= (cmd << 1); + pc10_set_videorom_bank(space->machine, page, 2, data, 1); break; case 2: /* char banking */ @@ -737,29 +932,29 @@ static WRITE8_HANDLER( gboard_rom_switch_w ) case 4: /* char banking */ case 5: /* char banking */ page ^= cmd + 2; - ppu2c0x_set_videorom_bank( ppu, page, 1, data, 64 ); + pc10_set_videorom_bank(space->machine, page, 1, data, 1); break; case 6: /* program banking */ { - UINT8 *prg = memory_region( space->machine, "cart" ); - if ( gboard_command & 0x40 ) + UINT8 *prg = memory_region(space->machine, "cart"); + if (gboard_command & 0x40) { /* high bank */ gboard_banks[0] = data & 0x1f; - bank = ( gboard_banks[0] ) * 0x2000 + 0x10000; + bank = (gboard_banks[0]) * 0x2000 + 0x10000; - memcpy( &prg[0x0c000], &prg[bank], 0x2000 ); - memcpy( &prg[0x08000], &prg[0x4c000], 0x2000 ); + memcpy(&prg[0x0c000], &prg[bank], 0x2000); + memcpy(&prg[0x08000], &prg[0x4c000], 0x2000); } else { /* low bank */ gboard_banks[0] = data & 0x1f; - bank = ( gboard_banks[0] ) * 0x2000 + 0x10000; + bank = (gboard_banks[0]) * 0x2000 + 0x10000; - memcpy( &prg[0x08000], &prg[bank], 0x2000 ); - memcpy( &prg[0x0c000], &prg[0x4c000], 0x2000 ); + memcpy(&prg[0x08000], &prg[bank], 0x2000); + memcpy(&prg[0x0c000], &prg[0x4c000], 0x2000); } } break; @@ -767,11 +962,11 @@ static WRITE8_HANDLER( gboard_rom_switch_w ) case 7: /* program banking */ { /* mid bank */ - UINT8 *prg = memory_region( space->machine, "cart" ); + UINT8 *prg = memory_region(space->machine, "cart"); gboard_banks[1] = data & 0x1f; bank = gboard_banks[1] * 0x2000 + 0x10000; - memcpy( &prg[0x0a000], &prg[bank], 0x2000 ); + memcpy(&prg[0x0a000], &prg[bank], 0x2000); } break; } @@ -779,12 +974,12 @@ static WRITE8_HANDLER( gboard_rom_switch_w ) break; case 0x2000: /* mirroring */ - if( !gboard_4screen ) + if (!gboard_4screen) { - if ( data & 0x40 ) - ppu2c0x_set_mirroring( ppu, PPU_MIRROR_HIGH ); + if (data & 0x40) + pc10_set_mirroring(PPU_MIRROR_HIGH); else - ppu2c0x_set_mirroring( ppu, ( data & 1 ) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT ); + pc10_set_mirroring((data & 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); } break; @@ -801,23 +996,24 @@ static WRITE8_HANDLER( gboard_rom_switch_w ) break; case 0x6000: /* disable irqs */ - ppu2c0x_set_scanline_callback( ppu, 0 ); + ppu2c0x_set_scanline_callback(ppu, 0); break; case 0x6001: /* enable irqs */ - ppu2c0x_set_scanline_callback( ppu, gboard_scanline_cb ); + ppu2c0x_set_scanline_callback(ppu, gboard_scanline_cb); break; } } DRIVER_INIT( pcgboard ) { - UINT8 *prg = memory_region( machine, "cart" ); + UINT8 *prg = memory_region(machine, "cart"); + vram = NULL; /* We do manual banking, in case the code falls through */ /* Copy the initial banks */ - memcpy( &prg[0x08000], &prg[0x4c000], 0x4000 ); - memcpy( &prg[0x0c000], &prg[0x4c000], 0x4000 ); + memcpy(&prg[0x08000], &prg[0x4c000], 0x4000); + memcpy(&prg[0x0c000], &prg[0x4c000], 0x4000); /* MMC3 mapper at writes to $8000-$ffff */ memory_install_write8_handler(cputag_get_address_space(machine, "cart", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, gboard_rom_switch_w ); @@ -838,6 +1034,7 @@ DRIVER_INIT( pcgboard ) DRIVER_INIT( pcgboard_type2 ) { + vram = NULL; /* common init */ DRIVER_INIT_CALL(pcgboard); @@ -846,66 +1043,66 @@ DRIVER_INIT( pcgboard_type2 ) } /**********************************************************************************/ - /* i Board games (Captain Sky Hawk, Solar Jetman) */ static WRITE8_HANDLER( iboard_rom_switch_w ) { int bank = data & 7; - const device_config *ppu = devtag_get_device(space->machine, "ppu"); - UINT8 *prg = memory_region( space->machine, "cart" ); + UINT8 *prg = memory_region(space->machine, "cart"); - if ( data & 0x10 ) - ppu2c0x_set_mirroring( ppu, PPU_MIRROR_HIGH ); + if (data & 0x10) + pc10_set_mirroring(PPU_MIRROR_HIGH); else - ppu2c0x_set_mirroring( ppu, PPU_MIRROR_LOW ); + pc10_set_mirroring(PPU_MIRROR_LOW); - memcpy( &prg[0x08000], &prg[bank * 0x8000 + 0x10000], 0x8000 ); + memcpy(&prg[0x08000], &prg[bank * 0x8000 + 0x10000], 0x8000); } DRIVER_INIT( pciboard ) { - UINT8 *prg = memory_region( machine, "cart" ); + UINT8 *prg = memory_region(machine, "cart"); /* We do manual banking, in case the code falls through */ /* Copy the initial banks */ - memcpy( &prg[0x08000], &prg[0x10000], 0x8000 ); + memcpy(&prg[0x08000], &prg[0x10000], 0x8000); /* Roms are banked at $8000 to $bfff */ memory_install_write8_handler(cputag_get_address_space(machine, "cart", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, iboard_rom_switch_w ); /* common init */ DRIVER_INIT_CALL(playch10); + + /* allocate vram */ + vram = auto_alloc_array(machine, UINT8, 0x2000); + /* special init */ + set_videoram_bank(machine, 0, 8, 0, 8); } /**********************************************************************************/ - /* H Board games (PinBot) */ static WRITE8_HANDLER( hboard_rom_switch_w ) { - const device_config *ppu = devtag_get_device(space->machine, "ppu"); - - switch( offset & 0x7001 ) + switch (offset & 0x7001) { case 0x0001: { UINT8 cmd = gboard_command & 0x07; - int page = ( gboard_command & 0x80 ) >> 5; + int page = (gboard_command & 0x80) >> 5; - switch( cmd ) + switch (cmd) { case 0: /* char banking */ case 1: /* char banking */ data &= 0xfe; - page ^= ( cmd << 1 ); - if ( data & 0x20 ) + page ^= (cmd << 1); + if (data & 0x40) { - ppu2c0x_set_videoram_bank( ppu, page, 2, data, 64 ); + set_videoram_bank(space->machine, page, 2, data, 1); } else { - ppu2c0x_set_videorom_bank( ppu, page, 2, data, 64 ); + pc10_set_videorom_bank(space->machine, page, 2, data, 1); } return; @@ -914,13 +1111,13 @@ static WRITE8_HANDLER( hboard_rom_switch_w ) case 4: /* char banking */ case 5: /* char banking */ page ^= cmd + 2; - if ( data & 0x40 ) + if (data & 0x40) { - ppu2c0x_set_videoram_bank( ppu, page, 1, data, 64 ); + set_videoram_bank(space->machine, page, 1, data, 1); } else { - ppu2c0x_set_videorom_bank( ppu, page, 1, data, 64 ); + pc10_set_videorom_bank(space->machine, page, 1, data, 1); } return; } @@ -932,9 +1129,9 @@ static WRITE8_HANDLER( hboard_rom_switch_w ) DRIVER_INIT( pchboard ) { - UINT8 *prg = memory_region( machine, "cart" ); - memcpy( &prg[0x08000], &prg[0x4c000], 0x4000 ); - memcpy( &prg[0x0c000], &prg[0x4c000], 0x4000 ); + UINT8 *prg = memory_region(machine, "cart"); + memcpy(&prg[0x08000], &prg[0x4c000], 0x4000); + memcpy(&prg[0x0c000], &prg[0x4c000], 0x4000); /* Roms are banked at $8000 to $bfff */ memory_install_write8_handler(cputag_get_address_space(machine, "cart", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, hboard_rom_switch_w ); @@ -955,16 +1152,15 @@ DRIVER_INIT( pchboard ) } /**********************************************************************************/ - /* K Board games (Mario Open Golf) */ DRIVER_INIT( pckboard ) { - UINT8 *prg = memory_region( machine, "cart" ); + UINT8 *prg = memory_region(machine, "cart"); /* We do manual banking, in case the code falls through */ /* Copy the initial banks */ - memcpy( &prg[0x08000], &prg[0x48000], 0x8000 ); + memcpy(&prg[0x08000], &prg[0x48000], 0x8000); mmc1_rom_mask = 0x0f; @@ -977,4 +1173,9 @@ DRIVER_INIT( pckboard ) /* common init */ DRIVER_INIT_CALL(playch10); + + /* allocate vram */ + vram = auto_alloc_array(machine, UINT8, 0x2000); + /* special init */ + set_videoram_bank(machine, 0, 8, 0, 8); } diff --git a/src/mame/machine/vsnes.c b/src/mame/machine/vsnes.c index 36d710634e8..3eb0100e1fb 100644 --- a/src/mame/machine/vsnes.c +++ b/src/mame/machine/vsnes.c @@ -22,6 +22,25 @@ static const UINT8 *remapped_colortable; static int sound_fix=0; static UINT8 last_bank; +/* PPU notes */ +/* nametable is, per Lord Nightmare, always 4K per PPU */ +/* The vsnes system has relatively few banking options for CHR */ +/* Each driver will use ROM or RAM for CHR, never both, and RAM is never banked */ +/* This leads to the memory system being an optimal place to perform banking */ + +/* need double pointers for vsdual */ +static UINT8* vram = NULL; +static UINT8* vrom[2]; +static UINT8* nt_ram[2]; +static UINT8* nt_page[2][4]; // because mirroring is used. + +/* Prototypes for mapping board components to PPU bus */ +WRITE8_HANDLER( vsnes_nt0_w ); +WRITE8_HANDLER( vsnes_nt1_w ); +READ8_HANDLER( vsnes_nt0_r ); +READ8_HANDLER( vsnes_nt1_r ); +void v_set_videorom_bank( running_machine* machine, int start, int count, int bank, int bank_size_in_kb ); + /************************************* * * Color Mapping @@ -92,16 +111,16 @@ static int remap_colors( const device_config *device, int addr, int data ) /* this is the protection. color codes are shuffled around */ /* the ones with value 0xff are unknown */ - if ( addr >= 0x3f00 ) + if (addr >= 0x3f00) { - int newdata = remapped_colortable[ data & 0x3f ]; + int newdata = remapped_colortable[data & 0x3f]; - if ( newdata != 0xff ) + if (newdata != 0xff) data = newdata; #ifdef MAME_DEBUG else - popmessage( "Unmatched color %02x, at address %04x", data & 0x3f, addr ); + popmessage("Unmatched color %02x, at address %04x", data & 0x3f, addr); #endif } @@ -113,10 +132,11 @@ static int remap_colors( const device_config *device, int addr, int data ) * Input Ports * *************************************/ + WRITE8_HANDLER( vsnes_in0_w ) { /* Toggling bit 0 high then low resets both controllers */ - if ( data & 1 ) + if (data & 1) { /* load up the latches */ input_latch[0] = input_port_read(space->machine, "IN0"); @@ -126,13 +146,13 @@ WRITE8_HANDLER( vsnes_in0_w ) static READ8_HANDLER( gun_in0_r ) { - int ret = ( input_latch[0] ) & 1; + int ret = (input_latch[0]) & 1; /* shift */ input_latch[0] >>= 1; ret |= input_port_read(space->machine, "COINS"); /* merge coins, etc */ - ret |= ( input_port_read(space->machine, "DSW0") & 3 ) << 3; /* merge 2 dipswitches */ + ret |= (input_port_read(space->machine, "DSW0") & 3) << 3; /* merge 2 dipswitches */ /* The gun games expect a 1 returned on every 5th read after sound_fix is reset*/ /* Info Supplied by Ben Parnell of FCE Ultra fame */ @@ -148,26 +168,24 @@ static READ8_HANDLER( gun_in0_r ) } - READ8_HANDLER( vsnes_in0_r ) { - int ret = ( input_latch[0] ) & 1; + int ret = (input_latch[0]) & 1; /* shift */ input_latch[0] >>= 1; ret |= input_port_read(space->machine, "COINS"); /* merge coins, etc */ - ret |= ( input_port_read(space->machine, "DSW0") & 3 ) << 3; /* merge 2 dipswitches */ + ret |= (input_port_read(space->machine, "DSW0") & 3) << 3; /* merge 2 dipswitches */ return ret; } - READ8_HANDLER( vsnes_in1_r ) { - int ret = ( input_latch[1] ) & 1; + int ret = (input_latch[1]) & 1; ret |= input_port_read(space->machine, "DSW0") & ~3; /* merge the rest of the dipswitches */ @@ -180,7 +198,7 @@ READ8_HANDLER( vsnes_in1_r ) WRITE8_HANDLER( vsnes_in0_1_w ) { /* Toggling bit 0 high then low resets both controllers */ - if ( data & 1 ) + if (data & 1) { /* load up the latches */ input_latch[2] = input_port_read(space->machine, "IN2"); @@ -190,19 +208,19 @@ WRITE8_HANDLER( vsnes_in0_1_w ) READ8_HANDLER( vsnes_in0_1_r ) { - int ret = ( input_latch[2] ) & 1; + int ret = (input_latch[2]) & 1; /* shift */ input_latch[2] >>= 1; ret |= input_port_read(space->machine, "COINS2"); /* merge coins, etc */ - ret |= ( input_port_read(space->machine, "DSW1") & 3 ) << 3; /* merge 2 dipswitches */ + ret |= (input_port_read(space->machine, "DSW1") & 3) << 3; /* merge 2 dipswitches */ return ret; } READ8_HANDLER( vsnes_in1_1_r ) { - int ret = ( input_latch[3] ) & 1; + int ret = (input_latch[3]) & 1; ret |= input_port_read(space->machine, "DSW1") & ~3; /* merge the rest of the dipswitches */ @@ -229,8 +247,8 @@ MACHINE_RESET( vsnes ) input_latch[2] = input_latch[3] = 0; /* if we need to remap, install the callback */ - if ( remapped_colortable ) - ppu2c0x_set_vidaccess_callback( ppu, remap_colors ); + if (remapped_colortable) + ppu2c0x_set_vidaccess_callback(ppu, remap_colors); } /************************************* @@ -238,6 +256,7 @@ MACHINE_RESET( vsnes ) * Init machine * *************************************/ + MACHINE_RESET( vsdual ) { const device_config *ppu1 = devtag_get_device(machine, "ppu1"); @@ -247,10 +266,165 @@ MACHINE_RESET( vsdual ) input_latch[2] = input_latch[3] = 0; /* if we need to remap, install the callback */ - if ( remapped_colortable ) + if (remapped_colortable) { - ppu2c0x_set_vidaccess_callback( ppu1, remap_colors ); - ppu2c0x_set_vidaccess_callback( ppu2, remap_colors ); + ppu2c0x_set_vidaccess_callback(ppu1, remap_colors); + ppu2c0x_set_vidaccess_callback(ppu2, remap_colors); + } +} + +/************************************* + * + * Machine start functions + * + *************************************/ + +MACHINE_START( vsnes ) +{ + /* establish nametable ram */ + nt_ram[0] = auto_alloc_array(machine, UINT8, 0x1000); + /* set mirroring */ + nt_page[0][0] = nt_ram[0]; + nt_page[0][1] = nt_ram[0] + 0x400; + nt_page[0][2] = nt_ram[0] + 0x800; + nt_page[0][3] = nt_ram[0] + 0xc00; + + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x2000, 0x3eff, 0, 0, vsnes_nt0_r, vsnes_nt0_w); + + vrom[0] = memory_region(machine, "gfx1"); + + /* 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_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x0000, 0x03ff, 0, 0, SMH_BANK(2), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x0400, 0x07ff, 0, 0, SMH_BANK(3), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x0800, 0x0bff, 0, 0, SMH_BANK(4), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x0c00, 0x0fff, 0, 0, SMH_BANK(5), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x1000, 0x13ff, 0, 0, SMH_BANK(6), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x1400, 0x17ff, 0, 0, SMH_BANK(7), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x1800, 0x1bff, 0, 0, SMH_BANK(8), 0); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x1c00, 0x1fff, 0, 0, SMH_BANK(9), 0); + v_set_videorom_bank(machine, 0, 8, 0, 8); + } + else + { + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x0000, 0x1fff, 0, 0, SMH_BANK(2), SMH_BANK(2)); + memory_set_bankptr(machine, 2, vram); + } +} + +/************************************* + * + * Init machine + * + *************************************/ + +MACHINE_START( vsdual ) +{ + vrom[0] = memory_region(machine, "gfx1"); + vrom[1] = memory_region(machine, "gfx2"); + + /* establish nametable ram */ + nt_ram[0] = auto_alloc_array(machine, UINT8, 0x1000); + nt_ram[1] = auto_alloc_array(machine, UINT8, 0x1000); + /* set mirroring */ + nt_page[0][0] = nt_ram[0]; + nt_page[0][1] = nt_ram[0] + 0x400; + nt_page[0][2] = nt_ram[0] + 0x800; + nt_page[0][3] = nt_ram[0] + 0xc00; + nt_page[1][0] = nt_ram[1]; + nt_page[1][1] = nt_ram[1] + 0x400; + nt_page[1][2] = nt_ram[1] + 0x800; + nt_page[1][3] = nt_ram[1] + 0xc00; + + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x2000, 0x3eff, 0, 0, vsnes_nt0_r, vsnes_nt0_w); + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu2"), ADDRESS_SPACE_PROGRAM), 0x2000, 0x3eff, 0, 0, vsnes_nt1_r, vsnes_nt1_w); + // read only! + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu1"), ADDRESS_SPACE_PROGRAM), 0x0000, 0x1fff, 0, 0, SMH_BANK(2), 0); + // read only! + memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu2"), ADDRESS_SPACE_PROGRAM), 0x0000, 0x1fff, 0, 0, SMH_BANK(3), 0); + memory_set_bankptr(machine, 2, vrom[0]); + memory_set_bankptr(machine, 3, vrom[1]); +} + +/************************************* + * + * External mappings for PPU bus + * + *************************************/ + +WRITE8_HANDLER( vsnes_nt0_w ) +{ + int page = ((offset & 0xc00) >> 10); + nt_page[0][page][offset & 0x3ff] = data; + +} + +WRITE8_HANDLER( vsnes_nt1_w ) +{ + int page = ((offset & 0xc00) >> 10); + nt_page[1][page][offset & 0x3ff] = data; + +} + +READ8_HANDLER( vsnes_nt0_r ) +{ + int page = ((offset&0xc00) >> 10); + return nt_page[0][page][offset & 0x3ff]; +} + +READ8_HANDLER( vsnes_nt1_r ) +{ + int page = ((offset & 0xc00) >> 10); + return nt_page[1][page][offset & 0x3ff]; +} + +void v_set_mirroring( int ppu, int mirroring ) +{ + switch (mirroring) + { + case PPU_MIRROR_LOW: + nt_page[ppu][0] = nt_page[ppu][1] = nt_page[ppu][2] = nt_page[ppu][3] = nt_ram[ppu]; + break; + case PPU_MIRROR_HIGH: + nt_page[ppu][0] = nt_page[ppu][1] = nt_page[ppu][2] = nt_page[ppu][3] = nt_ram[ppu] + 0x400; + break; + case PPU_MIRROR_HORZ: + nt_page[ppu][0] = nt_ram[ppu]; + nt_page[ppu][1] = nt_ram[ppu]; + nt_page[ppu][2] = nt_ram[ppu] + 0x400; + nt_page[ppu][3] = nt_ram[ppu] + 0x400; + break; + case PPU_MIRROR_VERT: + nt_page[ppu][0] = nt_ram[ppu]; + nt_page[ppu][1] = nt_ram[ppu] + 0x400; + nt_page[ppu][2] = nt_ram[ppu]; + nt_page[ppu][3] = nt_ram[ppu] + 0x400; + break; + case PPU_MIRROR_NONE: + default: + nt_page[ppu][0] = nt_ram[ppu]; + nt_page[ppu][1] = nt_ram[ppu] + 0x400; + nt_page[ppu][2] = nt_ram[ppu] + 0x800; + nt_page[ppu][3] = nt_ram[ppu] + 0xc00; + break; + } + +} + +void v_set_videorom_bank( running_machine* machine, int start, int count, int bank, int bank_size_in_kb ) +{ + int i, j; + int offset = bank * (bank_size_in_kb * 0x400); + /* automatically add 2 to all start values (because the PPU is bank 2) */ + /* 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) + { + j = i + start + 2; + memory_set_bankptr(machine, j, vrom[0] + offset); } } @@ -259,6 +433,7 @@ MACHINE_RESET( vsdual ) * Common init for all games * *************************************/ + static void init_vsnes(running_machine *machine) { /* set the controller to default */ @@ -276,15 +451,13 @@ static void init_vsnes(running_machine *machine) static WRITE8_HANDLER( vsnormal_vrom_banking ) { - const device_config *ppu1 = devtag_get_device(space->machine, "ppu1"); - /* switch vrom */ - ppu2c0x_set_videorom_bank( ppu1, 0, 8, ( data & 4 ) ? 1 : 0, 512 ); + v_set_videorom_bank(space->machine, 0, 8, (data & 4) ? 1 : 0, 8); /* bit 1 ( data & 2 ) enables writes to extra ram, we ignore it */ /* move along */ - vsnes_in0_w( space, offset, data ); + vsnes_in0_w(space, offset, data); } /* Most games switch VROM Banks in controller 0 write */ @@ -301,17 +474,16 @@ static WRITE8_HANDLER( ppuRC2C05_protection ) /* This PPU has registers mapped at $2000 and $2001 inverted */ /* and no remapped color */ - if ( offset == 0 ) + if (offset == 0) { - ppu2c0x_w( ppu1, 1, data ); + ppu2c0x_w(ppu1, 1, data); return; } - ppu2c0x_w( ppu1, 0, data ); + ppu2c0x_w(ppu1, 0, data); } /**********************************************************************************/ - /* Super Mario Bros. Extra ram at $6000 (NV?) and remapped colors */ DRIVER_INIT( suprmrio ) @@ -333,7 +505,6 @@ DRIVER_INIT( suprmrio ) } /**********************************************************************************/ - /* Gun Games - VROM Banking in controller 0 write */ static WRITE8_HANDLER( gun_in0_w ) @@ -344,32 +515,32 @@ static WRITE8_HANDLER( gun_in0_w ) if (vsnes_do_vrom_bank) { /* switch vrom */ - ppu2c0x_set_videorom_bank( ppu1, 0, 8, ( data & 4 ) ? 1 : 0, 512 ); + v_set_videorom_bank(space->machine, 0, 8, (data & 4) ? 1 : 0, 8); } /* here we do things a little different */ - if ( data & 1 ) + if (data & 1) { /* load up the latches */ input_latch[0] = input_port_read(space->machine, "IN0"); /* do the gun thing */ - if ( vsnes_gun_controller ) + if (vsnes_gun_controller) { int x = input_port_read(space->machine, "GUNX"); int y = input_port_read(space->machine, "GUNY"); UINT32 pix, color_base; /* get the pixel at the gun position */ - pix = ppu2c0x_get_pixel( ppu1, x, y ); + pix = ppu2c0x_get_pixel(ppu1, x, y); /* get the color base from the ppu */ - color_base = ppu2c0x_get_colorbase( ppu1 ); + color_base = ppu2c0x_get_colorbase(ppu1); /* look at the screen and see if the cursor is over a bright pixel */ - if ( ( pix == color_base+0x20 ) || ( pix == color_base+0x30 ) || - ( pix == color_base+0x33 ) || ( pix == color_base+0x34 ) ) + if ((pix == color_base + 0x20 ) || (pix == color_base + 0x30) || + (pix == color_base + 0x33 ) || (pix == color_base + 0x34)) { input_latch[0] |= 0x40; } @@ -378,7 +549,7 @@ static WRITE8_HANDLER( gun_in0_w ) input_latch[1] = input_port_read(space->machine, "IN1"); } - if ( ( zapstore & 1 ) && ( !( data & 1 ) ) ) + if ((zapstore & 1) && (!(data & 1))) /* reset sound_fix to keep sound from hanging */ { sound_fix = 0; @@ -401,32 +572,30 @@ DRIVER_INIT( duckhunt ) } /**********************************************************************************/ - /* The Goonies, VS Gradius: ROMs bankings at $8000-$ffff */ static WRITE8_HANDLER( goonies_rom_banking ) { - const device_config *ppu1 = devtag_get_device(space->machine, "ppu1"); - int reg = ( offset >> 12 ) & 0x07; - int bankoffset = ( data & 7 ) * 0x2000 + 0x10000; + int reg = (offset >> 12) & 0x07; + int bankoffset = (data & 7) * 0x2000 + 0x10000; - switch( reg ) + switch (reg) { case 0: /* code bank 0 */ case 2: /* code bank 1 */ case 4: /* code bank 2 */ { - UINT8 *prg = memory_region( space->machine, "maincpu" ); - memcpy( &prg[0x08000 + reg*0x1000], &prg[bankoffset], 0x2000 ); + UINT8 *prg = memory_region(space->machine, "maincpu"); + memcpy(&prg[0x08000 + reg * 0x1000], &prg[bankoffset], 0x2000); } break; case 6: /* vrom bank 0 */ - ppu2c0x_set_videorom_bank( ppu1, 0, 4, data, 256 ); + v_set_videorom_bank(space->machine, 0, 4, data, 4); break; case 7: /* vrom bank 1 */ - ppu2c0x_set_videorom_bank( ppu1, 4, 4, data, 256 ); + v_set_videorom_bank(space->machine, 4, 4, data, 4); break; } } @@ -435,8 +604,8 @@ DRIVER_INIT( goonies ) { /* We do manual banking, in case the code falls through */ /* Copy the initial banks */ - UINT8 *prg = memory_region( machine, "maincpu" ); - memcpy( &prg[0x08000], &prg[0x18000], 0x8000 ); + UINT8 *prg = memory_region(machine, "maincpu"); + memcpy(&prg[0x08000], &prg[0x18000], 0x8000); /* banking is done with writes to the $8000-$ffff area */ memory_install_write8_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, goonies_rom_banking ); @@ -452,8 +621,8 @@ DRIVER_INIT( vsgradus ) { /* We do manual banking, in case the code falls through */ /* Copy the initial banks */ - UINT8 *prg = memory_region( machine, "maincpu" ); - memcpy( &prg[0x08000], &prg[0x18000], 0x8000 ); + UINT8 *prg = memory_region(machine, "maincpu"); + memcpy(&prg[0x08000], &prg[0x18000], 0x8000); /* banking is done with writes to the $8000-$ffff area */ memory_install_write8_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, goonies_rom_banking ); @@ -496,13 +665,12 @@ DRIVER_INIT( hogalley ) } /***********************************************************************/ - /* Vs. Gumshoe */ static READ8_HANDLER( vsgshoe_security_r ) { /* low part must be 0x1c */ - return ppu2c0x_r( devtag_get_device(space->machine, "ppu1"), 2 ) | 0x1c; + return ppu2c0x_r(devtag_get_device(space->machine, "ppu1"), 2) | 0x1c; } static WRITE8_HANDLER( vsgshoe_gun_in0_w ) @@ -511,10 +679,10 @@ static WRITE8_HANDLER( vsgshoe_gun_in0_w ) int addr; if((data & 0x04) != old_bank) { - UINT8 *prg = memory_region( space->machine, "maincpu" ); + UINT8 *prg = memory_region(space->machine, "maincpu"); old_bank = data & 0x04; addr = old_bank ? 0x12000: 0x10000; - memcpy (&prg[0x08000], &prg[addr], 0x2000); + memcpy(&prg[0x08000], &prg[addr], 0x2000); } gun_in0_w(space, offset, data); @@ -523,7 +691,7 @@ static WRITE8_HANDLER( vsgshoe_gun_in0_w ) DRIVER_INIT( vsgshoe ) { /* set up the default bank */ - UINT8 *prg = memory_region( machine, "maincpu" ); + UINT8 *prg = memory_region(machine, "maincpu"); memcpy (&prg[0x08000], &prg[0x12000], 0x2000); /* Protection */ @@ -541,7 +709,6 @@ DRIVER_INIT( vsgshoe ) } /**********************************************************************************/ - /* Dr Mario: ROMs bankings at $8000-$ffff */ static int drmario_shiftreg; @@ -549,15 +716,13 @@ static int drmario_shiftcount; static WRITE8_HANDLER( drmario_rom_banking ) { - const device_config *ppu1 = devtag_get_device(space->machine, "ppu1"); - /* basically, a MMC1 mapper from the nes */ static int size16k, switchlow, vrom4k; - int reg = ( offset >> 13 ); + int reg = (offset >> 13); /* reset mapper */ - if ( data & 0x80 ) + if (data & 0x80) { drmario_shiftreg = drmario_shiftcount = 0; @@ -570,21 +735,21 @@ static WRITE8_HANDLER( drmario_rom_banking ) } /* see if we need to clock in data */ - if ( drmario_shiftcount < 5 ) + if (drmario_shiftcount < 5) { drmario_shiftreg >>= 1; - drmario_shiftreg |= ( data & 1 ) << 4; + drmario_shiftreg |= (data & 1) << 4; drmario_shiftcount++; } /* are we done shifting? */ - if ( drmario_shiftcount == 5 ) + if (drmario_shiftcount == 5) { /* reset count */ drmario_shiftcount = 0; /* apply data to registers */ - switch( reg ) + switch (reg) { case 0: /* mirroring and options */ { @@ -594,7 +759,7 @@ static WRITE8_HANDLER( drmario_rom_banking ) size16k = drmario_shiftreg & 0x08; switchlow = drmario_shiftreg & 0x04; - switch( drmario_shiftreg & 3 ) + switch (drmario_shiftreg & 3) { case 0: mirroring = PPU_MIRROR_LOW; @@ -615,41 +780,41 @@ static WRITE8_HANDLER( drmario_rom_banking ) } /* apply mirroring */ - ppu2c0x_set_mirroring( ppu1, mirroring ); + v_set_mirroring(1, mirroring); } break; case 1: /* video rom banking - bank 0 - 4k or 8k */ - ppu2c0x_set_videorom_bank( ppu1, 0, ( vrom4k ) ? 4 : 8, drmario_shiftreg, ( vrom4k ) ? 256 : 512 ); + v_set_videorom_bank(space->machine, 0, (vrom4k) ? 4 : 8, drmario_shiftreg, (vrom4k) ? 4 : 8); break; case 2: /* video rom banking - bank 1 - 4k only */ - if ( vrom4k ) - ppu2c0x_set_videorom_bank( ppu1, 4, 4, drmario_shiftreg, 256 ); + if (vrom4k) + v_set_videorom_bank(space->machine, 4, 4, drmario_shiftreg, 4); break; case 3: /* program banking */ { - int bank = ( drmario_shiftreg & 0x03 ) * 0x4000; - UINT8 *prg = memory_region( space->machine, "maincpu" ); + int bank = (drmario_shiftreg & 0x03) * 0x4000; + UINT8 *prg = memory_region(space->machine, "maincpu"); - if ( !size16k ) + if (!size16k) { /* switch 32k */ - memcpy( &prg[0x08000], &prg[0x010000+bank], 0x8000 ); + memcpy(&prg[0x08000], &prg[0x010000 + bank], 0x8000); } else { /* switch 16k */ - if ( switchlow ) + if (switchlow) { /* low */ - memcpy( &prg[0x08000], &prg[0x010000+bank], 0x4000 ); + memcpy(&prg[0x08000], &prg[0x010000 + bank], 0x4000); } else { /* high */ - memcpy( &prg[0x0c000], &prg[0x010000+bank], 0x4000 ); + memcpy(&prg[0x0c000], &prg[0x010000 + bank], 0x4000); } } } @@ -664,9 +829,9 @@ DRIVER_INIT( drmario ) { /* We do manual banking, in case the code falls through */ /* Copy the initial banks */ - UINT8 *prg = memory_region( machine, "maincpu" ); - memcpy( &prg[0x08000], &prg[0x10000], 0x4000 ); - memcpy( &prg[0x0c000], &prg[0x1c000], 0x4000 ); + UINT8 *prg = memory_region(machine, "maincpu"); + memcpy(&prg[0x08000], &prg[0x10000], 0x4000); + memcpy(&prg[0x0c000], &prg[0x1c000], 0x4000); /* MMC1 mapper at writes to $8000-$ffff */ memory_install_write8_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, drmario_rom_banking ); @@ -682,7 +847,6 @@ DRIVER_INIT( drmario ) } /***********************************************************************/ - /* Excite Bike */ DRIVER_INIT( excitebk ) @@ -714,7 +878,6 @@ DRIVER_INIT( excitbkj ) } /**********************************************************************************/ - /* Mach Rider */ DRIVER_INIT( machridr ) @@ -733,7 +896,6 @@ DRIVER_INIT( machridr ) } /**********************************************************************************/ - /* VS Slalom */ DRIVER_INIT( vsslalom ) @@ -748,22 +910,21 @@ DRIVER_INIT( vsslalom ) } /**********************************************************************************/ - /* Castelvania: ROMs bankings at $8000-$ffff */ static WRITE8_HANDLER( castlevania_rom_banking ) { - int rombank = 0x10000 + ( data & 7 ) * 0x4000; - UINT8 *prg = memory_region( space->machine, "maincpu" ); + int rombank = 0x10000 + (data & 7) * 0x4000; + UINT8 *prg = memory_region(space->machine, "maincpu"); - memcpy( &prg[0x08000], &prg[rombank], 0x4000 ); + memcpy(&prg[0x08000], &prg[rombank], 0x4000); } DRIVER_INIT( cstlevna ) { /* when starting the game, the 1st 16k and the last 16k are loaded into the 2 banks */ - UINT8 *prg = memory_region( machine, "maincpu" ); - memcpy( &prg[0x08000], &prg[0x28000], 0x8000 ); + UINT8 *prg = memory_region(machine, "maincpu"); + memcpy(&prg[0x08000], &prg[0x28000], 0x8000); /* banking is done with writes to the $8000-$ffff area */ memory_install_write8_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, castlevania_rom_banking ); @@ -775,23 +936,25 @@ DRIVER_INIT( cstlevna ) /* we need to remap color tables */ /* this *is* the VS games protection, I guess */ remapped_colortable = rp2c04002_colortable; + + /* allocate vram */ + vram = auto_alloc_array(machine, UINT8, 0x2000); } /**********************************************************************************/ - /* VS Top Gun: ROMs bankings at $8000-$ffff, plus some protection */ static READ8_HANDLER( topgun_security_r ) { /* low part must be 0x1b */ - return ppu2c0x_r( devtag_get_device(space->machine, "ppu1"), 2 ) | 0x1b; + return ppu2c0x_r(devtag_get_device(space->machine, "ppu1"), 2) | 0x1b; } DRIVER_INIT( topgun ) { /* when starting the game, the 1st 16k and the last 16k are loaded into the 2 banks */ - UINT8 *prg = memory_region( machine, "maincpu" ); - memcpy( &prg[0x08000], &prg[0x28000], 0x8000 ); + UINT8 *prg = memory_region(machine, "maincpu"); + memcpy(&prg[0x08000], &prg[0x28000], 0x8000); /* banking is done with writes to the $8000-$ffff area */ memory_install_write8_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, castlevania_rom_banking ); @@ -802,6 +965,10 @@ DRIVER_INIT( topgun ) /* common init */ init_vsnes(machine); + + /* allocate vram */ + vram = auto_alloc_array(machine, UINT8, 0x2000); + } /**********************************************************************************/ @@ -813,41 +980,39 @@ static int IRQ_enable, IRQ_count, IRQ_count_latch; static void mapper4_set_prg (const address_space *space) { - UINT8 *prg = memory_region( space->machine, "maincpu" ); + UINT8 *prg = memory_region(space->machine, "maincpu"); MMC3_prg0 &= MMC3_prg_mask; MMC3_prg1 &= MMC3_prg_mask; if (MMC3_cmd & 0x40) { - memcpy( &prg[0x8000], &prg[(MMC3_prg_chunks-1) * 0x4000 + 0x10000], 0x2000 ); - memcpy( &prg[0xc000], &prg[0x2000 * (MMC3_prg0) + 0x10000], 0x2000 ); + memcpy(&prg[0x8000], &prg[(MMC3_prg_chunks - 1) * 0x4000 + 0x10000], 0x2000); + memcpy(&prg[0xc000], &prg[0x2000 * (MMC3_prg0) + 0x10000], 0x2000); } else { - memcpy( &prg[0x8000], &prg[0x2000 * (MMC3_prg0) + 0x10000], 0x2000 ); - memcpy( &prg[0xc000], &prg[(MMC3_prg_chunks-1) * 0x4000 + 0x10000], 0x2000 ); + memcpy(&prg[0x8000], &prg[0x2000 * (MMC3_prg0) + 0x10000], 0x2000); + memcpy(&prg[0xc000], &prg[(MMC3_prg_chunks - 1) * 0x4000 + 0x10000], 0x2000); } - memcpy( &prg[0xa000], &prg[0x2000 * (MMC3_prg1) + 0x10000], 0x2000 ); + memcpy(&prg[0xa000], &prg[0x2000 * (MMC3_prg1) + 0x10000], 0x2000); } static void mapper4_set_chr (const address_space *space) { - const device_config *ppu1 = devtag_get_device(space->machine, "ppu1"); UINT8 chr_page = (MMC3_cmd & 0x80) >> 5; - ppu2c0x_set_videorom_bank(ppu1, chr_page ^ 0, 2, MMC3_chr[0], 1); - ppu2c0x_set_videorom_bank(ppu1, chr_page ^ 2, 2, MMC3_chr[1], 1); - ppu2c0x_set_videorom_bank(ppu1, chr_page ^ 4, 1, MMC3_chr[2], 1); - ppu2c0x_set_videorom_bank(ppu1, chr_page ^ 5, 1, MMC3_chr[3], 1); - ppu2c0x_set_videorom_bank(ppu1, chr_page ^ 6, 1, MMC3_chr[4], 1); - ppu2c0x_set_videorom_bank(ppu1, chr_page ^ 7, 1, MMC3_chr[5], 1); + v_set_videorom_bank(space->machine, chr_page ^ 0, 2, MMC3_chr[0], 1); + v_set_videorom_bank(space->machine, chr_page ^ 2, 2, MMC3_chr[1], 1); + v_set_videorom_bank(space->machine, chr_page ^ 4, 1, MMC3_chr[2], 1); + v_set_videorom_bank(space->machine, chr_page ^ 5, 1, MMC3_chr[3], 1); + v_set_videorom_bank(space->machine, chr_page ^ 6, 1, MMC3_chr[4], 1); + v_set_videorom_bank(space->machine, chr_page ^ 7, 1, MMC3_chr[5], 1); } #define BOTTOM_VISIBLE_SCANLINE 239 /* The bottommost visible scanline */ #define NUM_SCANLINE 262 -static void mapper4_irq ( const device_config *device, int scanline, int vblank, int blanked ) +static void mapper4_irq( const device_config *device, int scanline, int vblank, int blanked ) { - mame_printf_debug("entra\n"); if ((scanline < BOTTOM_VISIBLE_SCANLINE) || (scanline == NUM_SCANLINE - 1)) { if ((IRQ_enable) && !blanked) @@ -875,8 +1040,8 @@ static WRITE8_HANDLER( mapper4_w ) if (last_bank != (data & 0xc0)) { /* Reset the banks */ - mapper4_set_prg (space); - mapper4_set_chr (space); + mapper4_set_prg(space); + mapper4_set_chr(space); } last_bank = data & 0xc0; @@ -889,38 +1054,38 @@ static WRITE8_HANDLER( mapper4_w ) { case 0: case 1: data &= 0xfe; - MMC3_chr[cmd] = data * 64; - mapper4_set_chr (space); + MMC3_chr[cmd] = data; + mapper4_set_chr(space); break; case 2: case 3: case 4: case 5: - MMC3_chr[cmd] = data * 64; - mapper4_set_chr (space); + MMC3_chr[cmd] = data; + mapper4_set_chr(space); break; case 6: MMC3_prg0 = data; - mapper4_set_prg (space); + mapper4_set_prg(space); break; case 7: MMC3_prg1 = data; - mapper4_set_prg (space); + mapper4_set_prg(space); break; } break; } case 0x2000: /* $a000 */ if (data & 0x40) - ppu2c0x_set_mirroring(ppu1, PPU_MIRROR_HIGH); + v_set_mirroring(1, PPU_MIRROR_HIGH); else { if (data & 0x01) - ppu2c0x_set_mirroring(ppu1, PPU_MIRROR_HORZ); + v_set_mirroring(1, PPU_MIRROR_HORZ); else - ppu2c0x_set_mirroring(ppu1, PPU_MIRROR_VERT); + v_set_mirroring(1, PPU_MIRROR_VERT); } break; @@ -963,7 +1128,7 @@ static WRITE8_HANDLER( mapper4_w ) DRIVER_INIT( MMC3 ) { - UINT8 *prg = memory_region( machine, "maincpu" ); + UINT8 *prg = memory_region(machine, "maincpu"); IRQ_enable = IRQ_count = IRQ_count_latch = 0; MMC3_prg0 = 0xfe; MMC3_prg1 = 0xff; @@ -973,10 +1138,10 @@ DRIVER_INIT( MMC3 ) MMC3_prg_mask = ((MMC3_prg_chunks << 1) - 1); - memcpy( &prg[0x8000], &prg[(MMC3_prg_chunks-1) * 0x4000 + 0x10000], 0x2000 ); - memcpy( &prg[0xa000], &prg[(MMC3_prg_chunks-1) * 0x4000 + 0x12000], 0x2000 ); - memcpy( &prg[0xc000], &prg[(MMC3_prg_chunks-1) * 0x4000 + 0x10000], 0x2000 ); - memcpy( &prg[0xe000], &prg[(MMC3_prg_chunks-1) * 0x4000 + 0x12000], 0x2000 ); + memcpy(&prg[0x8000], &prg[(MMC3_prg_chunks - 1) * 0x4000 + 0x10000], 0x2000); + memcpy(&prg[0xa000], &prg[(MMC3_prg_chunks - 1) * 0x4000 + 0x12000], 0x2000); + memcpy(&prg[0xc000], &prg[(MMC3_prg_chunks - 1) * 0x4000 + 0x10000], 0x2000); + memcpy(&prg[0xe000], &prg[(MMC3_prg_chunks - 1) * 0x4000 + 0x12000], 0x2000); /* MMC3 mapper at writes to $8000-$ffff */ memory_install_write8_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, mapper4_w ); @@ -991,7 +1156,7 @@ DRIVER_INIT( MMC3 ) /* Vs. RBI Baseball */ -static READ8_HANDLER( rbi_hack_r) +static READ8_HANDLER( rbi_hack_r ) { /* Supplied by Ben Parnell of FCE Ultra fame */ @@ -1040,7 +1205,7 @@ static READ8_HANDLER( supxevs_read_prot_1_r ) static READ8_HANDLER( supxevs_read_prot_2_r ) { - if( supxevs_prot_index ) + if (supxevs_prot_index) return 0; else return 0x01; @@ -1048,7 +1213,7 @@ static READ8_HANDLER( supxevs_read_prot_2_r ) static READ8_HANDLER( supxevs_read_prot_3_r ) { - if( supxevs_prot_index ) + if (supxevs_prot_index) return 0xd1; else return 0x89; @@ -1056,7 +1221,7 @@ static READ8_HANDLER( supxevs_read_prot_3_r ) static READ8_HANDLER( supxevs_read_prot_4_r ) { - if( supxevs_prot_index ) + if (supxevs_prot_index) { supxevs_prot_index = 0; return 0x3e; @@ -1094,7 +1259,7 @@ static READ8_HANDLER( tko_security_r ) 0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00 }; - if ( offset == 0 ) + if (offset == 0) { security_counter = 0; return 0; @@ -1136,31 +1301,29 @@ DRIVER_INIT( vsfdf ) static WRITE8_HANDLER( mapper68_rom_banking ) { - const device_config *ppu1 = devtag_get_device(space->machine, "ppu1"); - switch (offset & 0x7000) { case 0x0000: - ppu2c0x_set_videorom_bank(ppu1,0,2,data,128); + v_set_videorom_bank(space->machine, 0, 2, data, 2); break; case 0x1000: - ppu2c0x_set_videorom_bank(ppu1,2,2,data,128); + v_set_videorom_bank(space->machine, 2, 2, data, 2); break; case 0x2000: - ppu2c0x_set_videorom_bank(ppu1,4,2,data,128); + v_set_videorom_bank(space->machine, 4, 2, data, 2); break; case 0x3000: /* ok? */ - ppu2c0x_set_videorom_bank(ppu1,6,2,data,128); + v_set_videorom_bank(space->machine, 6, 2, data, 2); break; case 0x7000: { - UINT8 *prg = memory_region( space->machine, "maincpu" ); - memcpy( &prg[0x08000], &prg[0x10000 +data*0x4000], 0x4000 ); + UINT8 *prg = memory_region(space->machine, "maincpu"); + memcpy(&prg[0x08000], &prg[0x10000 + data * 0x4000], 0x4000); } break; @@ -1174,9 +1337,9 @@ DRIVER_INIT( platoon ) /* when starting a mapper 68 game the first 16K ROM bank in the cart is loaded into $8000 the LAST 16K ROM bank is loaded into $C000. The last 16K of ROM cannot be swapped. */ - UINT8 *prg = memory_region( machine, "maincpu" ); - memcpy( &prg[0x08000], &prg[0x10000], 0x4000 ); - memcpy( &prg[0x0c000], &prg[0x2c000], 0x4000 ); + UINT8 *prg = memory_region(machine, "maincpu"); + memcpy(&prg[0x08000], &prg[0x10000], 0x4000); + memcpy(&prg[0x0c000], &prg[0x2c000], 0x4000); memory_install_write8_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, mapper68_rom_banking ); @@ -1190,15 +1353,15 @@ DRIVER_INIT( platoon ) /* Vs. Raid on Bungeling Bay (Japan) */ static int ret; -static WRITE8_HANDLER ( set_bnglngby_irq_w ) +static WRITE8_HANDLER( set_bnglngby_irq_w ) { ret = data; - cputag_set_input_line(space->machine, "maincpu", 0, ( data & 2 ) ? ASSERT_LINE : CLEAR_LINE ); + cputag_set_input_line(space->machine, "maincpu", 0, (data & 2) ? ASSERT_LINE : CLEAR_LINE); /* other values ??? */ /* 0, 4, 84 */ } -static READ8_HANDLER ( set_bnglngby_irq_r ) +static READ8_HANDLER( set_bnglngby_irq_r ) { return ret; } @@ -1228,14 +1391,14 @@ DRIVER_INIT( bnglngby ) static READ8_HANDLER( jajamaru_security_r ) { /* low part must be 0x40 */ - return ppu2c0x_r( devtag_get_device(space->machine, "ppu1"), 2 ) | 0x40; + return ppu2c0x_r(devtag_get_device(space->machine, "ppu1"), 2) | 0x40; } DRIVER_INIT( jajamaru ) { - //It executes an illegal opcode: 0x04 at 0x9e67 and 0x9e1c - //At 0x9e5d and 0x9e12 there is a conditional jump to it - //Maybe it should be a DOP (double NOP) + // It executes an illegal opcode: 0x04 at 0x9e67 and 0x9e1c + // At 0x9e5d and 0x9e12 there is a conditional jump to it + // Maybe it should be a DOP (double NOP) /* Protection */ memory_install_read8_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x2002, 0x2002, 0, 0, jajamaru_security_r ); @@ -1249,13 +1412,12 @@ DRIVER_INIT( jajamaru ) } /***********************************************************************/ - /* Vs. Mighty Bomb Jack */ static READ8_HANDLER( mightybj_security_r ) { /* low part must be 0x3d */ - return ppu2c0x_r( devtag_get_device(space->machine, "ppu1"), 2 ) | 0x3d; + return ppu2c0x_r(devtag_get_device(space->machine, "ppu1"), 2) | 0x3d; } DRIVER_INIT( mightybj ) @@ -1274,25 +1436,23 @@ DRIVER_INIT( mightybj ) static WRITE8_HANDLER( vstennis_vrom_banking ) { const device_config *other_cpu = (space->cpu == cputag_get_cpu(space->machine, "maincpu")) ? cputag_get_cpu(space->machine, "sub") : cputag_get_cpu(space->machine, "maincpu"); - const device_config *ppu1 = devtag_get_device(space->machine, "ppu1"); - const device_config *ppu2 = devtag_get_device(space->machine, "ppu2"); /* switch vrom */ - ppu2c0x_set_videorom_bank( (space->cpu == cputag_get_cpu(space->machine, "maincpu")) ? ppu1 : ppu2, 0, 8, ( data & 4 ) ? 1 : 0, 512 ); + (space->cpu == cputag_get_cpu(space->machine, "maincpu")) ? memory_set_bankptr(space->machine, 2, (data & 4) ? vrom[0] + 0x2000 : vrom[0]) : memory_set_bankptr(space->machine, 3, (data & 4) ? vrom[1] + 0x2000 : vrom[1]); /* bit 1 ( data & 2 ) triggers irq on the other cpu */ - cpu_set_input_line(other_cpu, 0, ( data & 2 ) ? CLEAR_LINE : ASSERT_LINE ); + cpu_set_input_line(other_cpu, 0, (data & 2) ? CLEAR_LINE : ASSERT_LINE); /* move along */ if (space->cpu == cputag_get_cpu(space->machine, "maincpu")) - vsnes_in0_w( space, offset, data ); + vsnes_in0_w(space, offset, data); else - vsnes_in0_1_w( space, offset, data ); + vsnes_in0_1_w(space, offset, data); } DRIVER_INIT( vstennis ) { - UINT8 *prg = memory_region( machine, "maincpu" ); + UINT8 *prg = memory_region(machine, "maincpu"); /* vrom switching is enabled with bit 2 of $4016 */ memory_install_write8_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x4016, 0x4016, 0, 0, vstennis_vrom_banking ); @@ -1311,7 +1471,6 @@ DRIVER_INIT( vstennis ) DRIVER_INIT( wrecking ) { /* only differance between this and vstennis is the colors */ - DRIVER_INIT_CALL(vstennis); remapped_colortable = rp2c04002_colortable; } @@ -1322,7 +1481,6 @@ DRIVER_INIT( wrecking ) DRIVER_INIT( balonfgt ) { /* only differance between this and vstennis is the colors */ - DRIVER_INIT_CALL(vstennis); remapped_colortable = rp2c04003_colortable; @@ -1335,11 +1493,9 @@ DRIVER_INIT( balonfgt ) DRIVER_INIT( vsbball ) { /* only differance between this and vstennis is the colors */ - DRIVER_INIT_CALL(vstennis); remapped_colortable = rp2c04001_colortable; - } @@ -1349,15 +1505,14 @@ DRIVER_INIT( vsbball ) DRIVER_INIT( iceclmrj ) { /* only differance between this and vstennis is the colors */ - DRIVER_INIT_CALL(vstennis); remapped_colortable = rp2c05004_colortable; - } /**********************************************************************/ /* Battle City */ + DRIVER_INIT( btlecity ) { init_vsnes(machine); @@ -1367,6 +1522,7 @@ DRIVER_INIT( btlecity ) /***********************************************************************/ /* Tetris */ + DRIVER_INIT( vstetris ) { /* extra ram at $6000 is enabled with bit 1 of $4016 */ diff --git a/src/mame/video/ppu2c0x.c b/src/mame/video/ppu2c0x.c index b3c90070675..d0f075c5918 100644 --- a/src/mame/video/ppu2c0x.c +++ b/src/mame/video/ppu2c0x.c @@ -5,22 +5,20 @@ Written by Ernesto Corvi. This code is heavily based on Brad Oliver's MESS implementation. -******************************************************************************/ + 2009-04: Changed NES PPU to be a device (Nathan Woods) + 2009-07: Changed NES PPU to use a device memory map (Robert Bohms) -/****************************************************************************** + Current known bugs -Current known bugs + General: -General: + * PPU timing is imprecise for updates that happen mid-scanline. Some games + may demand more precision. -* PPU timing is imprecise for updates that happen mid-scanline. Some games - may demand more precision. + NES-specific: -NES-specific: - -* Micro Machines has minor rendering glitches (needs better timing). - -* Mach Rider has minor road rendering glitches (needs better timing). + * Micro Machines has minor rendering glitches (needs better timing). + * Mach Rider has minor road rendering glitches (needs better timing). ******************************************************************************/ @@ -36,7 +34,7 @@ NES-specific: /* constant definitions */ #define VISIBLE_SCREEN_WIDTH (32*8) /* Visible screen width */ #define VISIBLE_SCREEN_HEIGHT (30*8) /* Visible screen height */ -#define VIDEOMEM_SIZE 0x4000 /* videomem size */ +#define VIDEOMEM_SIZE 0x1000 /* videomem size */ #define VIDEOMEM_PAGE_SIZE 0x400 /* videomem page size */ #define SPRITERAM_SIZE 0x100 /* spriteram size */ #define SPRITERAM_MASK (0x100-1) /* spriteram size */ @@ -113,6 +111,7 @@ typedef struct int back_color; /* background color */ UINT8 *ppu_page[4]; /* ppu pages */ int nes_vram[8]; /* keep track of 8 .5k vram pages to speed things up */ + UINT8 palette_ram[0x20]; /* shouldn't be in main memory! */ int scan_scale; /* scan scale */ int scanlines_per_frame; /* number of scanlines per frame */ int mirror_state; @@ -120,12 +119,11 @@ typedef struct } ppu2c0x_chip; - /*************************************************************************** PROTOTYPES ***************************************************************************/ -static void update_scanline(const device_config *device); +static void update_scanline( const device_config *device ); static TIMER_CALLBACK( scanline_callback ); static TIMER_CALLBACK( hblank_callback ); @@ -133,12 +131,22 @@ static TIMER_CALLBACK( nmi_callback ); void (*ppu_latch)( const device_config *device, offs_t offset ); +/* palette handlers */ +WRITE8_HANDLER( ppu2c0x_palette_write ); +READ8_HANDLER( ppu2c0x_palette_read ); +/* name and attribute table functions */ +WRITE8_HANDLER( ppu2c0x_name_write ); +READ8_HANDLER( ppu2c0x_name_read ); +/* name and attribute table functions */ +WRITE8_HANDLER( ppu2c0x_chr_write ); +READ8_HANDLER( ppu2c0x_chr_read ); + /*************************************************************************** INLINE FUNCTIONS ***************************************************************************/ -INLINE ppu2c0x_chip *get_token(const device_config *device) +INLINE ppu2c0x_chip *get_token( const device_config *device ) { assert(device != NULL); assert((device->type == PPU_2C02) || (device->type == PPU_2C03B) @@ -148,7 +156,7 @@ INLINE ppu2c0x_chip *get_token(const device_config *device) } -INLINE const ppu2c0x_interface *get_interface(const device_config *device) +INLINE const ppu2c0x_interface *get_interface( const device_config *device ) { assert(device != NULL); assert((device->type == PPU_2C02) || (device->type == PPU_2C03B) @@ -167,7 +175,14 @@ INLINE const ppu2c0x_interface *get_interface(const device_config *device) * PPU Palette Initialization * *************************************/ -void ppu2c0x_init_palette(running_machine *machine, int first_entry ) + +/* default address map */ +// make this INTERNAL, default should just be enough to avoid compile errors, print error messages! +static ADDRESS_MAP_START( ppu2c0x, 0, 8 ) + AM_RANGE(0x3f00, 0x3fff) AM_READWRITE (ppu2c0x_palette_read, ppu2c0x_palette_write) +ADDRESS_MAP_END + +void ppu2c0x_init_palette( running_machine *machine, int first_entry ) { /* This routine builds a palette using a transformation from */ @@ -251,30 +266,30 @@ void ppu2c0x_init_palette(running_machine *machine, int first_entry ) break; } - u = sat * cos( rad ); - v = sat * sin( rad ); + u = sat * cos(rad); + v = sat * sin(rad); /* Transform to RGB */ - R = ( y + Kv * v ) * 255.0; - G = ( y - ( Kb * Ku * u + Kr * Kv * v) / (1 - Kb - Kr) ) * 255.0; - B = ( y + Ku * u ) * 255.0; + R = (y + Kv * v) * 255.0; + G = (y - (Kb * Ku * u + Kr * Kv * v) / (1 - Kb - Kr)) * 255.0; + B = (y + Ku * u) * 255.0; /* Clipping, in case of saturation */ - if ( R < 0 ) + if (R < 0) R = 0; - if ( R > 255 ) + if (R > 255) R = 255; - if ( G < 0 ) + if (G < 0) G = 0; - if ( G > 255 ) + if (G > 255) G = 255; - if ( B < 0 ) + if (B < 0) B = 0; - if ( B > 255 ) + if (B > 255) B = 255; /* Round, and set the value */ - palette_set_color_rgb(machine, first_entry++, floor(R+.5), floor(G+.5), floor(B+.5)); + palette_set_color_rgb(machine, first_entry++, floor(R + .5), floor(G + .5), floor(B + .5)); } } } @@ -285,7 +300,7 @@ void ppu2c0x_init_palette(running_machine *machine, int first_entry ) /* the charlayout we use for the chargen */ static const gfx_layout ppu_charlayout = { - 8,8, /* 8*8 characters */ + 8, 8, /* 8*8 characters */ 0, 2, /* 2 bits per pixel */ { 8*8, 0 }, /* the two bitplanes are separated */ @@ -302,9 +317,8 @@ static const gfx_layout ppu_charlayout = static DEVICE_START( ppu2c0x ) { - UINT32 total; ppu2c0x_chip *chip = get_token(device); - const ppu2c0x_interface *intf = get_interface(device); + // const ppu2c0x_interface *intf = get_interface(device); memset(chip, 0, sizeof(*chip)); chip->scanlines_per_frame = (int) device_get_info_int(device, PPU2C0XINFO_INT_SCANLINES_PER_FRAME); @@ -318,58 +332,9 @@ static DEVICE_START( ppu2c0x ) /* allocate a screen bitmap, videomem and spriteram, a dirtychar array and the monochromatic colortable */ chip->bitmap = auto_bitmap_alloc(device->machine, VISIBLE_SCREEN_WIDTH, VISIBLE_SCREEN_HEIGHT, video_screen_get_format(device->machine->primary_screen)); - chip->videomem = auto_alloc_array_clear(device->machine, UINT8, VIDEOMEM_SIZE ); - chip->videoram = auto_alloc_array_clear(device->machine, UINT8, VIDEOMEM_SIZE ); - chip->spriteram = auto_alloc_array_clear(device->machine, UINT8, SPRITERAM_SIZE ); - chip->colortable = auto_alloc_array(device->machine, pen_t, ARRAY_LENGTH( default_colortable ) ); - chip->colortable_mono = auto_alloc_array(device->machine, pen_t, ARRAY_LENGTH( default_colortable_mono ) ); - - memset( chip->videoram_banks_indices, 0xff, sizeof(chip->videoram_banks_indices) ); - - if ( intf->vram_enabled ) - { - chip->has_videoram = 1; - } - - /* initialize the video ROM portion, if available */ - if ( ( intf->vrom_region != NULL ) && ( memory_region( device->machine, intf->vrom_region ) != 0 ) ) - { - /* mark that we have a videorom */ - chip->has_videorom = 1; - - /* find out how many banks */ - chip->videorom_banks = memory_region_length( device->machine, intf->vrom_region ) / 0x2000; - - /* tweak the layout accordingly */ - if ( chip->has_videoram ) - { - total = CHARGEN_NUM_CHARS; - } - else - { - total = chip->videorom_banks * CHARGEN_NUM_CHARS; - } - } - else - { - chip->has_videorom = chip->videorom_banks = 0; - - /* we need to reset this in case of mame running multisession */ - total = CHARGEN_NUM_CHARS; - } - - /* now create the gfx region */ - { - gfx_layout gl; - UINT8 *src = (chip->has_videorom && !chip->has_videoram) ? memory_region( device->machine, intf->vrom_region ) : chip->videomem; - - memcpy(&gl, &ppu_charlayout, sizeof(gl)); - gl.total = total; - device->machine->gfx[intf->gfx_layout_number] = gfx_element_alloc( device->machine, &gl, src, 8, 0 ); - } - - /* setup our videomem handlers based on mirroring */ - ppu2c0x_set_mirroring( device, intf->mirroring ); + chip->spriteram = auto_alloc_array_clear(device->machine, UINT8, SPRITERAM_SIZE); + chip->colortable = auto_alloc_array(device->machine, pen_t, ARRAY_LENGTH(default_colortable)); + chip->colortable_mono = auto_alloc_array(device->machine, pen_t, ARRAY_LENGTH(default_colortable_mono)); } static TIMER_CALLBACK( hblank_callback ) @@ -378,10 +343,10 @@ static TIMER_CALLBACK( hblank_callback ) ppu2c0x_chip *this_ppu = get_token(device); int *ppu_regs = &this_ppu->regs[0]; - int blanked = ( ppu_regs[PPU_CONTROL1] & ( PPU_CONTROL1_BACKGROUND | PPU_CONTROL1_SPRITES ) ) == 0; - int vblank = ((this_ppu->scanline >= PPU_VBLANK_FIRST_SCANLINE-1) && (this_ppu->scanline < this_ppu->scanlines_per_frame-1)) ? 1 : 0; + int blanked = (ppu_regs[PPU_CONTROL1] & (PPU_CONTROL1_BACKGROUND | PPU_CONTROL1_SPRITES)) == 0; + int vblank = ((this_ppu->scanline >= PPU_VBLANK_FIRST_SCANLINE - 1) && (this_ppu->scanline < this_ppu->scanlines_per_frame - 1)) ? 1 : 0; -// update_scanline (device); +// update_scanline(device); if (this_ppu->hblank_callback_proc) (*this_ppu->hblank_callback_proc) (device, this_ppu->scanline, vblank, blanked); @@ -403,7 +368,7 @@ static TIMER_CALLBACK( nmi_callback ) timer_adjust_oneshot(this_ppu->nmi_timer, attotime_never, 0); } -static void draw_background(const device_config *device, UINT8 *line_priority ) +static void draw_background( const device_config *device, UINT8 *line_priority ) { const ppu2c0x_interface *intf = get_interface(device); ppu2c0x_chip *this_ppu = get_token(device); @@ -413,27 +378,24 @@ static void draw_background(const device_config *device, UINT8 *line_priority ) const int *ppu_regs = &this_ppu->regs[0]; const int scanline = this_ppu->scanline; const int refresh_data = this_ppu->refresh_data; - const int gfx_bank = intf->gfx_layout_number; - const int total_elements = device->machine->gfx[gfx_bank]->total_elements; const int *nes_vram = &this_ppu->nes_vram[0]; const int tile_page = this_ppu->tile_page; - const int line_modulo = device->machine->gfx[gfx_bank]->line_modulo; - UINT8 **ppu_page = this_ppu->ppu_page; - int start_x = ( this_ppu->x_fine ^ 0x07 ) - 7; + + int start_x = (this_ppu->x_fine ^ 0x07) - 7; UINT16 back_pen; UINT16 *dest; UINT8 scroll_x_coarse, scroll_y_coarse, scroll_y_fine, color_mask; - int x, tile_index, start, i; + int x, tile_index, i; const pen_t *color_table; const pen_t *paldata; - const UINT8 *sd; + // const UINT8 *sd; - int tilecount=0; + int tilecount = 0; /* setup the color mask and colortable to use */ - if ( ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO ) + if (ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO) { color_mask = 0xf0; color_table = this_ppu->colortable_mono; @@ -445,24 +407,24 @@ static void draw_background(const device_config *device, UINT8 *line_priority ) } /* cache the background pen */ - back_pen = (this_ppu->back_color & color_mask)+intf->color_base; + back_pen = (this_ppu->back_color & color_mask) + intf->color_base; /* determine where in the nametable to start drawing from */ /* based on the current scanline and scroll regs */ scroll_x_coarse = refresh_data & 0x1f; - scroll_y_coarse = ( refresh_data & 0x3e0 ) >> 5; - scroll_y_fine = ( refresh_data & 0x7000 ) >> 12; + scroll_y_coarse = (refresh_data & 0x3e0) >> 5; + scroll_y_fine = (refresh_data & 0x7000) >> 12; x = scroll_x_coarse; /* get the tile index */ - tile_index = ( ( refresh_data & 0xc00 ) | 0x2000 ) + scroll_y_coarse * 32; + tile_index = ((refresh_data & 0xc00) | 0x2000) + scroll_y_coarse * 32; /* set up dest */ dest = ((UINT16 *) bitmap->base) + (bitmap->rowpixels * scanline) + start_x; /* draw the 32 or 33 tiles that make up a line */ - while ( tilecount <34) + while (tilecount < 34) { int color_byte; int color_bits; @@ -474,40 +436,60 @@ static void draw_background(const device_config *device, UINT8 *line_priority ) index1 = tile_index + x; + + // this is attribute table stuff! (actually read 2 in PPUspeak)! /* Figure out which byte in the color table to use */ - pos = ( ( index1 & 0x380 ) >> 4 ) | ( ( index1 & 0x1f ) >> 2 ); + pos = ((index1 & 0x380) >> 4) | ((index1 & 0x1f) >> 2); page = (index1 & 0x0c00) >> 10; address = 0x3c0 + pos; - color_byte = ppu_page[page][address]; + color_byte = memory_read_byte(device->space[0], (((page * 0x400) + address) & 0xfff) + 0x2000); /* figure out which bits in the color table to use */ - color_bits = ( ( index1 & 0x40 ) >> 4 ) + ( index1 & 0x02 ); + color_bits = ((index1 & 0x40) >> 4) + (index1 & 0x02); + // page2 is the output of the nametable read (this section is the FIRST read per tile!) address = index1 & 0x3ff; - page2 = ppu_page[page][address]; - index2 = nes_vram[ ( page2 >> 6 ) | tile_page ] + ( page2 & 0x3f ); + page2 = memory_read_byte(device->space[0], index1); + index2 = nes_vram[(page2 >> 6) | tile_page] + (page2 & 0x3f); - //27/12/2002 - if( ppu_latch ) + // 27/12/2002 + if (ppu_latch) { - (*ppu_latch)(device, ( tile_page << 10 ) | ( page2 << 4 )); + (*ppu_latch)(device, (tile_page << 10) | (page2 << 4)); } - if(start_x < VISIBLE_SCREEN_WIDTH ) + if (start_x < VISIBLE_SCREEN_WIDTH) { - paldata = &color_table[ 4 * ( ( ( color_byte >> color_bits ) & 0x03 ) ) ]; - start = scroll_y_fine * line_modulo; - sd = gfx_element_get_data(device->machine->gfx[gfx_bank], index2 % total_elements) + start; + UINT8 plane1, plane2; // use extended size so I can shift! + paldata = &color_table[4 * (((color_byte >> color_bits) & 0x03))]; + // start = scroll_y_fine * line_modulo; + + // need to read 0x0000 or 0x1000 + 16*nametable data + address = ((this_ppu->tile_page) ? 0x1000 : 0) + (page2 * 16); + // plus something that accounts for y + // address -= (scanline % 8); + address += scroll_y_fine; + + plane1 = memory_read_byte(device->space[0], (address & 0x1fff)); + plane2 = memory_read_byte(device->space[0], (address + 8) & 0x1fff); + // plane2 = plane2 << 1; + +// sd = gfx_element_get_data(device->machine->gfx[gfx_bank], index2 % total_elements) + start; /* render the pixel */ - for( i = 0; i < 8; i++ ) + for (i = 0; i < 8; i++) { - if ( ( start_x+i ) >= 0 && ( start_x+i ) < VISIBLE_SCREEN_WIDTH ) + UINT8 pix; + pix = ((plane1 >> 7) & 1) | (((plane2 >> 7) & 1) << 1); + plane1 = plane1 << 1; + plane2 = plane2 << 1; + if ((start_x + i) >= 0 && (start_x + i) < VISIBLE_SCREEN_WIDTH) { - if ( sd[i] ) + + if (pix) { - pen = paldata[sd[i]]; - line_priority[ start_x+i ] |= 0x02; + pen = paldata[pix]; + line_priority[start_x + i] |= 0x02; } else { @@ -522,7 +504,7 @@ static void draw_background(const device_config *device, UINT8 *line_priority ) /* move to next tile over and toggle the horizontal name table if necessary */ x++; - if ( x > 31 ) + if (x > 31) { x = 0; tile_index ^= 0x400; @@ -532,29 +514,26 @@ static void draw_background(const device_config *device, UINT8 *line_priority ) } /* if the left 8 pixels for the background are off, blank 'em */ - if ( !( ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_BACKGROUND_L8 ) ) + if (!(ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_BACKGROUND_L8)) { dest = ((UINT16 *) bitmap->base) + (bitmap->rowpixels * scanline); - for( i = 0; i < 8; i++ ) + for (i = 0; i < 8; i++) { *(dest++) = back_pen; - line_priority[ i ] ^= 0x02; + line_priority[i] ^= 0x02; } } } -static void draw_sprites(const device_config *device, UINT8 *line_priority ) +static void draw_sprites( const device_config *device, UINT8 *line_priority ) { - const ppu2c0x_interface *intf = get_interface(device); + // const ppu2c0x_interface *intf = get_interface(device); ppu2c0x_chip *this_ppu = get_token(device); /* cache some values locally */ bitmap_t *bitmap = this_ppu->bitmap; const int scanline = this_ppu->scanline; - const int gfx_bank = intf->gfx_layout_number; - const int total_elements = device->machine->gfx[gfx_bank]->total_elements; const int sprite_page = this_ppu->sprite_page; - const int line_modulo = device->machine->gfx[gfx_bank]->line_modulo; const UINT8 *sprite_ram = this_ppu->spriteram; pen_t *color_table = this_ppu->colortable; int *ppu_regs = &this_ppu->regs[0]; @@ -568,23 +547,25 @@ static void draw_sprites(const device_config *device, UINT8 *line_priority ) int spriteCount = 0; int sprite_line; int drawn; - int start; int first_pixel; const pen_t *paldata; - const UINT8 *sd; + // const UINT8 *sd; int pixel; /* determine if the sprites are 8x8 or 8x16 */ - size = ( ppu_regs[PPU_CONTROL0] & PPU_CONTROL0_SPRITE_SIZE ) ? 16 : 8; + size = (ppu_regs[PPU_CONTROL0] & PPU_CONTROL0_SPRITE_SIZE) ? 16 : 8; first_pixel = (ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_SPRITES_L8)? 0: 8; - for( spriteIndex = 0; spriteIndex < SPRITERAM_SIZE; spriteIndex += 4 ) + for (spriteIndex = 0; spriteIndex < SPRITERAM_SIZE; spriteIndex += 4) { + UINT8 plane1; + UINT8 plane2; + spriteYPos = sprite_ram[spriteIndex] + 1; - spriteXPos = sprite_ram[spriteIndex+3]; + spriteXPos = sprite_ram[spriteIndex + 3]; // The sprite collision acts funny on the last pixel of a scanline. // The various scanline latches update while the last few pixels @@ -602,22 +583,22 @@ static void draw_sprites(const device_config *device, UINT8 *line_priority ) } /* if the sprite isn't visible, skip it */ - if ( ( spriteYPos + size <= scanline ) || ( spriteYPos > scanline ) ) + if ((spriteYPos + size <= scanline) || (spriteYPos > scanline)) continue; /* clear our drawn flag */ drawn = 0; - tile = sprite_ram[spriteIndex+1]; - color = ( sprite_ram[spriteIndex+2] & 0x03 ) + 4; - pri = sprite_ram[spriteIndex+2] & 0x20; - flipx = sprite_ram[spriteIndex+2] & 0x40; - flipy = sprite_ram[spriteIndex+2] & 0x80; + tile = sprite_ram[spriteIndex + 1]; + color = (sprite_ram[spriteIndex + 2] & 0x03) + 4; + pri = sprite_ram[spriteIndex + 2] & 0x20; + flipx = sprite_ram[spriteIndex + 2] & 0x40; + flipy = sprite_ram[spriteIndex + 2] & 0x80; - if ( size == 16 ) + if (size == 16) { /* if it's 8x16 and odd-numbered, draw the other half instead */ - if ( tile & 0x01 ) + if (tile & 0x01) { tile &= ~0x01; tile |= 0x100; @@ -626,54 +607,82 @@ static void draw_sprites(const device_config *device, UINT8 *line_priority ) page = tile >> 6; } else - page = ( tile >> 6 ) | sprite_page; + page = (tile >> 6) | sprite_page; - index1 = this_ppu->nes_vram[page] + ( tile & 0x3f ); + // index1 = this_ppu->nes_vram[page] + (tile & 0x3f); - if ( ppu_latch ) - (*ppu_latch)(device, ( sprite_page << 10 ) | ( (tile & 0xff) << 4 )); + if (ppu_latch) + (*ppu_latch)(device, (sprite_page << 10) | ((tile & 0xff) << 4)); /* compute the character's line to draw */ sprite_line = scanline - spriteYPos; - if ( flipy ) - sprite_line = ( size - 1 ) - sprite_line; + + if (flipy) + sprite_line = (size - 1) - sprite_line; paldata = &color_table[4 * color]; - start = sprite_line * line_modulo; - sd = gfx_element_get_data(device->machine->gfx[gfx_bank], index1 % total_elements) + start; - if (size > 8) - gfx_element_get_data(device->machine->gfx[gfx_bank], (index1 + 1) % total_elements); - if ( pri ) + if (size == 16 && sprite_line > 7) + { + tile++; + sprite_line -= 8; + } + + index1 = tile * 16; + if (size == 8) + index1 += ((sprite_page == 0) ? 0 : 0x1000); + + plane1 = memory_read_byte(device->space[0], (index1 + sprite_line) & 0x1fff); + plane2 = memory_read_byte(device->space[0], (index1 + sprite_line + 8) & 0x1fff); + +// sd = gfx_element_get_data(device->machine->gfx[gfx_bank], index1 % total_elements) + start; +// if (size > 8) +// gfx_element_get_data(device->machine->gfx[gfx_bank], (index1 + 1) % total_elements); + + if (pri) { /* draw the low-priority sprites */ - - for ( pixel = 0; pixel < 8; pixel++ ) + for (pixel = 0; pixel < 8; pixel++) { - UINT8 pixelData = flipx ? sd[7-pixel] : sd[pixel]; +// UINT8 pixelData = flipx ? sd[7-pixel] : sd[pixel]; + UINT8 pixelData; + if (flipx) + { + pixelData = (plane1 & 1) + ((plane2 & 1) << 1); + plane1 = plane1 >> 1; + plane2 = plane2 >> 1; + // sd[7 - pixel] + } + else + { + pixelData = ((plane1 >> 7) & 1) | (((plane2 >> 7) & 1) << 1); + plane1 = plane1 << 1; + plane2 = plane2 << 1; + // sd[pixel]; + } /* is this pixel non-transparent? */ - if ( spriteXPos + pixel >= first_pixel) + if (spriteXPos + pixel >= first_pixel) { if (pixelData) { /* has the background (or another sprite) already been drawn here? */ - if ( !line_priority[ spriteXPos + pixel ] ) + if (!line_priority[spriteXPos + pixel]) { /* no, draw */ - if ( ( spriteXPos + pixel ) < VISIBLE_SCREEN_WIDTH ) + if ((spriteXPos + pixel) < VISIBLE_SCREEN_WIDTH) *BITMAP_ADDR16(bitmap, scanline, spriteXPos + pixel) = paldata[pixelData]; drawn = 1; } /* indicate that a sprite was drawn at this location, even if it's not seen */ - if ( ( spriteXPos + pixel ) < VISIBLE_SCREEN_WIDTH ) - line_priority[ spriteXPos + pixel ] |= 0x01; + if ((spriteXPos + pixel) < VISIBLE_SCREEN_WIDTH) + line_priority[spriteXPos + pixel] |= 0x01; } /* set the "sprite 0 hit" flag if appropriate */ - if ( spriteIndex == 0 && (pixelData & 0x03) && ((spriteXPos + pixel) < 255) && ( line_priority[ spriteXPos + pixel ] & 0x02 )) + if (spriteIndex == 0 && (pixelData & 0x03) && ((spriteXPos + pixel) < 255) && (line_priority[spriteXPos + pixel] & 0x02)) ppu_regs[PPU_STATUS] |= PPU_STATUS_SPRITE0_HIT; } } @@ -681,41 +690,54 @@ static void draw_sprites(const device_config *device, UINT8 *line_priority ) else { /* draw the high-priority sprites */ - - for ( pixel = 0; pixel < 8; pixel++ ) + for (pixel = 0; pixel < 8; pixel++) { - UINT8 pixelData = flipx ? sd[7-pixel] : sd[pixel]; + UINT8 pixelData; + if (flipx) + { + pixelData = (plane1 & 1) + ((plane2 & 1) << 1); + plane1 = plane1 >> 1; + plane2 = plane2 >> 1; + // sd[7 - pixel] + } + else + { + pixelData = ((plane1 >> 7) & 1) | (((plane2 >> 7) & 1) << 1); + plane1 = plane1 << 1; + plane2 = plane2 << 1; + // sd[pixel]; + } /* is this pixel non-transparent? */ - if ( spriteXPos + pixel >= first_pixel) + if (spriteXPos + pixel >= first_pixel) { if (pixelData) { /* has another sprite been drawn here? */ - if ( !( line_priority[ spriteXPos + pixel ] & 0x01 ) ) + if (!(line_priority[spriteXPos + pixel] & 0x01)) { /* no, draw */ - if ( ( spriteXPos + pixel ) < VISIBLE_SCREEN_WIDTH ) + if ((spriteXPos + pixel) < VISIBLE_SCREEN_WIDTH) { *BITMAP_ADDR16(bitmap, scanline, spriteXPos + pixel) = paldata[pixelData]; - line_priority[ spriteXPos + pixel ] |= 0x01; + line_priority[spriteXPos + pixel] |= 0x01; } drawn = 1; } } /* set the "sprite 0 hit" flag if appropriate */ - if ( spriteIndex == 0 && (pixelData & 0x03) && ((spriteXPos + pixel) < 255) && ( line_priority[ spriteXPos + pixel ] & 0x02 )) + if (spriteIndex == 0 && (pixelData & 0x03) && ((spriteXPos + pixel) < 255) && (line_priority[spriteXPos + pixel] & 0x02)) ppu_regs[PPU_STATUS] |= PPU_STATUS_SPRITE0_HIT; } } } - if ( drawn ) + if (drawn) { /* if there are more than 8 sprites on this line, set the flag */ spriteCount++; - if ( spriteCount == 8 ) + if (spriteCount == 8) { ppu_regs[PPU_STATUS] |= PPU_STATUS_8SPRITES; // logerror ("> 8 sprites, scanline: %d\n", scanline); @@ -732,25 +754,26 @@ static void draw_sprites(const device_config *device, UINT8 *line_priority ) * Scanline Rendering and Update * *************************************/ -static void render_scanline(const device_config *device) + +static void render_scanline( const device_config *device ) { ppu2c0x_chip *this_ppu = get_token(device); const ppu2c0x_interface *intf = get_interface(device); - UINT8 line_priority[VISIBLE_SCREEN_WIDTH]; - int *ppu_regs = &this_ppu->regs[0]; + UINT8 line_priority[VISIBLE_SCREEN_WIDTH]; + int *ppu_regs = &this_ppu->regs[0]; /* lets see how long it takes */ profiler_mark(PROFILER_USER1); /* clear the line priority for this scanline */ - memset( line_priority, 0, VISIBLE_SCREEN_WIDTH ); + memset(line_priority, 0, VISIBLE_SCREEN_WIDTH); /* clear the sprite count for this line */ ppu_regs[PPU_STATUS] &= ~PPU_STATUS_8SPRITES; /* see if we need to render the background */ - if ( ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_BACKGROUND ) - draw_background(device, line_priority ); + if (ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_BACKGROUND) + draw_background(device, line_priority); else { bitmap_t *bitmap = this_ppu->bitmap; @@ -760,46 +783,46 @@ static void render_scanline(const device_config *device) int i; /* setup the color mask and colortable to use */ - if ( ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO ) + if (ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO) color_mask = 0xf0; else color_mask = 0xff; /* cache the background pen */ - back_pen = (this_ppu->back_color & color_mask)+intf->color_base; + back_pen = (this_ppu->back_color & color_mask) + intf->color_base; // Fill this scanline with the background pen. - for (i = 0; i < bitmap->width; i ++) + for (i = 0; i < bitmap->width; i++) *BITMAP_ADDR16(bitmap, scanline, i) = back_pen; } /* if sprites are on, draw them */ - if ( ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_SPRITES ) - draw_sprites( device, line_priority ); + if (ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_SPRITES) + draw_sprites(device, line_priority); /* done updating, whew */ profiler_mark(PROFILER_END); } -static void update_scanline(const device_config *device) +static void update_scanline( const device_config *device ) { ppu2c0x_chip *this_ppu = get_token(device); const ppu2c0x_interface *intf = get_interface(device); int scanline = this_ppu->scanline; int *ppu_regs = &this_ppu->regs[0]; - if ( scanline <= PPU_BOTTOM_VISIBLE_SCANLINE ) + if (scanline <= PPU_BOTTOM_VISIBLE_SCANLINE) { /* Render this scanline if appropriate */ - if ( ppu_regs[PPU_CONTROL1] & ( PPU_CONTROL1_BACKGROUND | PPU_CONTROL1_SPRITES ) ) + if (ppu_regs[PPU_CONTROL1] & (PPU_CONTROL1_BACKGROUND | PPU_CONTROL1_SPRITES)) { /* If background or sprites are enabled, copy the ppu address latch */ /* Copy only the scroll x-coarse and the x-overflow bit */ this_ppu->refresh_data &= ~0x041f; - this_ppu->refresh_data |= ( this_ppu->refresh_latch & 0x041f ); + this_ppu->refresh_data |= (this_ppu->refresh_latch & 0x041f); -//logerror(" updating refresh_data: %04x (scanline: %d)\n", this_ppu->refresh_data, this_ppu->scanline); - render_scanline( device ); +// logerror("updating refresh_data: %04x (scanline: %d)\n", this_ppu->refresh_data, this_ppu->scanline); + render_scanline(device); } else { @@ -810,7 +833,7 @@ static void update_scanline(const device_config *device) int i; /* setup the color mask and colortable to use */ - if ( ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO ) + if (ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO) color_mask = 0xf0; else color_mask = 0xff; @@ -825,17 +848,17 @@ static void update_scanline(const device_config *device) int penNum; if (this_ppu->videomem_addr & 0x03) - penNum = this_ppu->videomem[this_ppu->videomem_addr & 0x3f1f] & 0x3f; + penNum = this_ppu->palette_ram[this_ppu->videomem_addr & 0x1f]; else - penNum = this_ppu->videomem[this_ppu->videomem_addr & 0x3f00] & 0x3f; + penNum = this_ppu->palette_ram[0]; back_pen = penNum + intf->color_base; } else - back_pen = (this_ppu->back_color & color_mask)+intf->color_base; + back_pen = (this_ppu->back_color & color_mask) + intf->color_base; // Fill this scanline with the background pen. - for (i = 0; i < bitmap->width; i ++) + for (i = 0; i < bitmap->width; i++) *BITMAP_ADDR16(bitmap, scanline, i) = back_pen; } @@ -843,20 +866,20 @@ static void update_scanline(const device_config *device) this_ppu->refresh_data += 0x1000; /* if it's rolled, increment the coarse y-scroll */ - if ( this_ppu->refresh_data & 0x8000 ) + if (this_ppu->refresh_data & 0x8000) { UINT16 tmp; - tmp = ( this_ppu->refresh_data & 0x03e0 ) + 0x20; + tmp = (this_ppu->refresh_data & 0x03e0) + 0x20; this_ppu->refresh_data &= 0x7c1f; /* handle bizarro scrolling rollover at the 30th (not 32nd) vertical tile */ - if ( tmp == 0x03c0 ) + if (tmp == 0x03c0) this_ppu->refresh_data ^= 0x0800; else - this_ppu->refresh_data |= ( tmp & 0x03e0 ); + this_ppu->refresh_data |= (tmp & 0x03e0); -//logerror("updating refresh_data: %04x\n", this_ppu->refresh_data); - } +// logerror("updating refresh_data: %04x\n", this_ppu->refresh_data); + } } } @@ -866,26 +889,26 @@ static TIMER_CALLBACK( scanline_callback ) const device_config *device = (const device_config *)ptr; ppu2c0x_chip *this_ppu = get_token(device); int *ppu_regs = &this_ppu->regs[0]; - int blanked = ( ppu_regs[PPU_CONTROL1] & ( PPU_CONTROL1_BACKGROUND | PPU_CONTROL1_SPRITES ) ) == 0; - int vblank = ((this_ppu->scanline >= PPU_VBLANK_FIRST_SCANLINE-1) && (this_ppu->scanline < this_ppu->scanlines_per_frame-1)) ? 1 : 0; + int blanked = (ppu_regs[PPU_CONTROL1] & (PPU_CONTROL1_BACKGROUND | PPU_CONTROL1_SPRITES)) == 0; + int vblank = ((this_ppu->scanline >= PPU_VBLANK_FIRST_SCANLINE - 1) && (this_ppu->scanline < this_ppu->scanlines_per_frame - 1)) ? 1 : 0; int next_scanline; /* if a callback is available, call it */ - if ( this_ppu->scanline_callback_proc != NULL ) - (*this_ppu->scanline_callback_proc)( device, this_ppu->scanline, vblank, blanked ); + if (this_ppu->scanline_callback_proc != NULL) + (*this_ppu->scanline_callback_proc)(device, this_ppu->scanline, vblank, blanked); /* update the scanline that just went by */ - update_scanline( device ); + update_scanline(device); /* increment our scanline count */ this_ppu->scanline++; -//logerror("starting scanline %d (MAME %d, beam %d)\n", this_ppu->scanline, video_screen_get_vpos(device->machine->primary_screen), video_screen_get_hpos(device->machine->primary_screen)); +// logerror("starting scanline %d (MAME %d, beam %d)\n", this_ppu->scanline, video_screen_get_vpos(device->machine->primary_screen), video_screen_get_hpos(device->machine->primary_screen)); /* Note: this is called at the _end_ of each scanline */ if (this_ppu->scanline == PPU_VBLANK_FIRST_SCANLINE) { -logerror("vlbank starting\n"); + // logerror("vblank starting\n"); /* We just entered VBLANK */ ppu_regs[PPU_STATUS] |= PPU_STATUS_VBLANK; @@ -900,26 +923,26 @@ logerror("vlbank starting\n"); } } - if ( this_ppu->scanline == this_ppu->scanlines_per_frame - 1 ) + if (this_ppu->scanline == this_ppu->scanlines_per_frame - 1) { -logerror("vlbank ending\n"); + // logerror("vblank ending\n"); /* clear the vblank & sprite hit flag */ - ppu_regs[PPU_STATUS] &= ~( PPU_STATUS_VBLANK | PPU_STATUS_SPRITE0_HIT ); + ppu_regs[PPU_STATUS] &= ~(PPU_STATUS_VBLANK | PPU_STATUS_SPRITE0_HIT); } /* see if we rolled */ - else if ( this_ppu->scanline == this_ppu->scanlines_per_frame ) + else if (this_ppu->scanline == this_ppu->scanlines_per_frame) { /* if background or sprites are enabled, copy the ppu address latch */ - if ( !blanked ) + if (!blanked) this_ppu->refresh_data = this_ppu->refresh_latch; /* reset the scanline count */ this_ppu->scanline = 0; -//logerror(" sprite 0 x: %d y: %d num: %d\n", this_ppu->spriteram[3], this_ppu->spriteram[0]+1, this_ppu->spriteram[1]); +// logerror("sprite 0 x: %d y: %d num: %d\n", this_ppu->spriteram[3], this_ppu->spriteram[0] + 1, this_ppu->spriteram[1]); } - next_scanline = this_ppu->scanline+1; + next_scanline = this_ppu->scanline + 1; if (next_scanline == this_ppu->scanlines_per_frame) next_scanline = 0; @@ -961,7 +984,7 @@ static DEVICE_RESET( ppu2c0x ) this_ppu->scanline_callback_proc = 0; this_ppu->vidaccess_callback_proc = 0; - for( i = 0; i < PPU_MAX_REG; i++ ) + for (i = 0; i < PPU_MAX_REG; i++) this_ppu->regs[i] = 0; /* initialize the rest of the members */ @@ -981,7 +1004,7 @@ static DEVICE_RESET( ppu2c0x ) { int color_base = intf->color_base; - for( i = 0; i < ARRAY_LENGTH( default_colortable_mono ); i++ ) + for (i = 0; i < ARRAY_LENGTH(default_colortable_mono); i++) { /* monochromatic table */ this_ppu->colortable_mono[i] = default_colortable_mono[i] + color_base; @@ -992,13 +1015,61 @@ static DEVICE_RESET( ppu2c0x ) } /* set the vram bank-switch values to the default */ - for( i = 0; i < 8; i++ ) + for (i = 0; i < 8; i++) this_ppu->nes_vram[i] = i * 64; - if ( this_ppu->has_videorom ) - ppu2c0x_set_videorom_bank( device, 0, 8, 0, 512 ); +// if (this_ppu->has_videorom) +// ppu2c0x_set_videorom_bank(device, 0, 8, 0, 512); } +/************************************* +* +* PPU Memory functions +* +*************************************/ + +WRITE8_HANDLER( ppu2c0x_palette_write ) +{ + ppu2c0x_chip *this_ppu = get_token(space->cpu); + const ppu2c0x_interface *intf = get_interface(space->cpu); + int color_base = intf->color_base; + + int colorEmphasis = (this_ppu->regs[PPU_CONTROL1] & PPU_CONTROL1_COLOR_EMPHASIS) * 2; + // it's a palette + // transparent pens are mirrored! + if (offset & 0x3) + { + this_ppu->palette_ram[offset & 0x1f] = data; + this_ppu->colortable[offset & 0x1f] = color_base + data + colorEmphasis; + this_ppu->colortable_mono[offset & 0x1f] = color_base + (data & 0xf0) + colorEmphasis; + } + else + { + int i; + if (0 == (offset & 0xf)) + { + this_ppu->back_color = data; + for (i = 0; i < 32; i += 4) + { + this_ppu->colortable[i] = color_base + data + colorEmphasis; + this_ppu->colortable_mono[i] = color_base + (data & 0xf0) + colorEmphasis; + } + } + this_ppu->palette_ram[offset & 0xf] = this_ppu->palette_ram[(offset & 0xf) + 0x10] = data; + } +} + +READ8_HANDLER( ppu2c0x_palette_read ) +{ + ppu2c0x_chip *this_ppu = get_token(space->cpu); + { + // it's a palette + // ERROR: doesn't currently handle monochrome! + if (this_ppu->regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO) + return (this_ppu->palette_ram[offset & 0x1f] & 0x30); + else return (this_ppu->palette_ram[offset & 0x1f] & 0x3f); + } +} /************************************* * @@ -1010,14 +1081,14 @@ READ8_DEVICE_HANDLER( ppu2c0x_r ) { ppu2c0x_chip *this_ppu = get_token(device); - if ( offset >= PPU_MAX_REG ) + if (offset >= PPU_MAX_REG) { - logerror( "PPU %s(r): Attempting to read past the chip\n", device->tag ); + logerror("PPU %s(r): Attempting to read past the chip\n", device->tag); offset &= PPU_MAX_REG - 1; } // see which register to read - switch( offset & 7 ) + switch (offset & 7) { case PPU_STATUS: // The top 3 bits of the status register are the only ones that report data. The @@ -1037,22 +1108,20 @@ READ8_DEVICE_HANDLER( ppu2c0x_r ) break; case PPU_DATA: - if ( this_ppu->videomem_addr >= 0x3f00 ) + if (ppu_latch) + (*ppu_latch)(device, this_ppu->videomem_addr & 0x3fff); + + if (this_ppu->videomem_addr >= 0x3f00) { - this_ppu->data_latch = this_ppu->videomem[this_ppu->videomem_addr & 0x3F1F]; - if (this_ppu->regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO) - this_ppu->data_latch &= 0x30; + this_ppu->data_latch = memory_read_byte(device->space[0], this_ppu->videomem_addr); + // buffer the mirrored NT data + this_ppu->buffered_data = memory_read_byte(device->space[0], this_ppu->videomem_addr & 0x2fff); } else + { this_ppu->data_latch = this_ppu->buffered_data; - - if ( ppu_latch ) - (*ppu_latch)( device, this_ppu->videomem_addr & 0x3fff ); - - if ( ( this_ppu->videomem_addr >= 0x2000 ) && ( this_ppu->videomem_addr <= 0x3fff ) ) - this_ppu->buffered_data = this_ppu->ppu_page[ ( this_ppu->videomem_addr & 0xc00) >> 10][ this_ppu->videomem_addr & 0x3ff ]; - else - this_ppu->buffered_data = this_ppu->videomem[ this_ppu->videomem_addr & 0x3fff ]; + this_ppu->buffered_data = memory_read_byte(device->space[0], this_ppu->videomem_addr); + } this_ppu->videomem_addr += this_ppu->add; break; @@ -1079,9 +1148,9 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w ) color_base = intf->color_base; - if ( offset >= PPU_MAX_REG ) + if (offset >= PPU_MAX_REG) { - logerror( "PPU: Attempting to write past the chip\n" ); + logerror("PPU: Attempting to write past the chip\n"); offset &= PPU_MAX_REG - 1; } @@ -1089,41 +1158,41 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w ) if (this_ppu->scanline <= PPU_BOTTOM_VISIBLE_SCANLINE) { const device_config *screen = device->machine->primary_screen; - logerror(" PPU register %d write %02x during non-vblank scanline %d (MAME %d, beam pos: %d)\n", offset, data, this_ppu->scanline, video_screen_get_vpos(screen), video_screen_get_hpos(screen)); + logerror("PPU register %d write %02x during non-vblank scanline %d (MAME %d, beam pos: %d)\n", offset, data, this_ppu->scanline, video_screen_get_vpos(screen), video_screen_get_hpos(screen)); } #endif - switch( offset & 7 ) + switch (offset & 7) { case PPU_CONTROL0: this_ppu->regs[PPU_CONTROL0] = data; /* update the name table number on our refresh latches */ this_ppu->refresh_latch &= 0x73ff; - this_ppu->refresh_latch |= ( data & 3 ) << 10; + this_ppu->refresh_latch |= (data & 3) << 10; /* the char ram bank points either 0x0000 or 0x1000 (page 0 or page 4) */ - this_ppu->tile_page = ( data & PPU_CONTROL0_CHR_SELECT ) >> 2; - this_ppu->sprite_page = ( data & PPU_CONTROL0_SPR_SELECT ) >> 1; + this_ppu->tile_page = (data & PPU_CONTROL0_CHR_SELECT) >> 2; + this_ppu->sprite_page = (data & PPU_CONTROL0_SPR_SELECT) >> 1; - this_ppu->add = ( data & PPU_CONTROL0_INC ) ? 32 : 1; -//logerror(" control0 write: %02x (scanline: %d)\n", data, this_ppu->scanline); + this_ppu->add = (data & PPU_CONTROL0_INC) ? 32 : 1; +// logerror("control0 write: %02x (scanline: %d)\n", data, this_ppu->scanline); break; case PPU_CONTROL1: /* if color intensity has changed, change all the color tables to reflect them */ - if ( ( data & PPU_CONTROL1_COLOR_EMPHASIS ) != ( this_ppu->regs[PPU_CONTROL1] & PPU_CONTROL1_COLOR_EMPHASIS ) ) + if ((data & PPU_CONTROL1_COLOR_EMPHASIS) != (this_ppu->regs[PPU_CONTROL1] & PPU_CONTROL1_COLOR_EMPHASIS)) { int i; for (i = 0; i <= 0x1f; i ++) { - UINT8 oldColor = this_ppu->videomem[i+0x3f00]; + UINT8 oldColor = this_ppu->palette_ram[i]; - this_ppu->colortable[i] = color_base + oldColor + (data & PPU_CONTROL1_COLOR_EMPHASIS)*2; + this_ppu->colortable[i] = color_base + oldColor + (data & PPU_CONTROL1_COLOR_EMPHASIS) * 2; } } -//logerror(" control1 write: %02x (scanline: %d)\n", data, this_ppu->scanline); +// logerror("control1 write: %02x (scanline: %d)\n", data, this_ppu->scanline); this_ppu->regs[PPU_CONTROL1] = data; break; @@ -1136,17 +1205,17 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w ) if (this_ppu->scanline <= PPU_BOTTOM_VISIBLE_SCANLINE) data = 0xff; this_ppu->spriteram[this_ppu->regs[PPU_SPRITE_ADDRESS]] = data; - this_ppu->regs[PPU_SPRITE_ADDRESS] = ( this_ppu->regs[PPU_SPRITE_ADDRESS] + 1 ) & 0xff; + this_ppu->regs[PPU_SPRITE_ADDRESS] = (this_ppu->regs[PPU_SPRITE_ADDRESS] + 1) & 0xff; break; case PPU_SCROLL: - if ( this_ppu->toggle ) + if (this_ppu->toggle) { /* second write */ this_ppu->refresh_latch &= 0x0c1f; - this_ppu->refresh_latch |= ( data & 0xf8 ) << 2; - this_ppu->refresh_latch |= ( data & 0x07 ) << 12; -//logerror(" scroll write 2: %d, %04x (scanline: %d)\n", data, this_ppu->refresh_latch, this_ppu->scanline); + this_ppu->refresh_latch |= (data & 0xf8) << 2; + this_ppu->refresh_latch |= (data & 0x07) << 12; +// logerror("scroll write 2: %d, %04x (scanline: %d)\n", data, this_ppu->refresh_latch, this_ppu->scanline); } else { @@ -1155,14 +1224,14 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w ) this_ppu->refresh_latch |= (data & 0xf8) >> 3; this_ppu->x_fine = data & 7; -//logerror(" scroll write 1: %d, %04x (scanline: %d)\n", data, this_ppu->refresh_latch, this_ppu->scanline); +// logerror("scroll write 1: %d, %04x (scanline: %d)\n", data, this_ppu->refresh_latch, this_ppu->scanline); } this_ppu->toggle ^= 1; break; case PPU_ADDRESS: - if ( this_ppu->toggle ) + if (this_ppu->toggle) { /* second write */ this_ppu->refresh_latch &= 0x7f00; @@ -1170,14 +1239,14 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w ) this_ppu->refresh_data = this_ppu->refresh_latch; this_ppu->videomem_addr = this_ppu->refresh_latch; -//logerror(" vram addr write 2: %02x, %04x (scanline: %d)\n", data, this_ppu->refresh_latch, this_ppu->scanline); +// logerror("vram addr write 2: %02x, %04x (scanline: %d)\n", data, this_ppu->refresh_latch, this_ppu->scanline); } else { /* first write */ this_ppu->refresh_latch &= 0x00ff; - this_ppu->refresh_latch |= ( data & 0x3f ) << 8; -//logerror(" vram addr write 1: %02x, %04x (scanline: %d)\n", data, this_ppu->refresh_latch, this_ppu->scanline); + this_ppu->refresh_latch |= (data & 0x3f) << 8; +// logerror("vram addr write 1: %02x, %04x (scanline: %d)\n", data, this_ppu->refresh_latch, this_ppu->scanline); } this_ppu->toggle ^= 1; @@ -1187,80 +1256,37 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w ) { int tempAddr = this_ppu->videomem_addr & 0x3fff; - if ( ppu_latch ) - (*ppu_latch)( device, tempAddr ); + if (ppu_latch) + (*ppu_latch)(device, tempAddr); /* if there's a callback, call it now */ - if ( this_ppu->vidaccess_callback_proc ) - data = (*this_ppu->vidaccess_callback_proc)( device, tempAddr, data ); + if (this_ppu->vidaccess_callback_proc) + data = (*this_ppu->vidaccess_callback_proc)(device, tempAddr, data); /* see if it's on the chargen portion */ - if ( tempAddr < 0x2000 ) + if (tempAddr < 0x2000) { /* if we have a videorom mapped there, dont write and log the problem */ - if ( this_ppu->has_videorom && !this_ppu->has_videoram ) + if (this_ppu->has_videorom && !this_ppu->has_videoram) { /* if there is a vidaccess callback, assume it coped with it */ - if ( this_ppu->vidaccess_callback_proc == NULL ) - logerror( "PPU: Attempting to write to the chargen when there's a ROM there!\n" ); + if (this_ppu->vidaccess_callback_proc == NULL) + logerror("PPU: Attempting to write to the chargen when there's a ROM there!\n"); } else { /* store the data */ - this_ppu->videomem[tempAddr] = data; + memory_write_byte(device->space[0], tempAddr, data); /* mark the char dirty */ - gfx_element_mark_dirty(device->machine->gfx[intf->gfx_layout_number], tempAddr >> 4); + // gfx_element_mark_dirty(device->machine->gfx[intf->gfx_layout_number], tempAddr >> 4); } } - else if ( tempAddr >= 0x3f00 ) - { - int colorEmphasis = (this_ppu->regs[PPU_CONTROL1] & PPU_CONTROL1_COLOR_EMPHASIS) * 2; - - /* store the data */ - if (tempAddr & 0x03) - this_ppu->videomem[tempAddr & 0x3F1F] = data; - else - { - this_ppu->videomem[0x3F10+(tempAddr&0xF)] = data; - this_ppu->videomem[0x3F00+(tempAddr&0xF)] = data; - } - - /* As usual, some games attempt to write values > the number of colors so we must mask the data. */ - data &= 0x3f; - - if ( tempAddr & 0x03 ) - { - this_ppu->colortable[ tempAddr & 0x1f ] = color_base + data + colorEmphasis; - this_ppu->colortable_mono[tempAddr & 0x1f] = color_base + (data & 0xf0) + colorEmphasis; - } - - /* The only valid background colors are writes to 0x3f00 and 0x3f10 */ - /* and even then, they are mirrors of each other. */ - if ( ( tempAddr & 0x0f ) == 0 ) - { - int i; - - this_ppu->back_color = data; - for( i = 0; i < 32; i += 4 ) - { - this_ppu->colortable[ i ] = color_base + data + colorEmphasis; - this_ppu->colortable_mono[i] = color_base + (data & 0xf0) + colorEmphasis; - } - } - } - - /* everything else */ - /* writes to $3000-$3eff are mirrors of $2000-$2eff */ else { - int page = ( tempAddr & 0x0c00) >> 10; - int address = tempAddr & 0x3ff; - - this_ppu->ppu_page[page][address] = data; + memory_write_byte(device->space[0], tempAddr, data); } - /* increment the address */ this_ppu->videomem_addr += this_ppu->add; } @@ -1277,16 +1303,18 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w ) * Sprite DMA * *************************************/ -void ppu2c0x_spriteram_dma (const address_space *space, const device_config *device, const UINT8 page) + +void ppu2c0x_spriteram_dma( const address_space *space, const device_config *device, const UINT8 page ) { int i; int address = page << 8; -//logerror(" sprite DMA: %d (scanline: %d)\n", page, this_ppu->scanline); +// logerror("sprite DMA: %d (scanline: %d)\n", page, this_ppu->scanline); for (i = 0; i < SPRITERAM_SIZE; i++) { UINT8 spriteData = memory_read_byte(space, address + i); - ppu2c0x_w (device, PPU_SPRITE_DATA, spriteData); + memory_write_byte(space, 0x2004, spriteData); +// ppu2c0x_w(device, PPU_SPRITE_DATA, spriteData); } // should last 513 CPU cycles. @@ -1314,98 +1342,7 @@ void ppu2c0x_spriteram_dma (const address_space *space, const device_config *dev void ppu2c0x_render( const device_config *device, bitmap_t *bitmap, int flipx, int flipy, int sx, int sy ) { ppu2c0x_chip *this_ppu = get_token(device); - copybitmap( bitmap, this_ppu->bitmap, flipx, flipy, sx, sy, 0 ); -} - -/************************************* - * - * PPU VideoROM banking - * - *************************************/ -void ppu2c0x_set_videorom_bank( const device_config *device, int start_page, int num_pages, int bank, int bank_size ) -{ - ppu2c0x_chip *this_ppu = get_token(device); - const ppu2c0x_interface *intf = get_interface(device); - int i; - - if ( !this_ppu->has_videorom ) - { - logerror( "PPU(set vrom bank): Attempting to switch videorom banks and no rom is mapped\n" ); - return; - } - - bank &= ( this_ppu->videorom_banks * ( CHARGEN_NUM_CHARS / bank_size ) ) - 1; - - if (this_ppu->has_videoram) - { - for ( i = start_page; i < start_page + num_pages; i++ ) - { - int elemnum; - - if ( this_ppu->videoram_banks_indices[i] != -1 ) - { - memcpy( &this_ppu->videoram[this_ppu->videoram_banks_indices[i]*0x400], &this_ppu->videomem[i*0x400], 0x400); - } - this_ppu->videoram_banks_indices[i] = -1; - for (elemnum = 0; elemnum < (num_pages*0x400 >> 4); elemnum++) - gfx_element_mark_dirty(device->machine->gfx[intf->gfx_layout_number], (start_page*0x400 >> 4) + elemnum); - } - } - else - { - for( i = start_page; i < ( start_page + num_pages ); i++ ) - this_ppu->nes_vram[i] = bank * bank_size + 64 * ( i - start_page ); - } - - { - int vram_start = start_page * 0x400; - int count = num_pages * 0x400; - int rom_start = bank * bank_size * 16; - - memcpy( &this_ppu->videomem[vram_start], &memory_region( device->machine, intf->vrom_region )[rom_start], count ); - } -} - -/************************************* - * - * PPU VideoRAM banking - * - *************************************/ - -void ppu2c0x_set_videoram_bank( const device_config *device, int start_page, int num_pages, int bank, int bank_size ) -{ - ppu2c0x_chip *this_ppu = get_token(device); - const ppu2c0x_interface *intf = get_interface(device); - int i; - - if ( !this_ppu->has_videoram ) - { - logerror( "PPU(set vram bank): Attempting to switch videoram banks and no ram is mapped\n" ); - return; - } - - bank &= ( CHARGEN_NUM_CHARS / bank_size ) - 1; - - for ( i = start_page; i < start_page + num_pages; i++ ) - { - int elemnum; - if ( this_ppu->videoram_banks_indices[i] != -1 ) - { - memcpy( &this_ppu->videoram[this_ppu->videoram_banks_indices[i]*0x400], &this_ppu->videomem[i*0x400], 0x400); - } - this_ppu->videoram_banks_indices[i] = (bank * bank_size * 16)/0x400 + (i - start_page); - for (elemnum = 0; elemnum < (num_pages*0x400 >> 4); elemnum++) - gfx_element_mark_dirty(device->machine->gfx[intf->gfx_layout_number], (start_page*0x400 >> 4) + elemnum); - } - - { - int vram_start = start_page * 0x400; - int count = num_pages * 0x400; - int ram_start = bank * bank_size * 16; - - logerror( "ppu2c0x_set_videoram_bank: vram_start = %04x, count = %04x, ram_start = %04x\n", vram_start, count, ram_start ); - memcpy( &this_ppu->videomem[vram_start], &this_ppu->videoram[ram_start], count ); - } + copybitmap(bitmap, this_ppu->bitmap, flipx, flipy, sx, sy, 0); } /************************************* @@ -1418,10 +1355,10 @@ int ppu2c0x_get_pixel( const device_config *device, int x, int y ) { ppu2c0x_chip *this_ppu = get_token(device); - if ( x >= VISIBLE_SCREEN_WIDTH ) + if (x >= VISIBLE_SCREEN_WIDTH) x = VISIBLE_SCREEN_WIDTH - 1; - if ( y >= VISIBLE_SCREEN_HEIGHT ) + if (y >= VISIBLE_SCREEN_HEIGHT) y = VISIBLE_SCREEN_HEIGHT - 1; return *BITMAP_ADDR16(this_ppu->bitmap, y, x); @@ -1439,60 +1376,6 @@ int ppu2c0x_get_current_scanline( const device_config *device ) return this_ppu->scanline; } -void ppu2c0x_set_mirroring( const device_config *device, int mirroring ) -{ - ppu2c0x_chip *this_ppu = get_token(device); - - // Once we've set 4-screen mirroring, do not change. Some games - // (notably Gauntlet) use mappers that can change the mirroring - // state, but are also hard-coded for 4-screen VRAM. - if (this_ppu->mirror_state == PPU_MIRROR_4SCREEN) - return; - - /* setup our videomem handlers based on mirroring */ - switch( mirroring ) - { - case PPU_MIRROR_VERT: - this_ppu->ppu_page[0] = &(this_ppu->videomem[0x2000]); - this_ppu->ppu_page[1] = &(this_ppu->videomem[0x2400]); - this_ppu->ppu_page[2] = &(this_ppu->videomem[0x2000]); - this_ppu->ppu_page[3] = &(this_ppu->videomem[0x2400]); - break; - - case PPU_MIRROR_HORZ: - this_ppu->ppu_page[0] = &(this_ppu->videomem[0x2000]); - this_ppu->ppu_page[1] = &(this_ppu->videomem[0x2000]); - this_ppu->ppu_page[2] = &(this_ppu->videomem[0x2400]); - this_ppu->ppu_page[3] = &(this_ppu->videomem[0x2400]); - break; - - case PPU_MIRROR_HIGH: - this_ppu->ppu_page[0] = &(this_ppu->videomem[0x2400]); - this_ppu->ppu_page[1] = &(this_ppu->videomem[0x2400]); - this_ppu->ppu_page[2] = &(this_ppu->videomem[0x2400]); - this_ppu->ppu_page[3] = &(this_ppu->videomem[0x2400]); - break; - - case PPU_MIRROR_LOW: - this_ppu->ppu_page[0] = &(this_ppu->videomem[0x2000]); - this_ppu->ppu_page[1] = &(this_ppu->videomem[0x2000]); - this_ppu->ppu_page[2] = &(this_ppu->videomem[0x2000]); - this_ppu->ppu_page[3] = &(this_ppu->videomem[0x2000]); - break; - - case PPU_MIRROR_NONE: - case PPU_MIRROR_4SCREEN: - default: - this_ppu->ppu_page[0] = &(this_ppu->videomem[0x2000]); - this_ppu->ppu_page[1] = &(this_ppu->videomem[0x2400]); - this_ppu->ppu_page[2] = &(this_ppu->videomem[0x2800]); - this_ppu->ppu_page[3] = &(this_ppu->videomem[0x2c00]); - break; - } - - this_ppu->mirror_state = mirroring; -} - void ppu2c0x_set_scanline_callback( const device_config *device, ppu2c0x_scanline_cb cb ) { ppu2c0x_chip *this_ppu = get_token(device); @@ -1531,6 +1414,14 @@ DEVICE_GET_INFO(ppu2c02) case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break; case DEVINFO_INT_CLASS: info->i = DEVICE_CLASS_PERIPHERAL; break; case PPU2C0XINFO_INT_SCANLINES_PER_FRAME: info->i = PPU_NTSC_SCANLINES_PER_FRAME; break; + case DEVINFO_INT_DATABUS_WIDTH_0: info->i = 8; break; + case DEVINFO_INT_ADDRBUS_WIDTH_0: info->i = 14; break; + case DEVINFO_INT_ADDRBUS_SHIFT_0: info->i = 0; break; + + + /* --- the following bits of info are returned as pointers to data --- */ + case DEVINFO_PTR_DEFAULT_MEMORY_MAP_0: info->default_map8 = ADDRESS_MAP_NAME(ppu2c0x);break; + /* --- the following bits of info are returned as pointers to data or functions --- */ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ppu2c0x); break; diff --git a/src/mame/video/ppu2c0x.h b/src/mame/video/ppu2c0x.h index 8c9571f6943..60f8f71be6f 100644 --- a/src/mame/video/ppu2c0x.h +++ b/src/mame/video/ppu2c0x.h @@ -109,14 +109,11 @@ DEVICE_GET_INFO(ppu2c07); /* routines */ void ppu2c0x_init_palette(running_machine *machine, int first_entry ) ATTR_NONNULL(1); -void ppu2c0x_set_videorom_bank( const device_config *device, int start_page, int num_pages, int bank, int bank_size ) ATTR_NONNULL(1); -void ppu2c0x_set_videoram_bank( const device_config *device, int start_page, int num_pages, int bank, int bank_size ) ATTR_NONNULL(1); void ppu2c0x_spriteram_dma(const address_space *space, const device_config *device, const UINT8 page ) ATTR_NONNULL(1); void ppu2c0x_render( const device_config *device, bitmap_t *bitmap, int flipx, int flipy, int sx, int sy ) ATTR_NONNULL(1); int ppu2c0x_get_pixel( const device_config *device, int x, int y ) ATTR_NONNULL(1); int ppu2c0x_get_colorbase( const device_config *device ) ATTR_NONNULL(1); int ppu2c0x_get_current_scanline( const device_config *device ) ATTR_NONNULL(1); -void ppu2c0x_set_mirroring( const device_config *device, int mirroring ) ATTR_NONNULL(1); void ppu2c0x_set_scanline_callback( const device_config *device, ppu2c0x_scanline_cb cb ) ATTR_NONNULL(1); void ppu2c0x_set_hblank_callback( const device_config *device, ppu2c0x_scanline_cb cb ) ATTR_NONNULL(1); void ppu2c0x_set_vidaccess_callback( const device_config *device, ppu2c0x_vidaccess_cb cb ) ATTR_NONNULL(1);