It has been some time since I last posted an update on my Juno First game. The project has been on hold for a while, but it has not been abandoned completely. One of the reasons that it stalled is because I wasn't completely happy with the kernel. My aim for the game was to have full colour sprites that are updated on every line (1LK). This should make the game visually superior to similar games (such as Beamrider), but it is quite a challenge to achieve!
I managed to get the kernel working, except in one case, which would cause the gridline to jump in an annoying way. The source of the problem is that the alien sprites need to be repositioned at various places on the screen, and this repositioning takes a screen line to accomplish. This repositioning can clash with the drawing of the gridline, as there isn't enough time to do both. In most of the screen this wasn't a problem, as I just delayed the repositioning by 1 line when this happened (with a gap of two screen lines between aliens). However, at the bottom of the screen the ship also needs to be drawn every screen line and this trick doesn't work. My solution was to draw the gridline immediately after repositioning in this case, but this causes the gridline to be drawn one line further down, and leads to the annoying jumping effect.
For a long time, I tried to re-arrange things to avoid the jumping problem. I managed to get within a few cycles of a solution by resorting to some loop unrolling, but I just couldn't make it fit! However, I recently read this post in batari's blog and was inspired to have another go. The suggestion in this post is that it isn't always necessary to waste a complete line on repositioning the sprites, since most of the repositioning code is just waiting for the correct position. Instead, it is possible to implement a series of mini-kernels that each reposition the sprite in a different horizontal position, and also have some spare time to do extra work! However, this technique is difficult to implement and requires a lot of ROM space.
In Juno First, the aliens don't go completely to the edges of the screen, so there are ten different horizontal sprite positions. Therefore, 10 mini-kernels are required to implement the technique. I used the following code to jump to the correct mini-kernel:
; Set pointer at beginning of kernel lda #>ReposFunctions sta JPTR+1 ; Jump to correct minikernel ldx XPOSITION lda ReposTable,X sta JPTR jmp (JPTR)
The jumping code costs only 15 cycles, but it requires a fairly large table of pointer values. In Juno First, there are 15 pointers required for each of the 10 mini-kernels:
ReposTable DS.B 15, #<Repos0 DS.B 15, #<Repos1 DS.B 15, #<Repos2 DS.B 15, #<Repos3 DS.B 15, #<Repos4 DS.B 15, #<Repos5 DS.B 15, #<Repos6 DS.B 15, #<Repos7 DS.B 15, #<Repos8 DS.B 15, #<Repos9 EndReposTable
Within each kernel it is necessary to hit the RESPx register at exactly the right time and also to set the HMPx value. I accomplished this with the following code fragments. Obviously, the cycle on which RESPx is hit, and the sbc# value must be changed in each mini-kernel.
ReposX ; Reposition Sprite (Coarse) sta.w RESP1 ; Must happen on exactly the right cycle (20/25/30/35/40/45/50/55/60/65) ... ; Fine Tuning (X contains sprite position) txa sec sbc #30 ; Change value for each mini-kernel: 15/30/45/60/75/90/105/120/135/150 sta HMP1 ; Can happen anywhere before HMOVE ... ; Move Sprite sta WSYNC sta HMOVE EndReposX
Anyway, to cut a long story short, I managed to get this technique working in Juno First after a lot of tweaking. The results are attached to this message. The kernel now takes a whole 4K bank and is the most convoluted bit of code that I ever hope to write! However, it has got rid of the annoying jumping gridline, so I am pleased with the results. I have also made a number of other tweaks to the Juno code since my last posting:
- Homing bullets are now implemented (although slightly buggy)!
- All the different alien types have their own movement and firing patterns.
- You have three warps (shown by the W's at the bottom of the screen). Pressing Select will make your ship disappear for a short time (handy for avoiding bullets).
- There is a nice reverse-explosion when the ship appears on the screen.
- You have to hit fire to start the game, and to resume after you die.
The game now has all of the important features that I planned to include, although there is still a lot of polishing to do. I'm not going to make any rash predictions about when I will get this finished, as at least the following tasks have still to be completed:
- Implement lots of levels with different alien types.
- Make something happen when you pick up an astronaut!
- Add some cool sound effects!
- Add a title screen and high score table (see previous post).
- Add more polish if there is space, e.g. music, attract mode, colour schemes, etc.
As always, let me know if you find any bugs or have any suggestions. The game works in both Stella and Z26 (use phosphor mode), but I haven't tested it on real hardware. I will strongly resist any changes to the kernel now, except if there are any bugs