To keep from crowding out the forum this will be the resident thread for my PPU questions (and there'll be a few).
First up: What in the heck do I do CHR-ROM? Is it loaded into VRAM sort of like PRG-ROM? Or does the program do this? Thanks.
Robin: Holy smokes Batman, where now?
Batman: To the Batmobile! I mean, to the Newbie Help Center!
CHR-ROM is loaded into $0000-1FFF in PPU memory. If there isn't any present in the ROM then $0000-1FFF is VRAM. It can be switched in and out of that area via memory mappers.
Holy scanlines, Batman!
Which brings me to the next quesiton: how in blazes does one handle screen drawing? Should I draw the screen one pixel at a time, or fake v/hblank times? What I currently have set up now (sort of) is to redraw the screen every 1000/59.97 ms and call NMI after that. The time in between is set to vblank. I'm guessing this'll probably screw timing up something terrible. EDIT: Also, how do fields come into play, PCs being progressive? Thanks again
EDIT: Another thing. How does $2006 work exactly? I know it takes two writes to set the address, but how does that work? I assume save the low byte somewhere temporarily and wait for the high byte?
The NES is also progressive.
The CPU and PPU run in parallel, with 341 PPU cycles per line (except 340 in some cases that you can worry about later) and 5 CPU cycles for every 15 or 16 PPU cycles (depending on region). You can emulate the CPU up to the point where it reads or writes a PPU register ($2000-$3FFF or $4014), and then render pixels up to that point.
And about $2005 and $2006: Loopy's document "The skinny on NES scrolling" explains how writes to $2005 and $2006 are translated into writes to internal V and T registers.
Okay, got that working. Next question: is sprite ram actually seperate from vram?
dxprog wrote:
Okay, got that working. Next question: is sprite ram actually seperate from vram?
lmao, er yes it is. There are three memory maps on the NES, CPU, PPU and Sprite. It has 256 bytes of it's own memory, enough to hold data for 64 sprites.
Ack! I've been n00bd! Anyways, no more questions at the moment. SMB seems to have gotten itself stuck in an infinite loop (8057: JMP 8057). Actually, I do have a question. Can an NMI fire while the NMI routine is executing (gives you an idea of how porly timed my code is
)?
SMB is supposed to get itself into an infinite loop (8057: JMP 8057). It is a method of waiting until the VBlank time starts. The loop is exited by executing an NMI.
I assume that the internal VRam counter wraps after &H3FFF?
Well here is where it gets tricky. PPU Memory is 14 bits wide, enough for $0000-$3FFF, BUT the PPU VRAM Address/Temp Address are 15 bits wide enough for $0000-$7FFF. If you try to access PPU memory above $3FFF then actual address accessed in the same minus $4000, (i.e. $63FC would return the value at $23FC. As far as incrementing the PPU Address whenever $2007 is accessed, I assume that the Address goes up to $4000.
Well, after a little searching (amazing feature, eh?) and reading I found that I'm handling $2005/$2006 all wrong anyways. Hopefully when I get that written properly I won't have out of bounds problems (at least, not with SMB).
Okay, a question that isn't quite as n00bish as the last one. One pixel is drawn every PPU clock and there are 340/341 PPU clocks per scanline yet the screen is only 256 pixels wide. What's the PPU doing after that last pixel is drawn?
dxprog wrote:
Okay, a question that isn't quite as n00bish as the last one. One pixel is drawn every PPU clock and there are 340/341 PPU clocks per scanline yet the screen is only 256 pixels wide. What's the PPU doing after that last pixel is drawn?
Loading sprite data, HBLANK, pre-fetching the first two tiles for the next scanline.
The boards were down all day yesterday and I was sad
.
I assume all the scroll values (written to 2005) esentially say where to start reading tiles (y * 32 + x + $2000)? And how is $2006 updated every frame during rendering (+1 every 8 pixels to point to the next tile)?
Ignore the previous question for now (actually I may have figured it out).
New question, though. What do you do when a palette entry is greater than 51?
Palette entries actually range from 0 to 63. The unused values aren't bunched up at the end.
The NES color values normally regarded as unused are $0D, $0E, $1D-$20, $2D-$2F, and $3D-$3F. $0D is the sync level, which should be avoided so as not to confuse TVs. $1D, $2D, and $3D are various nearly-duplicate gray levels that don't show up on the PlayChoice PPU, which commercial games tended not to use. The $xE and $xF values other than $0F are duplicates of $0F (canonical black). $20 is a duplicate of $30 (canonical white).
You may have guessed that the unused values were together at the end ($34-$3F), which is what I meant by "bunched up".
dxprog wrote:
New question, though. What do you do when a palette entry is greater than 51?
Greater than 51? You don't do anything special when a pallete entry is greater than 51. Are you refferring to $51? Or 51 in decimal. If you are reffering to hex, I think it's like this:
0 - 3F = color values
40 - 7F = mirror of 0 - 3F
80 - BF = mirror of 0 - 3F
C0 - FF = mirror of 0 - 3F
So if you store 40 in PPU address $3F00, then it will read as color $0, because 40 - 7F is a miror of 00 - 3F. So color $51 would be color $11. I suppose it's not really like a mirror, it's like a color mirror. Do you understand what I mean?
Edit: If tepples answered your question correctly, then I was way off on what you were asking. But yeah, I suggest you use $3F for black. It's like the official black color. Actually, a lot of people use $0F, but it bothers me to use that, because black seems like it should be at the end of the color selection, so I use $3F.
Yeah, that was 51 decimal (I work primarily in VBasic, sue me
).
Are your questions on that matter answered?
A good convention is to write decimal numbers without a designator: 789, hexadecimal numbers as 0xBEEF, 0BEEFh, or $BEEF. If you need to write a lot of hexadecimal numbers, then announce a temporary "change of default base" to hex.
If we had easy subscripts here, we'd just write
Code:
789
10
BEEF
16
When I'm using hex I usually prefix it with $. And, yeah, my question's answered. Wrap after $3F. Thanks
$bfff or 0xbfff are both good. BFFFh is confusing to be, because you'll try to still read the final "h" as to be the value, and so hex number like that are hard to read.
Could someone tell me the effect of displaying the color $1d ?
Without using $xd color, the darkest available gray is $00, and it isn't very dark, so the NES basically doesn't allow dark grays at all.
But with the use of $xd colors, is it possible to have a drarker gray than $00 ? Because you'd usually like to have a black border arround sprites, but you won't like haing the black border of sprites mess up with black parts of BG. So having dark-gray border arround sprites would be a good choise, but $00 is way too light.
Well, the effect of $1D all depends on the TV, or so I understand.
$1D will probably show up as black on most emulators. But on a real NES hooked up to a TV, it may show up as a darker gray, which is good. But you probably don't want to take a risk of putting a game with that color code on it onto a cartridge, then having it show up as some weird pink color, or something. If it does show up as a darker gray, than I say go for it, use it. But I wouldn't want to risk using that, then having it show up as a lame pink on a different TV, or something random like that.
I agree. The grays that the NES provides are total shit. For vincents hair in FFVII NES, I use a dark blue, because if his hair was black, and the background was black, it wouldn't show up, and it'd look really dumb. I'm just saying, you could find some ways around it by using another dark color, but they are like way too light, I agree.
Can you get a decent gray by flickering $08 with $02?
You mean like changing the pallete values every frame to $02 or $08? That's a really annoying subroutine to do. And constant writes to $2006/$2007 isn't healthy, because you could mess up the scroll if your not careful. I've done something like that where every NMI the pallete updates, and it was not healthy. There were alot of scrolling issues. I don't like that EVERY time you write to $2007 you have to restore the scroll. I suppose it doesn't matter that much though.
If you want to save time, I'm sure you'd want to do as little writes as possible. But I just don't like doing constant writes to $2006/$2007. It bothers me. And that'd look kinda ugly, the constant flickering. I don't know, I'll have to try and see.
EDIT: I forgot to say, flickering $00 and $3F would get you a decent dark gray, as apposed to $02 and $08.
Celius wrote:
And constant writes to $2006/$2007 isn't healthy, because you could mess up the scroll if your not careful. I've done something like that where every NMI the pallete updates, and it was not healthy. There were alot of scrolling issues. I don't like that EVERY time you write to $2007 you have to restore the scroll.
No, you just have to set the scroll after the
last VRAM or palette update of vblank. If you have a scrolling game (not a fixed game such as Donkey Kong or something inspired by Tetris), chances are you're already doing this.
Oh, I guess I'm just retarded then. I thought it was every write to $2006/$2007. Thanks for the info, though.
On a standard configuration, you'll want to do all your PPU updates through $2006 and $2007 during VBlank, and write proper scroll to $2005 and nametable index to $2000 once it's done.
Things are going weird if you want to do anything midframe.
Yeah, having the color black randomly shows up as pink would be RALLY anoying.
Using blue for black hair really is a good idea. Magus has blue hair in Chrono Trigger, but he actually looks like to have a black hair.
Howver, you won't have all your sprites surrounded with a blue shadow.
Flickering is also risked, as it would show nice on some TVs and ugly on some others.
On my TV, sprite flickering is nearly unnoticeable, and under an emulator on my PC it looks awfull. I think the same goes for color flickering.
Yeah, the pink would really be dumb, so I wouldn't use that color if I wasn't sure of the outcome.
But the flickering might be good if you can't notice it on a TV. But if you can, then obviously it isn't very good.