mirror of
https://github.com/holub/mame
synced 2025-05-24 14:56:21 +03:00
Improved Sprite Overflow emulation of NES PPU (this fixes the first of blargg's Sprite Overflow tests) [Robert Bohms]
This commit is contained in:
parent
cd932c1c27
commit
b63f9602f0
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user