More NES work: [Robert Bohms]

* Fixes bug in nes_apu that caused errors reading $4015
* Adds length counter status bits to $4015
* Fixes 4-screen mirroring (PPU regression)
* Fixed cham24

Also, I fixed the tab lengths in nes_apu.c
This commit is contained in:
Fabio Priuli 2009-08-06 10:58:38 +00:00
parent 1934fb76af
commit 80f73ab376
4 changed files with 506 additions and 511 deletions

View File

@ -546,6 +546,10 @@ INLINE void apu_regwrite(nesapu_state *info,int address, uint8 value)
break; break;
case APU_IRQCTRL: case APU_IRQCTRL:
if(value & 0x80)
info->APU.step_mode = 5;
else
info->APU.step_mode = 4;
break; break;
case APU_SMASK: case APU_SMASK:
@ -633,18 +637,27 @@ INLINE void apu_update(nesapu_state *info, stream_sample_t *buffer16, int sample
/* READ VALUES FROM REGISTERS */ /* READ VALUES FROM REGISTERS */
INLINE uint8 apu_read(nesapu_state *info,int address) INLINE uint8 apu_read(nesapu_state *info,int address)
{ {
if (address == 0x0f) /*FIXED* Address $4015 has different behaviour*/ if (address == 0x15) /*FIXED* Address $4015 has different behaviour*/
{ {
int readval = 0; int readval = 0;
if (info->APU.squ[0].vbl_length > 0)
readval |= 0x01;
if (info->APU.squ[1].vbl_length > 0)
readval |= 0x02;
if (info->APU.tri.vbl_length > 0)
readval |= 0x04;
if (info->APU.noi.vbl_length > 0)
readval |= 0x08;
if (info->APU.dpcm.enabled == TRUE) if (info->APU.dpcm.enabled == TRUE)
{
readval |= 0x10; readval |= 0x10;
}
if (info->APU.dpcm.irq_occurred == TRUE) if (info->APU.dpcm.irq_occurred == TRUE)
{
readval |= 0x80; readval |= 0x80;
}
return readval; return readval;
} }
else else
@ -753,6 +766,7 @@ static DEVICE_START( nesapu )
state_save_register_device_item(device, 0, info->APU.tail); state_save_register_device_item(device, 0, info->APU.tail);
#else #else
state_save_register_device_item(device, 0, info->APU.buf_pos); state_save_register_device_item(device, 0, info->APU.buf_pos);
state_save_register_device_item(device, 0, info->APU.step_mode);
#endif #endif
} }

View File

@ -168,6 +168,7 @@ typedef struct apu
#endif #endif
int step_mode;
} apu_t; } apu_t;
/* CONSTANTS */ /* CONSTANTS */

View File

@ -244,12 +244,6 @@ static const nes_interface cham24_interface_1 =
static MACHINE_RESET( cham24 ) static MACHINE_RESET( cham24 )
{ {
/* switch PRG rom */
UINT8* dst = memory_region(machine, "maincpu");
UINT8* src = memory_region(machine, "user1");
memcpy(&dst[0x8000], &src[0x0f8000], 0x4000);
memcpy(&dst[0xc000], &src[0x0f8000], 0x4000);
} }
static PALETTE_INIT( cham24 ) static PALETTE_INIT( cham24 )
@ -282,8 +276,16 @@ static VIDEO_UPDATE( cham24 )
return 0; return 0;
} }
static DRIVER_INIT( cham24 )
static MACHINE_START( cham24 )
{ {
/* switch PRG rom */
UINT8* dst = memory_region(machine, "maincpu");
UINT8* src = memory_region(machine, "user1");
memcpy(&dst[0x8000], &src[0x0f8000], 0x4000);
memcpy(&dst[0xc000], &src[0x0f8000], 0x4000);
/* uses 8K swapping, all ROM!*/ /* 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_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")); memory_set_bankptr(machine, 1, memory_region(machine, "gfx1"));
@ -299,6 +301,10 @@ static DRIVER_INIT( cham24 )
memory_install_readwrite8_handler(cpu_get_address_space(cputag_get_cpu(machine, "ppu"), ADDRESS_SPACE_PROGRAM), 0x2000, 0x3eff, 0, 0, nt_r, nt_w); 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 DRIVER_INIT( cham24 )
{
}
static GFXDECODE_START( cham24 ) static GFXDECODE_START( cham24 )
/* none, the ppu generates one */ /* none, the ppu generates one */
GFXDECODE_END GFXDECODE_END
@ -309,6 +315,7 @@ static MACHINE_DRIVER_START( cham24 )
MDRV_CPU_PROGRAM_MAP(cham24_map) MDRV_CPU_PROGRAM_MAP(cham24_map)
MDRV_MACHINE_RESET( cham24 ) MDRV_MACHINE_RESET( cham24 )
MDRV_MACHINE_START( cham24 )
/* video hardware */ /* video hardware */
MDRV_SCREEN_ADD("screen", RASTER) MDRV_SCREEN_ADD("screen", RASTER)

View File

@ -19,6 +19,7 @@
* 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).
* Rad Racer demonstrates road glitches: it changes horizontal scrolling mid-line.
******************************************************************************/ ******************************************************************************/
@ -380,7 +381,6 @@ static void draw_background( const device_config *device, UINT8 *line_priority )
const pen_t *color_table; const pen_t *color_table;
const pen_t *paldata; const pen_t *paldata;
// const UINT8 *sd;
int tilecount = 0; int tilecount = 0;
@ -447,19 +447,16 @@ 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! UINT8 plane1, plane2;
paldata = &color_table[4 * (((color_byte >> color_bits) & 0x03))]; paldata = &color_table[4 * (((color_byte >> color_bits) & 0x03))];
// start = scroll_y_fine * line_modulo;
// need to read 0x0000 or 0x1000 + 16*nametable data // need to read 0x0000 or 0x1000 + 16*nametable data
address = ((this_ppu->tile_page) ? 0x1000 : 0) + (page2 * 16); address = ((this_ppu->tile_page) ? 0x1000 : 0) + (page2 * 16);
// plus something that accounts for y // plus something that accounts for y
// address -= (scanline % 8);
address += scroll_y_fine; address += scroll_y_fine;
plane1 = memory_read_byte(device->space[0], (address & 0x1fff)); plane1 = memory_read_byte(device->space[0], (address & 0x1fff));
plane2 = memory_read_byte(device->space[0], (address + 8) & 0x1fff); plane2 = memory_read_byte(device->space[0], (address + 8) & 0x1fff);
// plane2 = plane2 << 1;
/* render the pixel */ /* render the pixel */
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
@ -618,30 +615,23 @@ static void draw_sprites( const device_config *device, UINT8 *line_priority )
plane1 = memory_read_byte(device->space[0], (index1 + sprite_line) & 0x1fff); plane1 = memory_read_byte(device->space[0], (index1 + sprite_line) & 0x1fff);
plane2 = memory_read_byte(device->space[0], (index1 + sprite_line + 8) & 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; UINT8 pixelData;
if (flipx) if (flipx)
{ {
pixelData = (plane1 & 1) + ((plane2 & 1) << 1); pixelData = (plane1 & 1) + ((plane2 & 1) << 1);
plane1 = plane1 >> 1; plane1 = plane1 >> 1;
plane2 = plane2 >> 1; plane2 = plane2 >> 1;
// sd[7 - pixel]
} }
else else
{ {
pixelData = ((plane1 >> 7) & 1) | (((plane2 >> 7) & 1) << 1); pixelData = ((plane1 >> 7) & 1) | (((plane2 >> 7) & 1) << 1);
plane1 = plane1 << 1; plane1 = plane1 << 1;
plane2 = plane2 << 1; plane2 = plane2 << 1;
// sd[pixel];
} }
/* is this pixel non-transparent? */ /* is this pixel non-transparent? */
@ -1037,11 +1027,11 @@ READ8_HANDLER( ppu2c0x_palette_read )
{ {
ppu2c0x_chip *this_ppu = get_token(space->cpu); 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) if (this_ppu->regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO)
return (this_ppu->palette_ram[offset & 0x1f] & 0x30); return (this_ppu->palette_ram[offset & 0x1f] & 0x30);
else return (this_ppu->palette_ram[offset & 0x1f] & 0x3f);
else
return (this_ppu->palette_ram[offset & 0x1f] & 0x3f);
} }
} }
@ -1242,9 +1232,6 @@ WRITE8_DEVICE_HANDLER( ppu2c0x_w )
{ {
/* store the data */ /* store the data */
memory_write_byte(device->space[0], tempAddr, data); memory_write_byte(device->space[0], tempAddr, data);
/* mark the char dirty */
// gfx_element_mark_dirty(device->machine->gfx[intf->gfx_layout_number], tempAddr >> 4);
} }
else else
@ -1273,28 +1260,14 @@ void ppu2c0x_spriteram_dma( const address_space *space, const device_config *dev
int i; int i;
int address = page << 8; int address = page << 8;
// logerror("sprite DMA: %d (scanline: %d)\n", page, this_ppu->scanline);
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);
memory_write_byte(space, 0x2004, spriteData); memory_write_byte(space, 0x2004, spriteData);
// ppu2c0x_w(device, PPU_SPRITE_DATA, spriteData);
} }
// should last 513 CPU cycles. // should last 513 CPU cycles.
cpu_adjust_icount(space->cpu, -513); cpu_adjust_icount(space->cpu, -513);
// ????TODO : need to account for PPU rendering - this is roughly 4.5 scanlines eaten up.
// Because the DMA is only useful during vblank, this may not be strictly necessary since
// the scanline timers should catch us up before drawing actually happens.
#if 0
{
scanline_callback(device);
scanline_callback(device);
scanline_callback(device);
scanline_callback(device);
}
#endif
} }
/************************************* /*************************************