Commit of Robert Bohms' NES PPU updates (please refer to his -emails for details)

Also, not worth mention, I've done some readability tweaks and fixed some crashes in cham24 and multigam (due to wrong copy and paste in the original diffs). multigam.c games still have some issues (which I'm trying to fix with Rob's help)
This commit is contained in:
Fabio Priuli 2009-07-31 09:10:31 +00:00
parent 6cdff80638
commit fd631b29b6
10 changed files with 1260 additions and 868 deletions

View File

@ -60,6 +60,54 @@ Notes:
#include "sound/nes_apu.h" #include "sound/nes_apu.h"
#include "video/ppu2c0x.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 ) static WRITE8_HANDLER( sprite_dma_w )
{ {
int source = (data & 7); int source = (data & 7);
@ -123,16 +171,15 @@ static WRITE8_HANDLER( cham24_mapper_w )
UINT32 prg_bank = (offset >> 7) & 0x1f; UINT32 prg_bank = (offset >> 7) & 0x1f;
UINT32 prg_bank_page_size = (offset >> 12) & 0x01; UINT32 prg_bank_page_size = (offset >> 12) & 0x01;
UINT32 gfx_mirroring = (offset >> 13) & 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* dst = memory_region(space->machine, "maincpu");
UINT8* src = memory_region(space->machine, "user1"); UINT8* src = memory_region(space->machine, "user1");
// switch PPU VROM bank // 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 // 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 // switch PRG bank
if (prg_bank_page_size == 0) if (prg_bank_page_size == 0)
@ -188,7 +235,6 @@ static INPUT_PORTS_START( cham24 )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) 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( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
INPUT_PORTS_END INPUT_PORTS_END
static const nes_interface cham24_interface_1 = static const nes_interface cham24_interface_1 =
@ -239,6 +285,15 @@ static VIDEO_UPDATE( cham24 )
static DRIVER_INIT( cham24 ) 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 ) static GFXDECODE_START( cham24 )

View File

@ -45,6 +45,69 @@
#include "sound/nes_apu.h" #include "sound/nes_apu.h"
#include "video/ppu2c0x.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 NES interface
@ -151,9 +214,8 @@ static WRITE8_HANDLER(multigam_switch_prg_rom)
static WRITE8_HANDLER(multigam_switch_gfx_rom) static WRITE8_HANDLER(multigam_switch_gfx_rom)
{ {
const device_config *ppu = devtag_get_device(space->machine, "ppu"); memory_set_bankptr(space->machine, 1, memory_region(space->machine, "gfx1") + (0x2000 * data));
ppu2c0x_set_videorom_bank( ppu, 0, 8, data /*& 0x3f*/, 512 ); set_mirroring(data & 0x40 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
ppu2c0x_set_mirroring( ppu, data & 0x40 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT );
multigam_game_gfx_bank = data; multigam_game_gfx_bank = data;
}; };
@ -162,8 +224,7 @@ 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"); memory_set_bankptr(space->machine, 1, memory_region(space->machine, "gfx1") + (0x2000 * ((data & 0xf) + multigam_game_gfx_bank)));
ppu2c0x_set_videorom_bank( ppu, 0, 8, multigam_game_gfx_bank + (data & 0xf), 512 );
} }
else else
{ {
@ -276,7 +337,7 @@ static WRITE8_HANDLER( multigam3_mmc3_rom_switch_w )
case 1: /* char banking */ case 1: /* char banking */
data &= 0xfe; data &= 0xfe;
page ^= (cmd << 1); page ^= (cmd << 1);
ppu2c0x_set_videorom_bank( ppu, page, 2, 0x180 + data, 64 ); set_videorom_bank(space->machine, page, 2, 0x180 + data, 1);
break; break;
case 2: /* char banking */ case 2: /* char banking */
@ -284,7 +345,7 @@ static WRITE8_HANDLER( multigam3_mmc3_rom_switch_w )
case 4: /* char banking */ case 4: /* char banking */
case 5: /* char banking */ case 5: /* char banking */
page ^= cmd + 2; page ^= cmd + 2;
ppu2c0x_set_videorom_bank( ppu, page, 1, 0x180 + data, 64 ); set_videorom_bank(space->machine, page, 1, 0x180 + data, 1);
break; break;
case 6: /* program banking */ case 6: /* program banking */
@ -332,9 +393,9 @@ static WRITE8_HANDLER( multigam3_mmc3_rom_switch_w )
if (!multigam3_mmc3_4screen) if (!multigam3_mmc3_4screen)
{ {
if (data & 0x40) if (data & 0x40)
ppu2c0x_set_mirroring( ppu, PPU_MIRROR_HIGH ); set_mirroring(PPU_MIRROR_HIGH);
else else
ppu2c0x_set_mirroring( ppu, ( data & 1 ) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT ); set_mirroring((data & 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
} }
break; break;
@ -385,8 +446,7 @@ 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"); set_videorom_bank(space->machine, 0, 8, (multigam_game_gfx_bank & 0xfc) + (data & 0x3), 8);
ppu2c0x_set_videorom_bank( ppu, 0, 8, (multigam_game_gfx_bank & 0xfc) + (data & 0x3), 512 );
} }
else else
{ {
@ -580,6 +640,28 @@ static MACHINE_RESET( multigm3 )
multigm3_switch_prg_rom(space, 0, 0x01 ); 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 ) static MACHINE_DRIVER_START( multigam )
/* basic machine hardware */ /* basic machine hardware */
@ -587,6 +669,7 @@ static MACHINE_DRIVER_START( multigam )
MDRV_CPU_PROGRAM_MAP(multigam_map) MDRV_CPU_PROGRAM_MAP(multigam_map)
MDRV_MACHINE_RESET( multigam ) MDRV_MACHINE_RESET( multigam )
MDRV_MACHINE_START( multigam )
/* video hardware */ /* video hardware */
MDRV_SCREEN_ADD("screen", RASTER) MDRV_SCREEN_ADD("screen", RASTER)
@ -620,6 +703,7 @@ static MACHINE_DRIVER_START( multigm3 )
MDRV_CPU_MODIFY("maincpu") MDRV_CPU_MODIFY("maincpu")
MDRV_CPU_PROGRAM_MAP(multigm3_map) MDRV_CPU_PROGRAM_MAP(multigm3_map)
MDRV_MACHINE_START( multigm3 )
MDRV_MACHINE_RESET( multigm3 ) MDRV_MACHINE_RESET( multigm3 )
MACHINE_DRIVER_END MACHINE_DRIVER_END

View File

@ -702,6 +702,7 @@ static MACHINE_DRIVER_START( playch10 )
MDRV_CPU_PROGRAM_MAP(cart_map) MDRV_CPU_PROGRAM_MAP(cart_map)
MDRV_MACHINE_RESET(pc10) MDRV_MACHINE_RESET(pc10)
MDRV_MACHINE_START(pc10)
// video hardware // video hardware
MDRV_GFXDECODE(playch10) MDRV_GFXDECODE(playch10)
@ -746,6 +747,7 @@ MACHINE_DRIVER_END
static MACHINE_DRIVER_START( playch10_hboard ) static MACHINE_DRIVER_START( playch10_hboard )
MDRV_IMPORT_FROM(playch10) MDRV_IMPORT_FROM(playch10)
MDRV_VIDEO_START(playch10_hboard) MDRV_VIDEO_START(playch10_hboard)
MDRV_MACHINE_START(playch10_hboard)
MDRV_DEVICE_REMOVE("ppu") MDRV_DEVICE_REMOVE("ppu")
MDRV_PPU2C03B_ADD("ppu", playch10_ppu_interface) MDRV_PPU2C03B_ADD("ppu", playch10_ppu_interface)

View File

@ -1768,6 +1768,7 @@ static MACHINE_DRIVER_START( vsnes )
MDRV_CPU_PROGRAM_MAP(vsnes_cpu1_map) MDRV_CPU_PROGRAM_MAP(vsnes_cpu1_map)
/* some carts also trigger IRQs */ /* some carts also trigger IRQs */
MDRV_MACHINE_RESET(vsnes) MDRV_MACHINE_RESET(vsnes)
MDRV_MACHINE_START(vsnes)
/* video hardware */ /* video hardware */
MDRV_SCREEN_ADD("screen", RASTER) MDRV_SCREEN_ADD("screen", RASTER)
@ -1806,6 +1807,7 @@ static MACHINE_DRIVER_START( vsdual )
MDRV_CPU_PROGRAM_MAP(vsnes_cpu2_map) MDRV_CPU_PROGRAM_MAP(vsnes_cpu2_map)
/* some carts also trigger IRQs */ /* some carts also trigger IRQs */
MDRV_MACHINE_RESET(vsdual) MDRV_MACHINE_RESET(vsdual)
MDRV_MACHINE_START(vsdual)
/* video hardware */ /* video hardware */
MDRV_PALETTE_LENGTH(2*8*4*16) MDRV_PALETTE_LENGTH(2*8*4*16)

View File

@ -1,6 +1,8 @@
/*----------- defined in machine/playch10.c -----------*/ /*----------- defined in machine/playch10.c -----------*/
MACHINE_RESET( pc10 ); MACHINE_RESET( pc10 );
MACHINE_START( pc10 );
MACHINE_START( playch10_hboard );
DRIVER_INIT( playch10 ); /* standard games */ DRIVER_INIT( playch10 ); /* standard games */
DRIVER_INIT( pc_gun ); /* gun games */ DRIVER_INIT( pc_gun ); /* gun games */
DRIVER_INIT( pc_hrz ); /* horizontal games */ DRIVER_INIT( pc_hrz ); /* horizontal games */

View File

@ -15,6 +15,8 @@ extern const ppu2c0x_interface vsnes_ppu_interface_2;
MACHINE_RESET( vsnes ); MACHINE_RESET( vsnes );
MACHINE_RESET( vsdual ); MACHINE_RESET( vsdual );
MACHINE_START( vsnes );
MACHINE_START( vsdual );
DRIVER_INIT( suprmrio ); DRIVER_INIT( suprmrio );
DRIVER_INIT( excitebk ); DRIVER_INIT( excitebk );
DRIVER_INIT( excitbkj ); DRIVER_INIT( excitbkj );

View File

@ -3,6 +3,22 @@
#include "machine/rp5h01.h" #include "machine/rp5h01.h"
#include "includes/playch10.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 */ /* Globals */
int pc10_sdcs; /* ShareD Chip Select */ int pc10_sdcs; /* ShareD Chip Select */
int pc10_dispmask; /* Display Mask */ int pc10_dispmask; /* Display Mask */
@ -21,14 +37,20 @@ static int mirroring;
static int MMC2_bank[4], MMC2_bank_latch[2]; 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 * Init machine
* *
*************************************/ *************************************/
MACHINE_RESET( pc10 ) MACHINE_RESET( pc10 )
{ {
const device_config *ppu = devtag_get_device(machine, "ppu");
const device_config *rp5h01 = devtag_get_device(machine, "rp5h01"); const device_config *rp5h01 = devtag_get_device(machine, "rp5h01");
/* initialize latches and flip-flops */ /* initialize latches and flip-flops */
@ -51,7 +73,39 @@ MACHINE_RESET( pc10 )
rp5h01_reset_w(rp5h01, 0, 1); rp5h01_reset_w(rp5h01, 0, 1);
rp5h01_enable_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);
} }
/************************************* /*************************************
@ -136,6 +190,7 @@ WRITE8_HANDLER( pc10_CARTSEL_w )
* RP5H01 handling * RP5H01 handling
* *
*************************************/ *************************************/
READ8_HANDLER( pc10_prot_r ) READ8_HANDLER( pc10_prot_r )
{ {
const device_config *rp5h01 = devtag_get_device(space->machine, "rp5h01"); const device_config *rp5h01 = devtag_get_device(space->machine, "rp5h01");
@ -179,6 +234,7 @@ WRITE8_HANDLER( pc10_prot_w )
* Input Ports * Input Ports
* *
*************************************/ *************************************/
WRITE8_HANDLER( pc10_in0_w ) WRITE8_HANDLER( pc10_in0_w )
{ {
/* Toggling bit 0 high then low resets both controllers */ /* Toggling bit 0 high then low resets both controllers */
@ -256,15 +312,135 @@ READ8_HANDLER( pc10_in1_r )
return ret; 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 * Common init for all games
* *
*************************************/ *************************************/
DRIVER_INIT( playch10 ) DRIVER_INIT( playch10 )
{ {
vram = NULL;
/* set the controller to default */ /* set the controller to default */
pc10_gun_controller = 0; pc10_gun_controller = 0;
@ -285,6 +461,9 @@ DRIVER_INIT( pc_gun )
/* common init */ /* common init */
DRIVER_INIT_CALL(playch10); 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 */ /* set the control type */
pc10_gun_controller = 1; pc10_gun_controller = 1;
} }
@ -337,8 +516,6 @@ static WRITE8_HANDLER( mmc1_rom_switch_w )
/* are we done shifting? */ /* are we done shifting? */
if (mmc1_shiftcount == 5) if (mmc1_shiftcount == 5)
{ {
const device_config *ppu = devtag_get_device(space->machine, "ppu");
/* reset count */ /* reset count */
mmc1_shiftcount = 0; mmc1_shiftcount = 0;
@ -374,17 +551,17 @@ static WRITE8_HANDLER( mmc1_rom_switch_w )
} }
/* apply mirroring */ /* apply mirroring */
ppu2c0x_set_mirroring( ppu, _mirroring ); pc10_set_mirroring(_mirroring);
} }
break; break;
case 1: /* video rom banking - bank 0 - 4k or 8k */ 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; break;
case 2: /* video rom banking - bank 1 - 4k only */ case 2: /* video rom banking - bank 1 - 4k only */
if (vrom4k) if (vrom4k)
ppu2c0x_set_videorom_bank( ppu, 4, 4, ( mmc1_shiftreg & 0x1f ), 256 ); pc10_set_videorom_bank(space->machine, 4, 4, (mmc1_shiftreg & 0x1f), 4);
break; break;
case 3: /* program banking */ case 3: /* program banking */
@ -418,13 +595,11 @@ static WRITE8_HANDLER( mmc1_rom_switch_w )
} }
/**********************************************************************************/ /**********************************************************************************/
/* A Board games (Track & Field, Gradius) */ /* A Board games (Track & Field, Gradius) */
static WRITE8_HANDLER( aboard_vrom_switch_w ) static WRITE8_HANDLER( aboard_vrom_switch_w )
{ {
const device_config *ppu = devtag_get_device(space->machine, "ppu"); pc10_set_videorom_bank(space->machine, 0, 8, (data & 3), 8);
ppu2c0x_set_videorom_bank( ppu, 0, 8, ( data & 3 ), 512 );
} }
DRIVER_INIT( pcaboard ) DRIVER_INIT( pcaboard )
@ -437,10 +612,12 @@ DRIVER_INIT( pcaboard )
/* set the mirroring here */ /* set the mirroring here */
mirroring = PPU_MIRROR_VERT; 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) */ /* B Board games (Contra, Rush N' Attach, Pro Wrestling) */
static WRITE8_HANDLER( bboard_rom_switch_w ) static WRITE8_HANDLER( bboard_rom_switch_w )
@ -465,18 +642,21 @@ DRIVER_INIT( pcbboard )
/* common init */ /* common init */
DRIVER_INIT_CALL(playch10); DRIVER_INIT_CALL(playch10);
/* allocate vram */
vram = auto_alloc_array(machine, UINT8, 0x2000);
/* set the mirroring here */ /* set the mirroring here */
mirroring = PPU_MIRROR_VERT; mirroring = PPU_MIRROR_VERT;
/* special init */
set_videoram_bank(machine, 0, 8, 0, 8);
} }
/**********************************************************************************/ /**********************************************************************************/
/* C Board games (The Goonies) */ /* C Board games (The Goonies) */
static WRITE8_HANDLER( cboard_vrom_switch_w ) static WRITE8_HANDLER( cboard_vrom_switch_w )
{ {
const device_config *ppu = devtag_get_device(space->machine, "ppu"); pc10_set_videorom_bank(space->machine, 0, 8, ((data >> 1) & 1), 8);
ppu2c0x_set_videorom_bank( ppu, 0, 8, ( ( data >> 1 ) & 1 ), 512 );
} }
DRIVER_INIT( pccboard ) DRIVER_INIT( pccboard )
@ -484,12 +664,14 @@ DRIVER_INIT( pccboard )
/* switches vrom with writes to $6000 */ /* 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 ); 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 */ /* common init */
DRIVER_INIT_CALL(playch10); DRIVER_INIT_CALL(playch10);
} }
/**********************************************************************************/ /**********************************************************************************/
/* D Board games (Rad Racer) */ /* D Board games (Rad Racer) */
DRIVER_INIT( pcdboard ) DRIVER_INIT( pcdboard )
@ -505,8 +687,13 @@ DRIVER_INIT( pcdboard )
/* MMC mapper at writes to $8000-$ffff */ /* 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 ); memory_install_write8_handler(cputag_get_address_space(machine, "cart", ADDRESS_SPACE_PROGRAM), 0x8000, 0xffff, 0, 0, mmc1_rom_switch_w );
/* common init */ /* common init */
DRIVER_INIT_CALL(playch10); 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) */ /* D Board games with extra ram (Metroid) */
@ -519,10 +706,14 @@ DRIVER_INIT( pcdboard_2 )
/* common init */ /* common init */
DRIVER_INIT_CALL(pcdboard); 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 */ /* E Board games (Mike Tyson's Punchout) - BROKEN - FIX ME */
/* callback for the ppu_latch */ /* callback for the ppu_latch */
@ -532,29 +723,27 @@ 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; 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; 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; 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; 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 ) 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 */ /* a variation of mapper 9 on a nes */
switch (offset & 0x7000) switch (offset & 0x7000)
{ {
@ -569,29 +758,29 @@ static WRITE8_HANDLER( eboard_rom_switch_w )
case 0x3000: /* gfx bank 0 - 4k */ case 0x3000: /* gfx bank 0 - 4k */
MMC2_bank[0] = data; MMC2_bank[0] = data;
if (MMC2_bank_latch[0] == 0xfd) if (MMC2_bank_latch[0] == 0xfd)
ppu2c0x_set_videorom_bank( ppu, 0, 4, data, 256 ); pc10_set_videorom_bank(space->machine, 0, 4, data, 4);
break; break;
case 0x4000: /* gfx bank 0 - 4k */ case 0x4000: /* gfx bank 0 - 4k */
MMC2_bank[1] = data; MMC2_bank[1] = data;
if (MMC2_bank_latch[0] == 0xfe) if (MMC2_bank_latch[0] == 0xfe)
ppu2c0x_set_videorom_bank( ppu, 0, 4, data, 256 ); pc10_set_videorom_bank(space->machine, 0, 4, data, 4);
break; break;
case 0x5000: /* gfx bank 1 - 4k */ case 0x5000: /* gfx bank 1 - 4k */
MMC2_bank[2] = data; MMC2_bank[2] = data;
if (MMC2_bank_latch[1] == 0xfd) if (MMC2_bank_latch[1] == 0xfd)
ppu2c0x_set_videorom_bank( ppu, 4, 4, data, 256 ); pc10_set_videorom_bank(space->machine, 4, 4, data, 4);
break; break;
case 0x6000: /* gfx bank 1 - 4k */ case 0x6000: /* gfx bank 1 - 4k */
MMC2_bank[3] = data; MMC2_bank[3] = data;
if (MMC2_bank_latch[1] == 0xfe) if (MMC2_bank_latch[1] == 0xfe)
ppu2c0x_set_videorom_bank( ppu, 4, 4, data, 256 ); pc10_set_videorom_bank(space->machine, 4, 4, data, 4);
break; break;
case 0x7000: /* mirroring */ 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; break;
} }
@ -601,6 +790,9 @@ 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 */ /* We do manual banking, in case the code falls through */
/* Copy the initial banks */ /* Copy the initial banks */
memcpy(&prg[0x08000], &prg[0x28000], 0x8000); memcpy(&prg[0x08000], &prg[0x28000], 0x8000);
@ -620,13 +812,15 @@ DRIVER_INIT( pceboard )
} }
/**********************************************************************************/ /**********************************************************************************/
/* F Board games (Ninja Gaiden, Double Dragon) */ /* F Board games (Ninja Gaiden, Double Dragon) */
DRIVER_INIT( pcfboard ) 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 */ /* We do manual banking, in case the code falls through */
/* Copy the initial banks */ /* Copy the initial banks */
memcpy(&prg[0x08000], &prg[0x28000], 0x8000); memcpy(&prg[0x08000], &prg[0x28000], 0x8000);
@ -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_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)); memory_set_bankptr(machine, 1, auto_alloc_array(machine, UINT8, 0x1000));
vram = NULL;
/* common init */ /* common init */
DRIVER_INIT_CALL(pcfboard); DRIVER_INIT_CALL(pcfboard);
} }
/**********************************************************************************/ /**********************************************************************************/
/* G Board games (Super Mario Bros. 3) */ /* G Board games (Super Mario Bros. 3) */
static int gboard_scanline_counter; static int gboard_scanline_counter;
@ -729,7 +924,7 @@ static WRITE8_HANDLER( gboard_rom_switch_w )
case 1: /* char banking */ case 1: /* char banking */
data &= 0xfe; data &= 0xfe;
page ^= (cmd << 1); page ^= (cmd << 1);
ppu2c0x_set_videorom_bank( ppu, page, 2, data, 64 ); pc10_set_videorom_bank(space->machine, page, 2, data, 1);
break; break;
case 2: /* char banking */ case 2: /* char banking */
@ -737,7 +932,7 @@ static WRITE8_HANDLER( gboard_rom_switch_w )
case 4: /* char banking */ case 4: /* char banking */
case 5: /* char banking */ case 5: /* char banking */
page ^= cmd + 2; page ^= cmd + 2;
ppu2c0x_set_videorom_bank( ppu, page, 1, data, 64 ); pc10_set_videorom_bank(space->machine, page, 1, data, 1);
break; break;
case 6: /* program banking */ case 6: /* program banking */
@ -782,9 +977,9 @@ static WRITE8_HANDLER( gboard_rom_switch_w )
if (!gboard_4screen) if (!gboard_4screen)
{ {
if (data & 0x40) if (data & 0x40)
ppu2c0x_set_mirroring( ppu, PPU_MIRROR_HIGH ); pc10_set_mirroring(PPU_MIRROR_HIGH);
else 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; break;
@ -813,6 +1008,7 @@ static WRITE8_HANDLER( gboard_rom_switch_w )
DRIVER_INIT( pcgboard ) 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 */ /* We do manual banking, in case the code falls through */
/* Copy the initial banks */ /* Copy the initial banks */
@ -838,6 +1034,7 @@ DRIVER_INIT( pcgboard )
DRIVER_INIT( pcgboard_type2 ) DRIVER_INIT( pcgboard_type2 )
{ {
vram = NULL;
/* common init */ /* common init */
DRIVER_INIT_CALL(pcgboard); DRIVER_INIT_CALL(pcgboard);
@ -846,19 +1043,17 @@ DRIVER_INIT( pcgboard_type2 )
} }
/**********************************************************************************/ /**********************************************************************************/
/* i Board games (Captain Sky Hawk, Solar Jetman) */ /* i Board games (Captain Sky Hawk, Solar Jetman) */
static WRITE8_HANDLER( iboard_rom_switch_w ) static WRITE8_HANDLER( iboard_rom_switch_w )
{ {
int bank = data & 7; 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) if (data & 0x10)
ppu2c0x_set_mirroring( ppu, PPU_MIRROR_HIGH ); pc10_set_mirroring(PPU_MIRROR_HIGH);
else 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);
} }
@ -876,16 +1071,18 @@ DRIVER_INIT( pciboard )
/* common init */ /* common init */
DRIVER_INIT_CALL(playch10); 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) */ /* H Board games (PinBot) */
static WRITE8_HANDLER( hboard_rom_switch_w ) 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: case 0x0001:
@ -899,13 +1096,13 @@ static WRITE8_HANDLER( hboard_rom_switch_w )
case 1: /* char banking */ case 1: /* char banking */
data &= 0xfe; data &= 0xfe;
page ^= (cmd << 1); page ^= (cmd << 1);
if ( data & 0x20 ) if (data & 0x40)
{ {
ppu2c0x_set_videoram_bank( ppu, page, 2, data, 64 ); set_videoram_bank(space->machine, page, 2, data, 1);
} }
else else
{ {
ppu2c0x_set_videorom_bank( ppu, page, 2, data, 64 ); pc10_set_videorom_bank(space->machine, page, 2, data, 1);
} }
return; return;
@ -916,11 +1113,11 @@ static WRITE8_HANDLER( hboard_rom_switch_w )
page ^= cmd + 2; 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 else
{ {
ppu2c0x_set_videorom_bank( ppu, page, 1, data, 64 ); pc10_set_videorom_bank(space->machine, page, 1, data, 1);
} }
return; return;
} }
@ -955,7 +1152,6 @@ DRIVER_INIT( pchboard )
} }
/**********************************************************************************/ /**********************************************************************************/
/* K Board games (Mario Open Golf) */ /* K Board games (Mario Open Golf) */
DRIVER_INIT( pckboard ) DRIVER_INIT( pckboard )
@ -977,4 +1173,9 @@ DRIVER_INIT( pckboard )
/* common init */ /* common init */
DRIVER_INIT_CALL(playch10); DRIVER_INIT_CALL(playch10);
/* allocate vram */
vram = auto_alloc_array(machine, UINT8, 0x2000);
/* special init */
set_videoram_bank(machine, 0, 8, 0, 8);
} }

View File

@ -22,6 +22,25 @@ static const UINT8 *remapped_colortable;
static int sound_fix=0; static int sound_fix=0;
static UINT8 last_bank; 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 * Color Mapping
@ -113,6 +132,7 @@ static int remap_colors( const device_config *device, int addr, int data )
* Input Ports * Input Ports
* *
*************************************/ *************************************/
WRITE8_HANDLER( vsnes_in0_w ) WRITE8_HANDLER( vsnes_in0_w )
{ {
/* Toggling bit 0 high then low resets both controllers */ /* Toggling bit 0 high then low resets both controllers */
@ -148,7 +168,6 @@ static READ8_HANDLER( gun_in0_r )
} }
READ8_HANDLER( vsnes_in0_r ) READ8_HANDLER( vsnes_in0_r )
{ {
@ -164,7 +183,6 @@ READ8_HANDLER( vsnes_in0_r )
} }
READ8_HANDLER( vsnes_in1_r ) READ8_HANDLER( vsnes_in1_r )
{ {
int ret = (input_latch[1]) & 1; int ret = (input_latch[1]) & 1;
@ -238,6 +256,7 @@ MACHINE_RESET( vsnes )
* Init machine * Init machine
* *
*************************************/ *************************************/
MACHINE_RESET( vsdual ) MACHINE_RESET( vsdual )
{ {
const device_config *ppu1 = devtag_get_device(machine, "ppu1"); const device_config *ppu1 = devtag_get_device(machine, "ppu1");
@ -254,11 +273,167 @@ MACHINE_RESET( vsdual )
} }
} }
/*************************************
*
* 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);
}
}
/************************************* /*************************************
* *
* Common init for all games * Common init for all games
* *
*************************************/ *************************************/
static void init_vsnes(running_machine *machine) static void init_vsnes(running_machine *machine)
{ {
/* set the controller to default */ /* set the controller to default */
@ -276,10 +451,8 @@ static void init_vsnes(running_machine *machine)
static WRITE8_HANDLER( vsnormal_vrom_banking ) static WRITE8_HANDLER( vsnormal_vrom_banking )
{ {
const device_config *ppu1 = devtag_get_device(space->machine, "ppu1");
/* switch vrom */ /* 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 */ /* bit 1 ( data & 2 ) enables writes to extra ram, we ignore it */
@ -311,7 +484,6 @@ static WRITE8_HANDLER( ppuRC2C05_protection )
} }
/**********************************************************************************/ /**********************************************************************************/
/* Super Mario Bros. Extra ram at $6000 (NV?) and remapped colors */ /* Super Mario Bros. Extra ram at $6000 (NV?) and remapped colors */
DRIVER_INIT( suprmrio ) DRIVER_INIT( suprmrio )
@ -333,7 +505,6 @@ DRIVER_INIT( suprmrio )
} }
/**********************************************************************************/ /**********************************************************************************/
/* Gun Games - VROM Banking in controller 0 write */ /* Gun Games - VROM Banking in controller 0 write */
static WRITE8_HANDLER( gun_in0_w ) static WRITE8_HANDLER( gun_in0_w )
@ -344,7 +515,7 @@ static WRITE8_HANDLER( gun_in0_w )
if (vsnes_do_vrom_bank) if (vsnes_do_vrom_bank)
{ {
/* switch vrom */ /* 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 */ /* here we do things a little different */
@ -401,12 +572,10 @@ DRIVER_INIT( duckhunt )
} }
/**********************************************************************************/ /**********************************************************************************/
/* The Goonies, VS Gradius: ROMs bankings at $8000-$ffff */ /* The Goonies, VS Gradius: ROMs bankings at $8000-$ffff */
static WRITE8_HANDLER( goonies_rom_banking ) static WRITE8_HANDLER( goonies_rom_banking )
{ {
const device_config *ppu1 = devtag_get_device(space->machine, "ppu1");
int reg = (offset >> 12) & 0x07; int reg = (offset >> 12) & 0x07;
int bankoffset = (data & 7) * 0x2000 + 0x10000; int bankoffset = (data & 7) * 0x2000 + 0x10000;
@ -422,11 +591,11 @@ static WRITE8_HANDLER( goonies_rom_banking )
break; break;
case 6: /* vrom bank 0 */ 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; break;
case 7: /* vrom bank 1 */ 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; break;
} }
} }
@ -496,7 +665,6 @@ DRIVER_INIT( hogalley )
} }
/***********************************************************************/ /***********************************************************************/
/* Vs. Gumshoe */ /* Vs. Gumshoe */
static READ8_HANDLER( vsgshoe_security_r ) static READ8_HANDLER( vsgshoe_security_r )
@ -541,7 +709,6 @@ DRIVER_INIT( vsgshoe )
} }
/**********************************************************************************/ /**********************************************************************************/
/* Dr Mario: ROMs bankings at $8000-$ffff */ /* Dr Mario: ROMs bankings at $8000-$ffff */
static int drmario_shiftreg; static int drmario_shiftreg;
@ -549,8 +716,6 @@ static int drmario_shiftcount;
static WRITE8_HANDLER( drmario_rom_banking ) static WRITE8_HANDLER( drmario_rom_banking )
{ {
const device_config *ppu1 = devtag_get_device(space->machine, "ppu1");
/* basically, a MMC1 mapper from the nes */ /* basically, a MMC1 mapper from the nes */
static int size16k, switchlow, vrom4k; static int size16k, switchlow, vrom4k;
@ -615,17 +780,17 @@ static WRITE8_HANDLER( drmario_rom_banking )
} }
/* apply mirroring */ /* apply mirroring */
ppu2c0x_set_mirroring( ppu1, mirroring ); v_set_mirroring(1, mirroring);
} }
break; break;
case 1: /* video rom banking - bank 0 - 4k or 8k */ 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; break;
case 2: /* video rom banking - bank 1 - 4k only */ case 2: /* video rom banking - bank 1 - 4k only */
if (vrom4k) if (vrom4k)
ppu2c0x_set_videorom_bank( ppu1, 4, 4, drmario_shiftreg, 256 ); v_set_videorom_bank(space->machine, 4, 4, drmario_shiftreg, 4);
break; break;
case 3: /* program banking */ case 3: /* program banking */
@ -682,7 +847,6 @@ DRIVER_INIT( drmario )
} }
/***********************************************************************/ /***********************************************************************/
/* Excite Bike */ /* Excite Bike */
DRIVER_INIT( excitebk ) DRIVER_INIT( excitebk )
@ -714,7 +878,6 @@ DRIVER_INIT( excitbkj )
} }
/**********************************************************************************/ /**********************************************************************************/
/* Mach Rider */ /* Mach Rider */
DRIVER_INIT( machridr ) DRIVER_INIT( machridr )
@ -733,7 +896,6 @@ DRIVER_INIT( machridr )
} }
/**********************************************************************************/ /**********************************************************************************/
/* VS Slalom */ /* VS Slalom */
DRIVER_INIT( vsslalom ) DRIVER_INIT( vsslalom )
@ -748,7 +910,6 @@ DRIVER_INIT( vsslalom )
} }
/**********************************************************************************/ /**********************************************************************************/
/* Castelvania: ROMs bankings at $8000-$ffff */ /* Castelvania: ROMs bankings at $8000-$ffff */
static WRITE8_HANDLER( castlevania_rom_banking ) static WRITE8_HANDLER( castlevania_rom_banking )
@ -775,10 +936,12 @@ DRIVER_INIT( cstlevna )
/* we need to remap color tables */ /* we need to remap color tables */
/* this *is* the VS games protection, I guess */ /* this *is* the VS games protection, I guess */
remapped_colortable = rp2c04002_colortable; remapped_colortable = rp2c04002_colortable;
/* allocate vram */
vram = auto_alloc_array(machine, UINT8, 0x2000);
} }
/**********************************************************************************/ /**********************************************************************************/
/* VS Top Gun: ROMs bankings at $8000-$ffff, plus some protection */ /* VS Top Gun: ROMs bankings at $8000-$ffff, plus some protection */
static READ8_HANDLER( topgun_security_r ) static READ8_HANDLER( topgun_security_r )
@ -802,6 +965,10 @@ DRIVER_INIT( topgun )
/* common init */ /* common init */
init_vsnes(machine); init_vsnes(machine);
/* allocate vram */
vram = auto_alloc_array(machine, UINT8, 0x2000);
} }
/**********************************************************************************/ /**********************************************************************************/
@ -832,14 +999,13 @@ static void mapper4_set_prg (const address_space *space)
static void mapper4_set_chr (const address_space *space) 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; UINT8 chr_page = (MMC3_cmd & 0x80) >> 5;
ppu2c0x_set_videorom_bank(ppu1, chr_page ^ 0, 2, MMC3_chr[0], 1); v_set_videorom_bank(space->machine, chr_page ^ 0, 2, MMC3_chr[0], 1);
ppu2c0x_set_videorom_bank(ppu1, chr_page ^ 2, 2, MMC3_chr[1], 1); v_set_videorom_bank(space->machine, chr_page ^ 2, 2, MMC3_chr[1], 1);
ppu2c0x_set_videorom_bank(ppu1, chr_page ^ 4, 1, MMC3_chr[2], 1); v_set_videorom_bank(space->machine, chr_page ^ 4, 1, MMC3_chr[2], 1);
ppu2c0x_set_videorom_bank(ppu1, chr_page ^ 5, 1, MMC3_chr[3], 1); v_set_videorom_bank(space->machine, chr_page ^ 5, 1, MMC3_chr[3], 1);
ppu2c0x_set_videorom_bank(ppu1, chr_page ^ 6, 1, MMC3_chr[4], 1); v_set_videorom_bank(space->machine, 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 ^ 7, 1, MMC3_chr[5], 1);
} }
#define BOTTOM_VISIBLE_SCANLINE 239 /* The bottommost visible scanline */ #define BOTTOM_VISIBLE_SCANLINE 239 /* The bottommost visible scanline */
@ -847,7 +1013,6 @@ static void mapper4_set_chr (const address_space *space)
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 ((scanline < BOTTOM_VISIBLE_SCANLINE) || (scanline == NUM_SCANLINE - 1))
{ {
if ((IRQ_enable) && !blanked) if ((IRQ_enable) && !blanked)
@ -889,13 +1054,13 @@ static WRITE8_HANDLER( mapper4_w )
{ {
case 0: case 1: case 0: case 1:
data &= 0xfe; data &= 0xfe;
MMC3_chr[cmd] = data * 64; MMC3_chr[cmd] = data;
mapper4_set_chr(space); mapper4_set_chr(space);
break; break;
case 2: case 3: case 4: case 5: case 2: case 3: case 4: case 5:
MMC3_chr[cmd] = data * 64; MMC3_chr[cmd] = data;
mapper4_set_chr(space); mapper4_set_chr(space);
break; break;
@ -914,13 +1079,13 @@ static WRITE8_HANDLER( mapper4_w )
} }
case 0x2000: /* $a000 */ case 0x2000: /* $a000 */
if (data & 0x40) if (data & 0x40)
ppu2c0x_set_mirroring(ppu1, PPU_MIRROR_HIGH); v_set_mirroring(1, PPU_MIRROR_HIGH);
else else
{ {
if (data & 0x01) if (data & 0x01)
ppu2c0x_set_mirroring(ppu1, PPU_MIRROR_HORZ); v_set_mirroring(1, PPU_MIRROR_HORZ);
else else
ppu2c0x_set_mirroring(ppu1, PPU_MIRROR_VERT); v_set_mirroring(1, PPU_MIRROR_VERT);
} }
break; break;
@ -1136,24 +1301,22 @@ DRIVER_INIT( vsfdf )
static WRITE8_HANDLER( mapper68_rom_banking ) static WRITE8_HANDLER( mapper68_rom_banking )
{ {
const device_config *ppu1 = devtag_get_device(space->machine, "ppu1");
switch (offset & 0x7000) switch (offset & 0x7000)
{ {
case 0x0000: case 0x0000:
ppu2c0x_set_videorom_bank(ppu1,0,2,data,128); v_set_videorom_bank(space->machine, 0, 2, data, 2);
break; break;
case 0x1000: case 0x1000:
ppu2c0x_set_videorom_bank(ppu1,2,2,data,128); v_set_videorom_bank(space->machine, 2, 2, data, 2);
break; break;
case 0x2000: case 0x2000:
ppu2c0x_set_videorom_bank(ppu1,4,2,data,128); v_set_videorom_bank(space->machine, 4, 2, data, 2);
break; break;
case 0x3000: /* ok? */ case 0x3000: /* ok? */
ppu2c0x_set_videorom_bank(ppu1,6,2,data,128); v_set_videorom_bank(space->machine, 6, 2, data, 2);
break; break;
@ -1249,7 +1412,6 @@ DRIVER_INIT( jajamaru )
} }
/***********************************************************************/ /***********************************************************************/
/* Vs. Mighty Bomb Jack */ /* Vs. Mighty Bomb Jack */
static READ8_HANDLER( mightybj_security_r ) static READ8_HANDLER( mightybj_security_r )
@ -1274,11 +1436,9 @@ DRIVER_INIT( mightybj )
static WRITE8_HANDLER( vstennis_vrom_banking ) 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 *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 */ /* 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 */ /* 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);
@ -1311,7 +1471,6 @@ DRIVER_INIT( vstennis )
DRIVER_INIT( wrecking ) DRIVER_INIT( wrecking )
{ {
/* only differance between this and vstennis is the colors */ /* only differance between this and vstennis is the colors */
DRIVER_INIT_CALL(vstennis); DRIVER_INIT_CALL(vstennis);
remapped_colortable = rp2c04002_colortable; remapped_colortable = rp2c04002_colortable;
} }
@ -1322,7 +1481,6 @@ DRIVER_INIT( wrecking )
DRIVER_INIT( balonfgt ) DRIVER_INIT( balonfgt )
{ {
/* only differance between this and vstennis is the colors */ /* only differance between this and vstennis is the colors */
DRIVER_INIT_CALL(vstennis); DRIVER_INIT_CALL(vstennis);
remapped_colortable = rp2c04003_colortable; remapped_colortable = rp2c04003_colortable;
@ -1335,11 +1493,9 @@ DRIVER_INIT( balonfgt )
DRIVER_INIT( vsbball ) DRIVER_INIT( vsbball )
{ {
/* only differance between this and vstennis is the colors */ /* only differance between this and vstennis is the colors */
DRIVER_INIT_CALL(vstennis); DRIVER_INIT_CALL(vstennis);
remapped_colortable = rp2c04001_colortable; remapped_colortable = rp2c04001_colortable;
} }
@ -1349,15 +1505,14 @@ DRIVER_INIT( vsbball )
DRIVER_INIT( iceclmrj ) DRIVER_INIT( iceclmrj )
{ {
/* only differance between this and vstennis is the colors */ /* only differance between this and vstennis is the colors */
DRIVER_INIT_CALL(vstennis); DRIVER_INIT_CALL(vstennis);
remapped_colortable = rp2c05004_colortable; remapped_colortable = rp2c05004_colortable;
} }
/**********************************************************************/ /**********************************************************************/
/* Battle City */ /* Battle City */
DRIVER_INIT( btlecity ) DRIVER_INIT( btlecity )
{ {
init_vsnes(machine); init_vsnes(machine);
@ -1367,6 +1522,7 @@ DRIVER_INIT( btlecity )
/***********************************************************************/ /***********************************************************************/
/* Tetris */ /* Tetris */
DRIVER_INIT( vstetris ) DRIVER_INIT( vstetris )
{ {
/* extra ram at $6000 is enabled with bit 1 of $4016 */ /* extra ram at $6000 is enabled with bit 1 of $4016 */

View File

@ -5,9 +5,8 @@
Written by Ernesto Corvi. Written by Ernesto Corvi.
This code is heavily based on Brad Oliver's MESS implementation. 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
@ -19,7 +18,6 @@ General:
NES-specific: NES-specific:
* Micro Machines has minor rendering glitches (needs better timing). * Micro Machines has minor rendering glitches (needs better timing).
* Mach Rider has minor road rendering glitches (needs better timing). * Mach Rider has minor road rendering glitches (needs better timing).
******************************************************************************/ ******************************************************************************/
@ -36,7 +34,7 @@ NES-specific:
/* constant definitions */ /* constant definitions */
#define VISIBLE_SCREEN_WIDTH (32*8) /* Visible screen width */ #define VISIBLE_SCREEN_WIDTH (32*8) /* Visible screen width */
#define VISIBLE_SCREEN_HEIGHT (30*8) /* Visible screen height */ #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 VIDEOMEM_PAGE_SIZE 0x400 /* videomem page size */
#define SPRITERAM_SIZE 0x100 /* spriteram size */ #define SPRITERAM_SIZE 0x100 /* spriteram size */
#define SPRITERAM_MASK (0x100-1) /* spriteram size */ #define SPRITERAM_MASK (0x100-1) /* spriteram size */
@ -113,6 +111,7 @@ typedef struct
int back_color; /* background color */ int back_color; /* background color */
UINT8 *ppu_page[4]; /* ppu pages */ UINT8 *ppu_page[4]; /* ppu pages */
int nes_vram[8]; /* keep track of 8 .5k vram pages to speed things up */ 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 scan_scale; /* scan scale */
int scanlines_per_frame; /* number of scanlines per frame */ int scanlines_per_frame; /* number of scanlines per frame */
int mirror_state; int mirror_state;
@ -120,7 +119,6 @@ typedef struct
} ppu2c0x_chip; } ppu2c0x_chip;
/*************************************************************************** /***************************************************************************
PROTOTYPES PROTOTYPES
***************************************************************************/ ***************************************************************************/
@ -133,6 +131,16 @@ static TIMER_CALLBACK( nmi_callback );
void (*ppu_latch)( const device_config *device, offs_t offset ); 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 FUNCTIONS
@ -167,6 +175,13 @@ INLINE const ppu2c0x_interface *get_interface(const device_config *device)
* PPU Palette Initialization * PPU Palette Initialization
* *
*************************************/ *************************************/
/* 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 ) void ppu2c0x_init_palette( running_machine *machine, int first_entry )
{ {
@ -302,9 +317,8 @@ static const gfx_layout ppu_charlayout =
static DEVICE_START( ppu2c0x ) static DEVICE_START( ppu2c0x )
{ {
UINT32 total;
ppu2c0x_chip *chip = get_token(device); 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)); memset(chip, 0, sizeof(*chip));
chip->scanlines_per_frame = (int) device_get_info_int(device, PPU2C0XINFO_INT_SCANLINES_PER_FRAME); 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 */ /* 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->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->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 = 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)); 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 );
} }
static TIMER_CALLBACK( hblank_callback ) static TIMER_CALLBACK( hblank_callback )
@ -413,22 +378,19 @@ static void draw_background(const device_config *device, UINT8 *line_priority )
const int *ppu_regs = &this_ppu->regs[0]; const int *ppu_regs = &this_ppu->regs[0];
const int scanline = this_ppu->scanline; const int scanline = this_ppu->scanline;
const int refresh_data = this_ppu->refresh_data; 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 *nes_vram = &this_ppu->nes_vram[0];
const int tile_page = this_ppu->tile_page; 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 back_pen;
UINT16 *dest; UINT16 *dest;
UINT8 scroll_x_coarse, scroll_y_coarse, scroll_y_fine, color_mask; 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 *color_table;
const pen_t *paldata; const pen_t *paldata;
const UINT8 *sd; // const UINT8 *sd;
int tilecount = 0; int tilecount = 0;
@ -474,17 +436,20 @@ static void draw_background(const device_config *device, UINT8 *line_priority )
index1 = tile_index + x; index1 = tile_index + x;
// this is attribute table stuff! (actually read 2 in PPUspeak)!
/* Figure out which byte in the color table to use */ /* 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; page = (index1 & 0x0c00) >> 10;
address = 0x3c0 + pos; 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 */ /* 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; address = index1 & 0x3ff;
page2 = ppu_page[page][address]; page2 = memory_read_byte(device->space[0], index1);
index2 = nes_vram[(page2 >> 6) | tile_page] + (page2 & 0x3f); index2 = nes_vram[(page2 >> 6) | tile_page] + (page2 & 0x3f);
// 27/12/2002 // 27/12/2002
@ -495,18 +460,35 @@ static void draw_background(const device_config *device, UINT8 *line_priority )
if (start_x < VISIBLE_SCREEN_WIDTH) if (start_x < VISIBLE_SCREEN_WIDTH)
{ {
UINT8 plane1, plane2; // use extended size so I can shift!
paldata = &color_table[4 * (((color_byte >> color_bits) & 0x03))]; paldata = &color_table[4 * (((color_byte >> color_bits) & 0x03))];
start = scroll_y_fine * line_modulo; // start = scroll_y_fine * line_modulo;
sd = gfx_element_get_data(device->machine->gfx[gfx_bank], index2 % total_elements) + start;
// 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 */ /* render the pixel */
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
{ {
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 ((start_x + i) >= 0 && (start_x + i) < VISIBLE_SCREEN_WIDTH)
{ {
if ( sd[i] )
if (pix)
{ {
pen = paldata[sd[i]]; pen = paldata[pix];
line_priority[start_x + i] |= 0x02; line_priority[start_x + i] |= 0x02;
} }
else else
@ -545,16 +527,13 @@ static void draw_background(const device_config *device, UINT8 *line_priority )
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); ppu2c0x_chip *this_ppu = get_token(device);
/* cache some values locally */ /* cache some values locally */
bitmap_t *bitmap = this_ppu->bitmap; bitmap_t *bitmap = this_ppu->bitmap;
const int scanline = this_ppu->scanline; 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 sprite_page = this_ppu->sprite_page;
const int line_modulo = device->machine->gfx[gfx_bank]->line_modulo;
const UINT8 *sprite_ram = this_ppu->spriteram; const UINT8 *sprite_ram = this_ppu->spriteram;
pen_t *color_table = this_ppu->colortable; pen_t *color_table = this_ppu->colortable;
int *ppu_regs = &this_ppu->regs[0]; int *ppu_regs = &this_ppu->regs[0];
@ -568,12 +547,11 @@ static void draw_sprites(const device_config *device, UINT8 *line_priority )
int spriteCount = 0; int spriteCount = 0;
int sprite_line; int sprite_line;
int drawn; int drawn;
int start;
int first_pixel; int first_pixel;
const pen_t *paldata; const pen_t *paldata;
const UINT8 *sd; // const UINT8 *sd;
int pixel; int pixel;
/* determine if the sprites are 8x8 or 8x16 */ /* determine if the sprites are 8x8 or 8x16 */
@ -583,6 +561,9 @@ static void draw_sprites(const device_config *device, UINT8 *line_priority )
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; spriteYPos = sprite_ram[spriteIndex] + 1;
spriteXPos = sprite_ram[spriteIndex + 3]; spriteXPos = sprite_ram[spriteIndex + 3];
@ -629,7 +610,7 @@ static void draw_sprites(const device_config *device, UINT8 *line_priority )
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) if (ppu_latch)
(*ppu_latch)(device, (sprite_page << 10) | ((tile & 0xff) << 4)); (*ppu_latch)(device, (sprite_page << 10) | ((tile & 0xff) << 4));
@ -637,22 +618,50 @@ static void draw_sprites(const device_config *device, UINT8 *line_priority )
/* compute the character's line to draw */ /* compute the character's line to draw */
sprite_line = scanline - spriteYPos; sprite_line = scanline - spriteYPos;
if (flipy) if (flipy)
sprite_line = (size - 1) - sprite_line; sprite_line = (size - 1) - sprite_line;
paldata = &color_table[4 * color]; 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 == 16 && sprite_line > 7)
if (size > 8) {
gfx_element_get_data(device->machine->gfx[gfx_bank], (index1 + 1) % total_elements); 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) if (pri)
{ {
/* draw the low-priority sprites */ /* 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? */ /* is this pixel non-transparent? */
if (spriteXPos + pixel >= first_pixel) if (spriteXPos + pixel >= first_pixel)
@ -681,10 +690,23 @@ static void draw_sprites(const device_config *device, UINT8 *line_priority )
else else
{ {
/* draw the high-priority sprites */ /* 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? */ /* is this pixel non-transparent? */
if (spriteXPos + pixel >= first_pixel) if (spriteXPos + pixel >= first_pixel)
@ -732,6 +754,7 @@ static void draw_sprites(const device_config *device, UINT8 *line_priority )
* Scanline Rendering and Update * 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); ppu2c0x_chip *this_ppu = get_token(device);
@ -825,9 +848,9 @@ static void update_scanline(const device_config *device)
int penNum; int penNum;
if (this_ppu->videomem_addr & 0x03) 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 else
penNum = this_ppu->videomem[this_ppu->videomem_addr & 0x3f00] & 0x3f; penNum = this_ppu->palette_ram[0];
back_pen = penNum + intf->color_base; back_pen = penNum + intf->color_base;
} }
@ -885,7 +908,7 @@ static TIMER_CALLBACK( scanline_callback )
/* Note: this is called at the _end_ of each scanline */ /* Note: this is called at the _end_ of each scanline */
if (this_ppu->scanline == PPU_VBLANK_FIRST_SCANLINE) if (this_ppu->scanline == PPU_VBLANK_FIRST_SCANLINE)
{ {
logerror("vlbank starting\n"); // logerror("vblank starting\n");
/* We just entered VBLANK */ /* We just entered VBLANK */
ppu_regs[PPU_STATUS] |= PPU_STATUS_VBLANK; ppu_regs[PPU_STATUS] |= PPU_STATUS_VBLANK;
@ -902,7 +925,7 @@ 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 */ /* 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);
} }
@ -995,10 +1018,58 @@ static DEVICE_RESET( ppu2c0x )
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
this_ppu->nes_vram[i] = i * 64; this_ppu->nes_vram[i] = i * 64;
if ( this_ppu->has_videorom ) // if (this_ppu->has_videorom)
ppu2c0x_set_videorom_bank( device, 0, 8, 0, 512 ); // 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);
}
}
/************************************* /*************************************
* *
@ -1037,22 +1108,20 @@ READ8_DEVICE_HANDLER( ppu2c0x_r )
break; break;
case PPU_DATA: case PPU_DATA:
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;
}
else
this_ppu->data_latch = this_ppu->buffered_data;
if (ppu_latch) if (ppu_latch)
(*ppu_latch)(device, this_ppu->videomem_addr & 0x3fff); (*ppu_latch)(device, this_ppu->videomem_addr & 0x3fff);
if ( ( this_ppu->videomem_addr >= 0x2000 ) && ( this_ppu->videomem_addr <= 0x3fff ) ) if (this_ppu->videomem_addr >= 0x3f00)
this_ppu->buffered_data = this_ppu->ppu_page[ ( this_ppu->videomem_addr & 0xc00) >> 10][ this_ppu->videomem_addr & 0x3ff ]; {
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 else
this_ppu->buffered_data = this_ppu->videomem[ this_ppu->videomem_addr & 0x3fff ]; {
this_ppu->data_latch = this_ppu->buffered_data;
this_ppu->buffered_data = memory_read_byte(device->space[0], this_ppu->videomem_addr);
}
this_ppu->videomem_addr += this_ppu->add; this_ppu->videomem_addr += this_ppu->add;
break; break;
@ -1117,7 +1186,7 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w )
int i; int i;
for (i = 0; i <= 0x1f; 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;
} }
@ -1207,60 +1276,17 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w )
else else
{ {
/* store the data */ /* store the data */
this_ppu->videomem[tempAddr] = data; memory_write_byte(device->space[0], tempAddr, data);
/* mark the char dirty */ /* 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 else
{ {
this_ppu->videomem[0x3F10+(tempAddr&0xF)] = data; memory_write_byte(device->space[0], tempAddr, 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;
}
/* increment the address */ /* increment the address */
this_ppu->videomem_addr += this_ppu->add; this_ppu->videomem_addr += this_ppu->add;
} }
@ -1277,6 +1303,7 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w )
* Sprite DMA * 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 i;
@ -1286,7 +1313,8 @@ void ppu2c0x_spriteram_dma (const address_space *space, const device_config *dev
for (i = 0; i < SPRITERAM_SIZE; i++) for (i = 0; i < SPRITERAM_SIZE; i++)
{ {
UINT8 spriteData = memory_read_byte(space, address + 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. // should last 513 CPU cycles.
@ -1317,97 +1345,6 @@ void ppu2c0x_render( const device_config *device, bitmap_t *bitmap, int flipx, i
copybitmap(bitmap, this_ppu->bitmap, flipx, flipy, sx, sy, 0); 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 );
}
}
/************************************* /*************************************
* *
* Utility functions * Utility functions
@ -1439,60 +1376,6 @@ int ppu2c0x_get_current_scanline( const device_config *device )
return this_ppu->scanline; 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 ) void ppu2c0x_set_scanline_callback( const device_config *device, ppu2c0x_scanline_cb cb )
{ {
ppu2c0x_chip *this_ppu = get_token(device); 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_INLINE_CONFIG_BYTES: info->i = 0; break;
case DEVINFO_INT_CLASS: info->i = DEVICE_CLASS_PERIPHERAL; 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 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 --- */ /* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ppu2c0x); break; case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ppu2c0x); break;

View File

@ -109,14 +109,11 @@ DEVICE_GET_INFO(ppu2c07);
/* routines */ /* routines */
void ppu2c0x_init_palette(running_machine *machine, int first_entry ) ATTR_NONNULL(1); 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_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); 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_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_colorbase( const device_config *device ) ATTR_NONNULL(1);
int ppu2c0x_get_current_scanline( 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_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_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); void ppu2c0x_set_vidaccess_callback( const device_config *device, ppu2c0x_vidaccess_cb cb ) ATTR_NONNULL(1);