MORE DEBRIEFING of Reindeer Rescue. It was such a whirlwind putting this together over the last month that I feel a bit wrung out right now. I'm hoping to write some of the development stuff down here to try to remember and try to collect my thoughts.
So anyway. Here's a description of the kernel and how it works.
First, a picture:
The kernel has four main parts. The top part is the horizon, where the sky, the sun, the snowman, the snowmobile, and the hills are drawn. The sky is the background, the hills are the playfield (duplicated, symmetrical), and the other three objects are the players.
The sun is stationary; the snowman and the snowmobile move from right to left. The sprite used for the sun is repositioned to draw the snowmobile. The real tricky part was this: the snowman/snowmobile scroll off the screen (completely) and then a new object replaces each of them on the right. I am using the whole width of the screen; how can I scroll something off/on the screen? Well, each of the two objects has a dedicated variable which is used to mask them. It was pretty tricky figuring out how to set up these variables, but the code to draw them is pretty simple:
Screen4 ; jsr Ret3 jsr Ret3 ;+24 51 lda (Temp),Y sta.w PF0 ;+9 60 lda (Temp+2),Y sta PF1 ;+8 68 lda (Temp+4),Y sta PF2 ;+8 76 lda (MidSkyDataPtr),Y and MSOMask sta GRP0 ;+11 11 lda (LowSkyDataPtr),Y and LSOMask sta GRP1 ;+11 22 dey bpl Screen4 ;+5 27
The masking variables are MSOMask and LSOMask.
Another thing that made the kernel tricky was this: You may notice that I claim that I repositioned the sun sprite to reuse it for the snowmobile. How is there, then, no HMOVE blank? Well, because I hit HMOVE early, ending at cycle 73, that's how. Actually, every HMOVE I strobe in the entire game is hit at cycle 73. This made the kernel a little convoluted, but this gave me the most headaches when I was figuring boundaries for sprites - because hitting HMOVE early moves all sprites 8 pixels left of where they would normally end up, when a sprite had an X-position of 3 it really ended up on the right side of the screen, at pixel 155.
Anyway, moving on. After the horizon is drawn, the playfield is erased and its color is changed to match the background, and both sprites are repositioned. Player 0 is used to draw Santa, and player 1 is positioned to draw the reindeer.
I also wanted the reindeer (and other flying things) to scroll smoothly on and off the screen - but, again, you can't really do that, since if you scroll things off the left edge of the screen they just show up on the right. So what I ended up doing was using PF0 to hide the sprites when they scroll on and off. So for about 20 scanlines PF0 is drawn on the left and then for the next 20 scanlines PF2 is drawn only on the right. So the playfield priority is changed so that the playfield appears in the foreground (after being in the background behind the snowman/snowmobile).
This means that flying objects need to scroll onto the screen from the upper right and scroll off the screen in the middle left. But the effect is pretty cool.
After these ~45 scanlines, the reindeer-sprite is repositioned and we begin the real fun part: the scrolling playfield. There are 8 bands of scrolling playfield, of varying heights, covering the next ~60 scanlines. For the top 7 scrolling bands, only the playfield and Santa are drawn; during the bottom band those are drawn plus the abominable snowman (A. Snowman).
The scrolling playfield is stored in RAM; 8 bands, each with all six playfield registers drawn to, means 48 bytes. The Running Man demo used 10 bands with another column (of 10 bytes) which contained the data that was being scrolled onto the screen. I couldn't afford that much RAM for the playfield, so I cut it to 8 bands and rewrote the scrolling routine to keep track of how many bits had been scrolled on so I could pull the new data directly from the ROM one bit at a time.
A. Snowman moves at exactly the same speed as the scrolling playfield; in four-pixel jumps. A little jerky, but still looks ok. After that is the floor, drawn with the background, then the string of Christmas lights, the score, and the Santa hats, all drawn with a general purpose subroutine I wrote that draws 48-pixels-wide bitmaps to the screen. That subroutine wasn't real hard to write, but it made creating the title screen, the game-over screen, the game-winning screen, and this section of the main kernel much easier. Just set the pointers to the bitmap and color data, set Y for how tall the bitmap is, and call the subroutine. It also made adding the score/hiscore to the title screen, game-over screen, and game-winning screen a breeze.