The following weekend I created a test level to check the update timing for the kernel. The time critical section of the kernel is when the ice blocks are being drawn as everything (snowman & color, nose, melt trail, fireball, 6 playfield updates) had the potential for being drawn:
Looked great, but I had to drop both the nose and the melt trail as there wasn't enough time to update everything during that critical section
- 36 cycles to update playfields
- 21 cycles to draw snowman
- 8 cycles to update fireball
- 7 cycles loop control
- 72 cycles total
Normally I would use sprite drawing logic of DoDraw, which would take 26 cycles to update & color the snowman, but there wasn't enough time for 5 additional cycles in that loop. Instead, I used a Mask:
lda (FrostyImagePtr),y ; 5 5 and (FrostyMaskPtr),y ; 5 10 sta GRP0 ; 3 13 lda (FrostyColorPtr),y ; 5 18 sta COLUP0 ; 3 21
The tradeoff of using a Mask is you need more RAM (for the mask pointer) and more ROM for the mask itself. The Mask is a block of $ff sized the same as the full-health snowman, with blocks of $00 on either side:
BlankGraphic repeat 50 ; 148-26 .byte 0 repend repeat 25 .byte $ff repend FrostyMask repeat 50 ; 148-26 .byte 0 repend
Now, that I'm more familiar with DASM, I would recode that as:
align 256 BlankGraphic: ds 50, $00 ds 26, $ff FrostyMask: ds 50, $00
In hindsight I probably should have looked into using SwitchDraw to eliminate the Mask's extra RAM and ROM requirements as the Y register isn't used to count down the scan lines for the entire screen; instead, Y counts down the height of each platform zone. This means the Y's value is always between 0 and 127, which is one of the prerequisites for SwitchDraw. You can get a good overview of a number of sprite drawing options in this post by vdub_bobby.
The playfield is only updated during the scanlines with ice or platforms, leaving quite a bit of time in the "air" above the ice. It's during this time that the player 1 is repositioned to draw the next fireball. In this early build the reposition routine has an X position limit of 0-146, which can be seen by moving fireball on the bottom platform. This was due to needing to update the snowman's sprite and color during the reposition logic. I hadn't yet looked into increasing the range, but felt that the limit would be acceptable if I couldn't change it.
The kernel was repeated 5 times to support 5 zones (platform levels). 109 bytes of RAM were required to keep track of it all!
Heights ds 1*SECTIONS ; heights of the levels FireBallX ds 2*SECTIONS ; fireball positions, 2 per section IceData ds 6*SECTIONS ; ice blocks Platforms ds 6*SECTIONS-6 ; platforms FrostyImagePtr ds 2*SECTIONS FrostyMaskPtr ds 2*SECTIONS FrostyColorPtr ds 2*SECTIONS FireImagePtr ds 2*SECTIONS
Blog entry covers November 5-11(AM), 2007