In many games like Ghosts & Goblins, there are sprite glitches on edges. They basically sometimes disappear on the right and sometimes on the left.
But in Tom & Jerry,
https://www.youtube.com/watch?v=TwsVhA-Uh_g if you run it in an emulator, you can see that the 8 pixels on the right and left hide the background and sprites so that these glitches don't appear.
How is that implemented? Is it implemented by the mapper, by PPU settings, by perfect PPU timing or what?
Alfred Chicken has a strip of all-black sprites down the right side of the screen. It reduces the effective sprite limit to 7 per line though, and with 8x16 pixel sprites, it eats up about one-fifth of OAM space depending on the height of the status bar.
The PPU hides the left 8 pixels of the screen when bits 2 and 3 of PPUMASK are set to 0.
The PPU can optionally not render sprites and/or the background in the leftmost 8 pixels of the screen, effectively reducing the horizontal resolution from 256 to 248 pixels, and allowing sprites to smoothly enter and leave the screen on that side. Sprites will still "pop" at the top of the screen though, unless the programmer manually masks the topmost 8 (or 16!) scanlines, like Jurassic Park does.
Depending on how the background is set up, scrolling can cause background glitches near the edges of the screen too. Jurassic Park hides scanlines at the top and bottom to avoid these glitches, while Felix the Cat and Alfred Chicken, which use a different background setup, use a column of sprites to hide scrolling glitches at the right edge of the screen.
Most games with multi-directional scrolling (and even some uni-directinal ones, such as some of the Mega Man games), simply don't do anything about these glitches, though.
EDIT: It's also worth noting that many emulators mask the top and bottom 8 scanlines by default (if you want to see those lines you have to go to the video settings and set the first scanline to 0 and the last one to 239), since many games have glitches in those areas. Many videos of NES games on YouTube are cropped like this for this reason. This makes it seem like many games that have scrolling glitches don't, and also propagates the misconception that 224 scanlines is a valid vertical resolution on the NES.
In SMB1, sprites only clip on left side, but they don't pop on the right side. Is this the default behavior?
Sprite pop-in on the left side is normal because horizontal coordinates cannot be negative. The window bits of $2001 exist to hide this. Sprites can, however, be partly off the right side of the screen. The Alfred Chicken technique is mostly about hiding attribute glitches that are otherwise unavoidable when you scroll horizontally with 1-screen or horizontal mirroring.
Yes, because a sprite's coordinates are relative to its top left corner. A horizontal coordinate of 0 will make the left side of the sprite touch the left edge of the screen, and since coordinates can't be negative, that's as far as sprites can go to the left. As for the right side, a coordinate of 248 will make the right side of the sprite touch the right edge of the screen (since sprites are 8 pixels wide), but the coordinate can still go all the way to 255, allowing the sprite to smoothly leave the screen.
Just to clarify, since nobody said it explicitly, Tom & Jerry uses the first 15 sprites (8 x 16 with black tiles) to hide the right side of the screen, like Alfred Chicken or Felix the Cat.
Technically the way it does scrolling it has attribute glitch on the top area of the screen as well, but this is cut off on NTSC TVs.
There are a lot of games that also do the same thing. For example, Zelda II (Overworld map) and Clash at Demonhead also use sprites to mask out the right column.
tokumaru wrote:
This makes it seem like many games that have scrolling glitches don't, and also propagates the misconception that 224 scanlines is a valid vertical resolution on the NES.
For this reason, one of the first things I always do is set that to 0-239.
8bitMicroGuy wrote:
In many games like Ghosts & Goblins, there are sprite glitches on edges. They basically sometimes disappear on the right and sometimes on the left.
On the left side the sprite glitches can be hidden by setting the 8px mask (as discussed). On the right side there's no need to do anything, per se. The reason you might see sprites disappearing prematurely on the right side in Ghosts & Goblins and other games comes down to the way the game engine has been written. For example, it might hide objects as soon as their center-point goes outside the screen boundaries. In this case it's not a hardware but an engine limitation.
So if any sprite's X coordinate is greater than $F8, that sprite should get removed?
Code:
ldx #$03
loop:
lda $0200, x
cmp #$F8
bmi skip
lda #$F0
sta $0200, x
skip:
txa
clc
adc #$04
tax
cpx #$03
bne loop
Why would you create such an artificial limitation if sprite coordinates can very well go up to 255?
I guess so as not to display useless sprites behind the column of solid sprites that you're using to hide attribute glitches, as a means of controlling the damage that a 7-sprite limit causes.
While removing sprites from the 8 rightmost columns could potentially reduce 8-per-line limitations, some suggestions about the code posted:
1. Erroneously uses bmi instead of bcc. The test for an unsigned comparison should use carry. (As is, will operate on any sprites on 50% of the screen.)
2. Doesn't remove the sprites, it shifts them to X=$F0. I think the intention was to do that for Y. (Probably wanted sta $1FD, X instead?)
3. If you were using a column of sprites at $F8 to hide the right most 8 pixels, you would have to omit them from this sprite removal pass, or they'd get eliminated by this code.
4. It would be better to prevent them from being added in the first place by your metasprite routines instead of removing them in a later pass like this.
5. The sequence txa clc adc #4 tax could be replaced by inx inx inx inx for a savings of one byte.
6. Instead of starting X at 3, you could begin at 0 and instead use lda $203, X to read from the array. This would let you skip the cpx #3 after incrementing.
I see now. But maybe I could dynamically mask out the last 8 pixels of any sprite that goes there. ... that wouldn't work.
Or maybe I could dynamically set the mask bit in the PPU register according to which sprite is going where. So if there's a sprite exiting on the left, the bit is switched to not mask so that the sprite can be seen exiting out on the left side. But if there is a sprite exiting on the right, the bit is switched to mask so that the sprite can be seen exiting out on the right side. Would this work?