| |
johncl
Registered: Aug 2007 Posts: 37 |
Screen copy CPU intensive
I am working on a little game for the C64 and have stumbled upon a slight problem. A smooth scroller is darn CPU intensive! Its a simple sidescroller where I want to scroll the upper 18 lines. The copy required to move the character and color ram is very expensive! I use kickassembler and at first I tried this:
.macro ScrollLines(screen,from,to) {
.var half = round([to-from]/2)
ldx #0
jmp !loop+
.align $100
!loop:
.for (var i=from;i<from+half;i++) {
lda screen+1+[i*40],x
sta screen+[i*40],x
lda SCREEN_COLOR+1+[i*40],x
sta SCREEN_COLOR+[i*40],x
}
inx
cpx #39
bne !loop-
ldx #0
jmp !loop+
.align $100
!loop:
.for (var i=from+half;i<=to;i++) {
lda screen+1+[i*40],x
sta screen+[i*40],x
lda SCREEN_COLOR+1+[i*40],x
sta SCREEN_COLOR+[i*40],x
}
inx
cpx #39
bne !loop-
}
So here I unroll a full column copy in two parts (because bne wont work if I unroll whole column). This even aligns the two loops so that the bne doesnt cross any page boundaries and end up costing another cycle. But still, this routine eats up my CPU big time.
I then tried a complete unroll of a pure copy:
.macro ScrollLines2(screen,from,to) {
.for (var i=from*40;i<=to*40;i++) {
lda screen+1+i
sta screen+i
lda SCREEN_COLOR+1+i
sta SCREEN_COLOR+i
}
}
This also copies the unecessary column too that I need to copy from my map data. But this complete unroll uses almost 2/3 of the screen raster time! Even with this I have to split up my copy so the top part is copied at the bottom redraw of the refresh and the bottom part on start of next screen refresh.
Am I doing something wrong here? |
|
... 25 posts hidden. Click here to view all posts.... |
| |
TDJ
Registered: Dec 2001 Posts: 1879 |
Quote: Guess??? wtf.. Graham guesses his way through life?
Suddenly all those demos he did lose a lot of their meaning :(
"He never meant that effect to happen, he just typed some code and hoped for the best!" |
| |
chatGPZ
Registered: Dec 2001 Posts: 11386 |
thats how a lot of demos were made probably =) |
| |
AüMTRöN
Registered: Sep 2003 Posts: 44 |
Quoting doynaxAnyway, here's the proof-of-concept demo: http://www.minoan.ath.cx/~doynax/6502/Balls%20of%20the%20Scroll..
(I know it isn't all that fancy but I'm a novice when it comes to VIC hacking so I'd like to pretend I invented a new graphics mode ;)
Nice demo, I liked it a lot. I guess your enemy formations lend themselves to "simple" multiplexing, but I still like a lot of moving objects no matter how its done. Good work! :D |
| |
doynax Account closed
Registered: Oct 2004 Posts: 212 |
Quoting cadaverDoynax: also notice the special "hell elevator" scene in Turrican II where you drop 8 pixels per frame :) *That* at least must consume all rastertime available.. Meh.. It seems like that whole game is built around a huge number of special case hacks.
Quoting MTR1975I guess your enemy formations lend themselves to "simple" multiplexing, but I still like a lot of moving objects no matter how its done. To be honest that's more of a symptom of lazy level design than a special purpose multiplexer. There should be room for a few sprites left to play with actually, especially if you synchronize the players' bullet streams and allow the occasional glitch. |
| |
johncl
Registered: Aug 2007 Posts: 37 |
Quote: I don't know how much you need leftover rastertime, but I just want to mention that games like Turrican I/II/III do up-to-4-pixels-per-frame scrolling without unrolling either the screen or color copy routine. An example:
frame 1: shift screen data in hidden buffer
frame 2: shift color data, split in two halves
frame 3: repeat above...
This is assuring to read. I see that unrolling the loops take a lot of memory which I really want to use for compressed level data instead. I'll probably unroll whole columns at least to free as much raster time as possible. Since I need a different loop per frame and one per direction a big unroll would have left me with scraps.
While I am at it (and sorry for the noobish questions here as I am quite new to the C64 after all these years): I have been able to turn off Basic ROM since that is not needed to free 8kb of memory. But is there more rom memory I can "get under"? I seem to recall that I should be able to write to char rom at $d000-$dfff but reading this I guess requires me to turn off that rom somehow? And the RAM under the kernal rom at $e000-$ffff - Is there any way I can use that? I guess I just need to avoid using kernal functions or will turning it off ruin stuff like raster interrupts etc? Again sorry for the noob questions.
Today I basically use the kernal for reading the keyboard to eg start the game or enter name in hiscore list. But maybe if I could store compressed level data there, turn it off, unpack to current level ram and turn it on again I will be ok? It would have been nice to use all the ram I can use.
Also one final question. Zero page addresses, which can I use for my own programs without messing anything up? I guess I can use any spot that is typically used by basic at least in addition to the end bytes that are reserved for apps? |
| |
Radiant
Registered: Sep 2004 Posts: 639 |
johncl: Put $35 in memory location $01 to swap out both the BASIC and KERNAL ROM areas. You'll have to use the $FFFE/$FFFF etc interrupt vectors.
Put $34 there to also swap out the IO registers at $D000-$E000. You have to enable them again once you are going to do any SID, VIC or CIA operations, of course. |
| |
Steppe
Registered: Jan 2002 Posts: 1510 |
Johncl, I think a very useful site for you is here:
http://www.the-dreams.de/aay.html
At least the zero page issue is answered there. |
| |
Radiant
Registered: Sep 2004 Posts: 639 |
Have to commend doynax on the EXCELLENT technique as well! Well done indeed! |
| |
Stainless Steel
Registered: Mar 2003 Posts: 966 |
Looks great, except for the gfx. |
| |
Oswald
Registered: Apr 2002 Posts: 5094 |
$01 usage for beginners:
http://codebase64.org/doku.php?id=base:memory_management&s=memo..
raster irq with kernal & basic off:
http://codebase64.org/doku.php?id=base:introduction_to_raster_i..
if you still want to use kernal you can do turn it back on IN the irq, and turn it off(or restore state) before exiting. If you use the kernal for reading the keys make sure to call SCNKEY once every screen refresh since this routine scans the keyboard and fills the keyboard buffer for GETIN which you call normall from the main loop to read the keys.
Make sure that your irq saves the state of $01 before changing it, and restores it before exiting. This assures that your code outside the irq can aswell safely turn the roms on and off.
This way you can turn off even the $d000 area, but that will cost you time since in all irqs you will have to turn it back on and off again. |
Previous - 1 | 2 | 3 | 4 - Next |