I am not sure how to do BG scrolling! I know that you write variables to $2005, but I don't know what to write! I don't know how write the most simple instruction ever: If this is here, do this. I can't even make it scroll on its own, let alone tell it when to scroll! I'm probably not making sense... But please answer this if anyone reads this within the next thousand years. I am using NESASM, for anyone that cares...
If you already know how to display a non-scrolling background, then try doing this during vertical blank:
Code:
; global variables in zero page
x_scroll_distance = $ee
y_scroll_distance = $ef
; reset $2005 latch and wait for vblank
; (pedagogic spinning method, not production nmi method)
@loop:
bit $2002
bpl @loop
; set scroll register
lda x_scroll_distance
sta $2005
lda y_scroll_distance
sta $2005
; turn on background
lda #$0A
sta $2001
inc x_scroll_distance
jmp @loop
Well this probably should've been in nesdev (as opposed to nesemdev) -- but whatever ^^
Anyway, Scrolling is suprisingly simple from a game developer standpoint. It involves two writes to $2005, and possibly a write to $2000.
First write to $2005 will be your X scroll (in pixels... 0-255)
Second write to $2005 will be your Y scroll (in pixels... 0-239)
The low two bits of $2000 pick which nametable to start drawing from. $2000.1 is the Y nametable (flipping this bit on would be like adding an additional 240 to your Y scroll). $2000.0 is the X nametable (flipping it on is like adding an additional 256 to your X scroll)
Yeah, I realized that after I typed this message. I didn't know people still like replied on this website. Posting this message was my only hope to finding out how to do BG scrolling. Well, it scrolls, and thank you, but, is there a way to to make it scroll continuosly? because it scrolls left, and then pops back up in the middle of the screen, and scrolls left. Is there a way to make it then come from the right, and go left? do you know what I mean? Sorry, I use alot of commas and question marks.
That's what the low bits of $2000 are for. Once you scroll 256 pixels, you're into the next nametable. So once your X scroll goes past 256, toggle $2000.0 (assuming vertical mirroring)
I tried toggling them, and it doesn't change anything. You're talking about the PPU right? I followed the code that the other guy posted below my first message, and I tried changing these two bits:
#%000010
00
sta $2000
like you said. It doesn't do anything! Are you talking about the Name Tables when you say 2000? because the NES's in the US skip a line, or something dumb like that, so they start at 2020. So could you re-explain that to me? thanks.
-- snip -- I misread your above code. Nevermind what was here before. The below code still applies.
To add on to tepples' code:
Code:
; set scroll register
lda x_scroll_distance
sta $2005
lda y_scroll_distance
sta $2005
lda name_table_status
sta $2000
; turn on background
lda #$0A
sta $2001
inc x_scroll_distance
bne @skip
lda name_table_status
eor #$01
sta name_table_status
@skip:
jmp @loop
I'm sure that would work, but what should I put for name_table_status? should I put that on top under the x_scroll_distance stuff? what would I write to it?
It's just a variable. Just stick it somewhere in RAM. The whole point is to keep track of the low bit to write to $2000 (since you can't read $2000, it helps to keep track of it in RAM somewhere, hence the use of that variable).
As for what you set it to -- set it to whatever you want to write to $2000. I won't get into what each bit does -- check nestech for that.
You don't have to do things this way -- it was just an example.
Okay, so I put name_table_status up under the x_scroll_distance stuff, and I set it to $FF, and it scrolls across the two name tables exactly how I wanted them to! thanks! and you can just write something to $2400 and have it be in the Second Name Table, and it will scroll right after the first name table?
Yes -- assuming Vertical mirroring.
The nametables will alternate like:
A B A B A B
'A' being accessable via ppu$2000
'B' being accessable via ppu$2400
When you scroll right off nametable A, you'll move into nametable B. Likewise when you scroll right from nametable B, you'll scroll into nametable A.
To write stuff to Name Table 2, do you have to set up PPU and all that again to a different adress? If so, what adresses?
Assuming Vertical mirroring, Nametable B is accessable at ppu$2400-27FF. So to write to that nametable you set the ppu address to ppu$2400 with dual $2006 writes:
LDA #$24
STA $2006
LDA #$00
STA $2006
Then you write to $2007 to send the data to the PPU. Exact same way you write to nametable A, only it's at a different PPU address.
Okay, Thanks! One last question, how do you get it to stop and start when you want it to? sorry...
You control the X and Y scroll with writes to $2005, and you control nametable scrolling with the low 2 bits of $2000. You can control exactly where and when the screen scrolls by writing the desired values to those registers at the desired times.
Don't try to build off that above pasted code -- it was just an example. Write your own scrolling code. Then you're in control of how it scrolls.
Well, if I knew how to scroll before hand, I think I would use some of that code without seeing the example, if you know what I'm saying. But thank you for all the help, now I know how to scroll! yay! thanks
!
-Celius
okay, what instruction do you stop a scroll with? BRK? i don't know.
There's no instruction. There's no stopping a scroll. You set the scroll to what you want -- it doesn't automatically move, you have to move it. The above example constantly updates the 'x_scroll_distance' var (with an inc command). That var gets moved to $2005 at the start of every frame -- which constantly scrolls the screen one pixel a frame.
But like I said, don't try to build on the above example -- write your own.
First write to $2005 = X scroll
Second write to $2005 = Y scroll
Low 2 bits of $2000 = Nametable scroll
^ That is all you need to know! Just write to those regs every frame with whatever values you want to scroll the screen exactly where you want it! There's no trick or anything -- that's all you have to do. ^
So -- if you want to scroll the screen right... say... 160 pixels at a rate of 20 pixels per frame, you would write 20 to the X scroll the first frame, then 40, then 60, etc until you hit 160, at which point you would stop changing your scroll value.
okay, but just so you know, I tried stopping an automatic scroll (which there is such a thing) with the BRK instruction, and my titlescreen moved to the center of the screen and stopped. I just wrote BRK right after the example scrolling code. But I do get what you're saying.
No, there is no such thing as an automatic scroll. You have to write the desired scroll values yourself. It doesn't change them automatically.
Don't use the example code! It was just an example! If you want to have full control of how the screen scrolls you will want to write your own scrolling code.
BRK will throw a software IRQ (jump to your IRQ vector). Since you're probably not jumping back to your scrolling code, you're not scrolling the screen anymore (if you even have a proper IRQ vector -- its very possible BRK is just locking up your whole program by jumping to garbage code). At any rate... BRK has nothing to do with the screen scrolling.
I think, that you shall first write something simpler to understand how the NES works before writing a scrooling stuff. When you'll understand the basics, you'll be able to do more interessting stuff, like scrooling.
Anyway, even if you don't scroll at all, you must clear $2005 after all $2006/$2007 writes in a VBlank (I remember the first time I've written a code for the NES, I uploaded the $2005 scrooling BEFORE uploading the palette via $2006/$2007, so the scroling get modified by the $2006 register and I've searched for months why my thing wasn't shown on the screen (the picture was out of the screen because of the odd scrooling value)).
How would you define the INC instruction?
nevermind, you don't have to answer that.