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);