It is currently Wed Oct 18, 2017 6:33 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 60 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
 Post subject: Partial Scrolling
PostPosted: Tue Nov 15, 2005 7:53 pm 
Offline
User avatar

Joined: Sun Jun 05, 2005 2:04 pm
Posts: 2129
Location: Minneapolis, Minnesota, United States
I really didn't get how to scroll for PART of a name table, it didn't really make sense to me. I know it's possible, as I can see from many games/tech demos: CMC 80's, Cosmic Epsilon, 3D battles of world runner. But I'm not trying 3D stuff yet, that's at the, well, bottom of my list of things I need to learn how to do. Way to complicated for me now. Anyways, I am going to put together a technical demo of partiall scrolling, and I need to well, know how to do it! What I want is the half of the middle row to scroll slowly, the other half will be still, and I want the rest to move faster. How would I do such a thing? I don't even know where to start. Please help. Thanks. :)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 9:11 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
You can accomplish this by changing the PPU scroll values mid-frame (ideally, in HBlank between scanlines). Say you break the screen into 3 sections:

Code:
----------

Top section, no scroll
(height: 60 scanlines)

----------

Mid section, half scroll
(height: 60 scanlines)

----------

Bottom section, full scroll
(height: remaining (240-60-60 = 120) scanlines)

----------


As you probably, know, each scanline is 113.66667 CPU cycles on an NTSC system, so you can count the number of cycles that need to pass from NMI to know when the PPU is rendering the scanline you want.

To create simple HORIZONTAL scroll effects, a la Excitebike, SMB, all you need to do is perform the first write to $2005 (second $2005 couldn't hurt, but it doesn't really have any effect) -- and also $2000.0 (for the nametable). You perform these writes at the proper time in the frame to split the screen.

Note that vertical scroll effects are far more difficult and usually require crafty alternating $2006/$2005 writes.

For the above example... say if the screen is supposed to be scrolled 80 pixels... you'd set the scroll to 0 in VBlank... then after 60 scanlines, change the scroll to 40... then after 60 more scanlines, set the scroll to 80.

Splitting the screen in this fashion is most easily done with the support of mapper IRQs (like MMC3's scanline counter). Without any mapper IRQ, the next easiest thing to do is to set up Sprite 0 so it'll hit at a certain time in the frame... then watch $2002 and wait for the Sprite 0 flag to raise. Or... if you have a LOT of free CPU time, you could have a big timed loop which counts the cycles (actually... Balloon fight does this for the Balloon Trip mode -- it doesn't use Sprite 0 hit at all I don't think... it just times it).

Wanting to split the screen TWICE per my previous example would be difficult (or CPU time consuming) without the aid of mapper IRQs... since you can only use Sprite 0 once in the frame.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 9:39 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19098
Location: NE Indiana, USA (NTSC)
Parallax scrolling

First use sprite 0 to determine where you are on the raster, by waiting for a bit in $2002 that indicates whether an opaque part of sprite 0 has been drawn overlapping the an opaque part of background (or vice versa). Then use timed writes to $2005 and $2006 (you can get away with a much simpler $2005-only loop if you only want to scroll horizontally).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 9:50 pm 
Offline
User avatar

Joined: Sun Jun 05, 2005 2:04 pm
Posts: 2129
Location: Minneapolis, Minnesota, United States
Okay, this may seem dumb, but when you say 113.666667 CPU cycles per scanline, do you mean per vblank? Okay, I don't think you do, I may sound stupid, because I know what I'm talking about more than it seems, but! I did a short test with the hello world program I made, and! I stored 0 in vbl_count before my endless loop. In my code I said this:
Code:
      lda #$00
      sta vbl_count
loop:
      lda vbl_count
      cmp #0
      beq keepinc
      jmp loop

keepinc:
      inc stuff
      jmp loop


and stuff ended up being #$72, which is 114! Which is most likely the number you're refering to: 113.666667, just the NES rounds it up because it doesn't do precise decimal things. But am I right about what I said? I think I am, I may be stupid, I don't know.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 10:13 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 10:59 pm
Posts: 1389
No, he meant 113+2/3 CPU cycles PER SCANLINE.
If you want the number of cycles per VBLANK, that'd be 2273+1/3.

_________________
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.


Last edited by Quietust on Tue Nov 15, 2005 10:32 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 10:22 pm 
Offline
User avatar

Joined: Sun Jun 05, 2005 2:04 pm
Posts: 2129
Location: Minneapolis, Minnesota, United States
Okay, this is really dumb, but how are there 2273.33333 scanlines per vblank? Oh man, I sound dumb, but I don't know that much about CPU speeds. It never said in like nestech or anything, so I wouldn't know. Please don't be hard on me, just nicely direct me to the document where this information is present. Thanks....:(


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 10:33 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 10:59 pm
Posts: 1389
Celius wrote:
Okay, this is really dumb, but how are there 2273.33333 scanlines per vblank?


There aren't - I made a typo; that should be cycles per VBLANK.

_________________
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 10:44 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
1 scanline = 1 row of rendered pixels.

also:
1 scanline = 341 PPU cycles
3 PPU cycles = 1 NTSC CPU cycle
therefore:
1 scanline = (341/3)=113.666667 CPU cycles

One NTSC frame consists of 262 scanlines. Constructed in the following manner:

Code:
------------
20 scanlines of VBlank

------------
1 "pre-render" scanline
------------
240 rendered scanlines


------------
1 idle scanline
------------


NMI starts right at the start of VBlank. If you start counting from NMI, and if you want to split the screen in half (after 120 scanlines have rendered), you would have to change the scroll 16027 cycles after NMI:

20 (VBlank) + 1 (pre-render) + 120 (half the rendered screen) = 141 scanlines

141 * 113.666667 = ~16027 CPU cycles


Of course if you can't count that many cycles (if your CPU is busy doing stuff), you can put sprite 0 so it'll hit on scanline 120 and wait for the Sprite-0 flag to raise. When it does, you'll know the PPU is rendering scanline 120 and you can change the scroll so the next scanline will have a different scroll value.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 10:56 pm 
Offline
User avatar

Joined: Sun Jun 05, 2005 2:04 pm
Posts: 2129
Location: Minneapolis, Minnesota, United States
Oh, so you're saying in 341 PPU cycles, 1 scanline is made? I guess the PPU travles at like a million miles an hour. So (this may be stupid) in 170.5 PPU cycles, a half scanline is made? I sound really dumb, don't I. Okay, I need to study sprite 0 hits and hblank and vblank and stuff a little more. Am I really dumb sounding about this whole thing? :(


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 11:10 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
To put it roughly:

the first 256 cycles are the PPU rendering pixels
the last (341-256) 85 cycles are HBlank

It's not quite that cut-and-dry, but that's basically the setup. One pixel is rendered on screen for each of the first 256 PPU cycles that pass. After that the PPU loads sprite stuff for the next scanline (your HBlank time), and then loads some tiles for the next scanline.

And no, you don't sound dumb ;P we all had to learn this stuff at some point.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 16, 2005 5:28 pm 
Offline
User avatar

Joined: Sun Jun 05, 2005 2:04 pm
Posts: 2129
Location: Minneapolis, Minnesota, United States
Okay, this is really bad, but I JUST want to make sure. Okay, now this really is a little bit dumb. So when you say CPU cycle, you mean like say, you increment a variable in your endless loop. Everytime it increases, is that a CPU cycle? If not, I am not sure what you mean! And it is very important that I learn! Help!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 16, 2005 5:43 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
http://www.obelisk.demon.co.uk/6502/reference.html


NOP takes 2 cycles
LDA immediate takes 2 cycles
LDA zero page takes 3 cycles
etc


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 16, 2005 7:27 pm 
Offline
User avatar

Joined: Sun Jun 05, 2005 2:04 pm
Posts: 2129
Location: Minneapolis, Minnesota, United States
Okay, I just made a demo, it doesn't have to do with my partiall scrolling, unfortunately, but I made an interesting demo here, it's on my site, which I have a link to in my signature. Go to tech demos, and download "hello1.zip", because it has a very interesting demo that I was kind of proud of, even though I didn't try to do it, I made something cool happen. I should submit it to pdroms tech demos. Maybe not. I don't know. See for yourself. Tell me if it's cool. Okay so I am going to create my complete full fledged partial scrolling demo later. Right now, I want the top and the bottom of the screen to scroll different ways. So my screen says "Hello, World!" twice. It says it once on the bottom row of the top half of the screen, then it says it once on the top row of the bottom half of the screen. Yeah, I want to say put sprite 0 on the scanline where the bottom "Hello, World!" text is, and then I'd say, dec scrollx, and :

stuff:
lda $2002
and #%01000000
bne lada
inc scrollx
lda scrollx
sta $2005
rts

lada:
rts

But that's what I used in my NMI routine, to get my sprite collide with color demo. Wow, I'm even more proud of that demo than I thought. I could really manipulate that effect to my own good. Okay, but I think I'm getting close, I just need a little more help here. Thank you, this is very helpful! :)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 16, 2005 8:09 pm 
Just checking sprite 0 flag once won't do -- you'll have to constantly check it and wait for the flag to raise. Additionally... once the Sprite 0 flag is set in the frame... it will remain set until the next vblank is over! So what you'll probably want to do is wait for the sprite 0 flag to go down... then wait for it to go back up. When it goes back up -- that's when sprite 0 hit, and then you can split your screen.

Code:
nmi:
  ; sprite DMA, set initial scroll, turn on the screen
  ;  all the typical NMI stuff -- do it here

wait_spr0_clear:
  bit $2002            ; sprite 0 flag gets put in the V flag
  bvs wait_spr0_clear  ; if the flag is set, loop until it's clear

wait_spr0_hit:
  bit $2002
  bvc wait_spr0_hit    ; if flag is clear, loop until it's set

  ; here, sprite 0 has been hit.  set your new scroll


I use BIT+BVC instead of LDA+AND+BNE since it's a little faster and does more or less the same job.

Also note that if sprite-0 never hits (like if you place it wrong) -- you may end up in an infinite loop, waiting for sprite-0 to hit when it never will. Remember that to make sprite-0 hit, a non-transparent sprite-0 pixel must be drawn on a non-transparent BG pixel.


Top
  
 
 Post subject:
PostPosted: Wed Nov 16, 2005 8:41 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
that was me -- I got logged out for some reason


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 60 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: Google [Bot] and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group