Rogue pixels
Moderator: Moderators
Rogue pixels
Hi all
I've been banging my head against this problem for a few days with no luck, so I'm hoping one of you guys could help me out. I'm a newbie NES programmer and I'm using ASM6 and 6502 assembly.
So far, I've done the Nerdy Nights tutorials and am trying my hand at my own game. I've got everything pretty much working and I even managed to integrate the GGSound engine without too much trouble. I added the examples from the https://wiki.nesdev.com/w/index.php/The_frame_and_NMIs page but now I have rogue pixels at the top left of my screen and I can't figure out where they're coming from.
I've moved the scroll values around and tried turning off the background, palette, sprites, etc. Turning off the palette blanks the screen so it's hard to tell if it's still there.
You can see it as red, white, and grey pixels at the top left.
Here's the basics of my code. Let me know if you need to see more. It's really just a framework with some custom and placeholder sprites.
I've been banging my head against this problem for a few days with no luck, so I'm hoping one of you guys could help me out. I'm a newbie NES programmer and I'm using ASM6 and 6502 assembly.
So far, I've done the Nerdy Nights tutorials and am trying my hand at my own game. I've got everything pretty much working and I even managed to integrate the GGSound engine without too much trouble. I added the examples from the https://wiki.nesdev.com/w/index.php/The_frame_and_NMIs page but now I have rogue pixels at the top left of my screen and I can't figure out where they're coming from.
I've moved the scroll values around and tried turning off the background, palette, sprites, etc. Turning off the palette blanks the screen so it's hard to tell if it's still there.
You can see it as red, white, and grey pixels at the top left.
Here's the basics of my code. Let me know if you need to see more. It's really just a framework with some custom and placeholder sprites.
- Attachments
-
- subroutines.asm
- subroutines
- (6.26 KiB) Downloaded 122 times
-
- rogue.asm
- main file
- (5.25 KiB) Downloaded 120 times
Re: Rogue pixels
Does it still happen when you render the background, but not sprites? My first guess is "sprites.spr" is not long enough, or has errors.
My second guess is something similar with rogue.nam.
The longshot:
Behold, the way to draw all the colors on the screen at once: https://wiki.nesdev.com/w/index.php/Full_palette_demo
Another potential issue is a negative scroll value for Y, but similarly I can't see anything that would cause that except RAM collisions here.
My second guess is something similar with rogue.nam.
The longshot:
Behold, the way to draw all the colors on the screen at once: https://wiki.nesdev.com/w/index.php/Full_palette_demo
But the only way I can see that happening in the code you posted is if the sound engine wasn't set up to use unique RAM.Normally, the PPU displays the palette byte from $3F00 as the background color. When rendering is disabled and the PPU address is in the $3F00-$3FFF range, the PPU displays the palette byte at that address.
Another potential issue is a negative scroll value for Y, but similarly I can't see anything that would cause that except RAM collisions here.
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Rogue pixels
If you would post an NES ROM as well, it would be very easy to tell what is causing any visual element that appears with a good debugging emulator (Mesen, FCEUX, Nintendulator, etc.)
The assembly files are helpful as well for diagnosing a problem, but it's much easier to just check what the ROM is actually doing than either try to reason about what a bunch of code does.
The assembly files are helpful as well for diagnosing a problem, but it's much easier to just check what the ROM is actually doing than either try to reason about what a bunch of code does.
Last edited by rainwarrior on Mon Mar 19, 2018 11:16 pm, edited 1 time in total.
Re: Rogue pixels
Top left is usually sprites that haven't been properly pushed off the screen (by setting a y value >= $f0).
If a sprite entry is left as 0,0,0,0 it will draw the #0 tile at position 0,0 (top left) using palette #0.
I'm guessing you have video settings at the default with top and bottom 8 pixels hidden.
Sprites show up 1 pixel lower on the screen, which is why you would see the bottom 8x1 slice of the sprite only. (top 8 pixels hidden, sprites shifted down 1 = 7 hidden and 1 visible).
If a sprite entry is left as 0,0,0,0 it will draw the #0 tile at position 0,0 (top left) using palette #0.
I'm guessing you have video settings at the default with top and bottom 8 pixels hidden.
Sprites show up 1 pixel lower on the screen, which is why you would see the bottom 8x1 slice of the sprite only. (top 8 pixels hidden, sprites shifted down 1 = 7 hidden and 1 visible).
nesdoug.com -- blog/tutorial on programming for the NES
Re: Rogue pixels
Also, as a developer, it's a good idea to configure your emulators to display all 240 scanlines (some emulators hide the top and bottom 8 scanlines by default, because some games have glitches in those areas and real TVs tend to hide some of those scanlines too), so you can see the whole picture your code is producing and detect problems that maybe you wouldn't notice otherwise.
Re: Rogue pixels
There's almost a 100% chance this is it. There is actually not a lot of newbie-friendly documentation out there about how to "disable" sprites, even though it should be obvious once you think about it. The NES hardware always renders 64 sprites, wether you want it or not. You can use invisible tiles, etc. for sprites you don't want the player to see, but by far the best and easiest solution is to simply push every unused sprite out of the visible area by setting the Y coordinate to something higher than 240 pixels (where you don't have to worry about the 8 sprites on a scanline limit either).dougeff wrote:Top left is usually sprites that haven't been properly pushed off the screen (by setting a y value >= $f0).
If a sprite entry is left as 0,0,0,0 it will draw the #0 tile at position 0,0 (top left) using palette #0.
I'm assuming you're copying a full object table from a "sprite buffer" every NMI, so a good cause of this issue could be that you simply have a bunch of zeroes in your unused part of the RAM buffer, which places sprites in the top left corner like dougeff describes. A lazy way to initialize your sprite buffer if just to write $ff to every byte, but you also want to clear out unused sprites every single frame, so you don't leave old garbage ones hanging around.
Re: Rogue pixels
Actually using 239 ($ef) or 240 ($f0) works too. (239 works because sprites are one pixel lower than the coordinate which is used in OAM).Sumez wrote:by far the best and easiest solution is to simply push every unused sprite out of the visible area by setting the Y coordinate to something higher than 240 pixels (where you don't have to worry about the 8 sprites on a scanline limit either).
Re: Rogue pixels
You guys were totally right. You guys are awesome. Cheers!
I had originally zero filled my sprite table thinking that was the way to go. I went back and replaced everything but the onscreen sprites with $EF and that fixed it. And now I realize why just turning off my sprite drawing routine was also causing the error since the PPU memory would still be zero when I turned sprites on.
I've included the fixed rom file and source if anyone wants to check it out. Deconstructing source and rom has really helped me fill in the gaps between the tutorials and actually making a game so I'm hoping someone finds it useful.
You've also cleared up why setting my initial yscroll value to #$08 was the only way to get the screen to show properly.
I've been using FCEUX as an emulator. Is there any way to see the PPU memory values?
Next up is actually figuring out how to store, unpack, and display levels.
I had originally zero filled my sprite table thinking that was the way to go. I went back and replaced everything but the onscreen sprites with $EF and that fixed it. And now I realize why just turning off my sprite drawing routine was also causing the error since the PPU memory would still be zero when I turned sprites on.
I've included the fixed rom file and source if anyone wants to check it out. Deconstructing source and rom has really helped me fill in the gaps between the tutorials and actually making a game so I'm hoping someone finds it useful.
You've also cleared up why setting my initial yscroll value to #$08 was the only way to get the screen to show properly.
I've been using FCEUX as an emulator. Is there any way to see the PPU memory values?
Next up is actually figuring out how to store, unpack, and display levels.
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Rogue pixels
FCEUX has an OAM (sprite memory) page in the hex editor, but it's not in the last release version (have to use a development build).
You can also use LUA scripts to help visualize where the sprites are (see included "sprites.lua", though tokumaru also wrote a really nice one).
However, Mesen and Nintendulator have dedicated OAM viewer tools which do a much better job of this, with good visual display of information.
FWIW, a lot of commercial era NES games put a value of "-8" into the Y scroll for more convenient alignment with the commonly visible picture. You could do this either with 232 (240-8) or 248 (256-8), though the latter causes garbage to appear in the extra row. You can see this in TMNT, for example, if you tell your emulator to show you the whole picture instead of cropping lines from the top and bottom.
You can also use LUA scripts to help visualize where the sprites are (see included "sprites.lua", though tokumaru also wrote a really nice one).
However, Mesen and Nintendulator have dedicated OAM viewer tools which do a much better job of this, with good visual display of information.
FWIW, a lot of commercial era NES games put a value of "-8" into the Y scroll for more convenient alignment with the commonly visible picture. You could do this either with 232 (240-8) or 248 (256-8), though the latter causes garbage to appear in the extra row. You can see this in TMNT, for example, if you tell your emulator to show you the whole picture instead of cropping lines from the top and bottom.
Re: Rogue pixels
Great suggestions. I've downloaded both of them and the tools work great. One question though: the palette colors look way different from FCEUX. I know simulating CRT rendering isn't exact, but are there different approaches to approximating it?rainwarrior wrote:FCEUX has an OAM (sprite memory) page in the hex editor, but it's not in the last release version (have to use a development build).
You can also use LUA scripts to help visualize where the sprites are (see included "sprites.lua", though tokumaru also wrote a really nice one).
However, Mesen and Nintendulator have dedicated OAM viewer tools which do a much better job of this, with good visual display of information.
I'm still trying to wrap my head around this. Do you mean treating y-scroll value as a signed int? Or wrapping around?rainwarrior wrote:FWIW, a lot of commercial era NES games put a value of "-8" into the Y scroll for more convenient alignment with the commonly visible picture. You could do this either with 232 (240-8) or 248 (256-8), though the latter causes garbage to appear in the extra row. You can see this in TMNT, for example, if you tell your emulator to show you the whole picture instead of cropping lines from the top and bottom.
BTW: I loved Lizard
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Rogue pixels
Sort of both. Yes, wrapping around, but in two's complement representation, a signed byte -8 is the same as an unsigned byte 256-8 (248).sailense wrote:I'm still trying to wrap my head around this. Do you mean treating y-scroll value as a signed int? Or wrapping around?
The NES picture also wraps to the next screen at Y=240, though, so it has two wrapping points, which is weird. (It's supposed to skip over 240-255, where the attribute data is stored, but if you start inside that range it will render a few lines of garbage data from it.)
Re: Rogue pixels
Yeah, a Y scroll of 248 or 232 will result in the same picture from scanline 8 onwards, but scanlines 0-7 will be different: 248 will show garbage (attribute table data interpreted as name table data), 232 will show the bottom row of the name table.
Re: Rogue pixels
I think I get This thread helped alot too viewtopic.php?f=10&t=17014
Right now I'm resetting scoll values in all my subroutines where I write to $2006. Is that the best way to go? And when is the best time to read from controller? Every NMI or during the main loop?
Right now I'm resetting scoll values in all my subroutines where I write to $2006. Is that the best way to go? And when is the best time to read from controller? Every NMI or during the main loop?
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Rogue pixels
I can think of theoretical situations where someone might want to read and use input in the NMI, but in general there's no reason to read the controller more often than you do something with those read values, so probably I'd suggest main loop.sailense wrote:Right now I'm resetting scoll values in all my subroutines where I write to $2006. Is that the best way to go? And when is the best time to read from controller? Every NMI or during the main loop?
Re: Rogue pixels
Perfect. Thanks so much.rainwarrior wrote:I can think of theoretical situations where someone might want to read and use input in the NMI, but in general there's no reason to read the controller more often than you do something with those read values, so probably I'd suggest main loop.sailense wrote:Right now I'm resetting scoll values in all my subroutines where I write to $2006. Is that the best way to go? And when is the best time to read from controller? Every NMI or during the main loop?