Improved Sprite Overflow emulation of NES PPU (this fixes the first of blargg's Sprite Overflow tests) [Robert Bohms]

This commit is contained in:
Fabio Priuli 2009-08-09 06:30:36 +00:00
parent cd932c1c27
commit b63f9602f0

View File

@ -527,12 +527,10 @@ static void draw_sprites( const device_config *device, UINT8 *line_priority )
int size; int size;
int spriteCount = 0; int spriteCount = 0;
int sprite_line; int sprite_line;
int drawn;
int first_pixel; int first_pixel;
const pen_t *paldata; const pen_t *paldata;
// const UINT8 *sd;
int pixel; int pixel;
/* determine if the sprites are 8x8 or 8x16 */ /* determine if the sprites are 8x8 or 8x16 */
@ -567,9 +565,6 @@ static void draw_sprites( const device_config *device, UINT8 *line_priority )
if ((spriteYPos + size <= scanline) || (spriteYPos > scanline)) if ((spriteYPos + size <= scanline) || (spriteYPos > scanline))
continue; continue;
/* clear our drawn flag */
drawn = 0;
tile = sprite_ram[spriteIndex + 1]; tile = sprite_ram[spriteIndex + 1];
color = (sprite_ram[spriteIndex + 2] & 0x03) + 4; color = (sprite_ram[spriteIndex + 2] & 0x03) + 4;
pri = sprite_ram[spriteIndex + 2] & 0x20; pri = sprite_ram[spriteIndex + 2] & 0x20;
@ -596,7 +591,6 @@ 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;
@ -615,6 +609,22 @@ 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);
/* if there are more than 8 sprites on this line, set the flag */
if (spriteCount == 8)
{
ppu_regs[PPU_STATUS] |= PPU_STATUS_8SPRITES;
// logerror ("> 8 sprites, scanline: %d\n", scanline);
/* the real NES only draws up to 8 sprites - the rest should be invisible */
break;
}
spriteCount++;
/* abort drawing if sprites aren't rendered */
if (!(ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_SPRITES))
continue;
if (pri) if (pri)
{ {
/* draw the low-priority sprites */ /* draw the low-priority sprites */
@ -645,7 +655,6 @@ static void draw_sprites( const device_config *device, UINT8 *line_priority )
/* no, draw */ /* no, draw */
if ((spriteXPos + pixel) < VISIBLE_SCREEN_WIDTH) if ((spriteXPos + pixel) < VISIBLE_SCREEN_WIDTH)
*BITMAP_ADDR16(bitmap, scanline, spriteXPos + pixel) = paldata[pixelData]; *BITMAP_ADDR16(bitmap, scanline, spriteXPos + pixel) = paldata[pixelData];
drawn = 1;
} }
/* indicate that a sprite was drawn at this location, even if it's not seen */ /* indicate that a sprite was drawn at this location, even if it's not seen */
if ((spriteXPos + pixel) < VISIBLE_SCREEN_WIDTH) if ((spriteXPos + pixel) < VISIBLE_SCREEN_WIDTH)
@ -669,14 +678,12 @@ static void draw_sprites( const device_config *device, UINT8 *line_priority )
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? */
@ -693,7 +700,6 @@ static void draw_sprites( const device_config *device, UINT8 *line_priority )
*BITMAP_ADDR16(bitmap, scanline, spriteXPos + pixel) = paldata[pixelData]; *BITMAP_ADDR16(bitmap, scanline, spriteXPos + pixel) = paldata[pixelData];
line_priority[spriteXPos + pixel] |= 0x01; line_priority[spriteXPos + pixel] |= 0x01;
} }
drawn = 1;
} }
} }
@ -703,20 +709,6 @@ static void draw_sprites( const device_config *device, UINT8 *line_priority )
} }
} }
} }
if (drawn)
{
/* if there are more than 8 sprites on this line, set the flag */
spriteCount++;
if (spriteCount == 8)
{
ppu_regs[PPU_STATUS] |= PPU_STATUS_8SPRITES;
// logerror ("> 8 sprites, scanline: %d\n", scanline);
/* the real NES only draws up to 8 sprites - the rest should be invisible */
break;
}
}
} }
} }
@ -739,9 +731,6 @@ static void render_scanline( const device_config *device )
/* clear the line priority for this scanline */ /* clear the line priority for this scanline */
memset(line_priority, 0, VISIBLE_SCREEN_WIDTH); memset(line_priority, 0, VISIBLE_SCREEN_WIDTH);
/* clear the sprite count for this line */
ppu_regs[PPU_STATUS] &= ~PPU_STATUS_8SPRITES;
/* see if we need to render the background */ /* see if we need to render the background */
if (ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_BACKGROUND) if (ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_BACKGROUND)
draw_background(device, line_priority); draw_background(device, line_priority);
@ -767,9 +756,8 @@ static void render_scanline( const device_config *device )
*BITMAP_ADDR16(bitmap, scanline, i) = back_pen; *BITMAP_ADDR16(bitmap, scanline, i) = back_pen;
} }
/* if sprites are on, draw them */ /* if sprites are on, draw them, but we call always to process them */
if (ppu_regs[PPU_CONTROL1] & PPU_CONTROL1_SPRITES) draw_sprites(device, line_priority);
draw_sprites(device, line_priority);
/* done updating, whew */ /* done updating, whew */
profiler_mark(PROFILER_END); profiler_mark(PROFILER_END);
@ -898,7 +886,7 @@ static TIMER_CALLBACK( scanline_callback )
{ {
// logerror("vblank 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 | PPU_STATUS_8SPRITES);
} }
/* see if we rolled */ /* see if we rolled */