As part of the testing of the current update to the Penultimate Cartridge, a lot of testing has been going on. This included a video from TFW8b where he went through 30 games in one hour using the built in "Rod's Random ROM Runner", which when enabled, will generate you a "random" game every time you press the reset button.
This was combined with an Arduino with a simple bit of code which automatically pressed the reset button every 2 minutes,
During that testing, RRRR carefully selected the game "Rabbit Blitz" by "C. Simun" for Rod to play.
Rod wasn't sure of the keys and managed to hit the RUN/STOP key, which because it was a BASIC program exited the game and left you at a READY prompt.
Because of the way the graphics had been done, none of those characters were readable, so it was all a bit of a fail.
Separately, during my testing, I had found that the game had a screen-shaking effect when you crashed, and that was leaving the screen set wrong for NTSC after the first crash.
Plan A
The simple plan, the one a sensible person would have chosen, would have been to take the BASIC program listing and make two changes.
The first would be to add in a POKE, such as:
POKE 788, 194
or
POKE 808, PEEK(808)+2
which would disable the RUN/STOP handler and stop that exiting to BASIC.
See the following posts for information on how those work:
- https://blog.tynemouthsoftware.co.uk/2024/01/converting-vic20-multi-part-games-outback.html
- https://blog.tynemouthsoftware.co.uk/2024/11/vic20-multipart-game-conversions-tank-war.html
The second would be to change the screen shake code.
The current version works by changing the value of vertical centering on the VIC chip rapidly between two values, and then resetting it to almost, but not quite, what the standard value should be.
The code in question was as follows:
Extracting out the relevant sections, 36865 is $9001, the address of the vertical centering register on the VIC chip.
POKE 36865,50
Sets this to 50, it then wait for a bit
POKE 36865,30
then sets it to 30.
Finally.
POKE 36865,40
Sets it to 40.
On a PAL VIC 20, for which this game was presumably written, the standard value is actually 38.
On an NTSC VIC20, the value is 25, and the grass is an interesting shade of green?
This means after the screen shake effect, the PAL screen is 2 lines lower, which you wouldn't normally notice.
However, the NTSC system is 15 lines out, so is pushed very low on the screen, still just about visible, but not ideal.
A simple fix would be rather than using
POKE 36865,40
to reset the value, instead it could either peek the value previously, store it and then restore it, or it could read the value from the KERNAL ROM, which is different for PAL and NTSC system, so would be correct. The value is at $EDE5, or 60901, so a fix would be
POKE 36865, PEEK(60901)
That that should be fairly straightforward.
But you know me.
Plan B
Rather than that, I decided to embark on an entirely different solution.
I would rewrite the game in 6502 assembler, fixing those issues in the process and tidying up a few other things as I go.
A combination of the arrogance of a long grey beard and also my intrigue at what the row of £ signs is about that appears briefly as the game starts.
And how exactly the game generates the city skyline using what appears to be an array of mostly inverse Q symbols?
It is 62 lines of BASIC, 1830 bytes. This should be a simple process to recreate that in assembler.
What Could Possibly Go Wrong?
Actually not that much.
I have the fall back of the simple BASIC fixes anyway, so I can just give up at any point and go with that. I could also just leave the game unmodified, as it has been since it was added to the cartridge 3 years ago and no one has noticed, or at least no one has complained about it.
No fake jeopardy here. I am not going to lose the shop if this doesn't work.
(actually, I am going to lose the shop if things don't pick up, but this short, self-indulgent dalliance into a little bit of notepad 6502 coding for a day or so is unlikely to affect that one way or the other)
As usual with these things, my tools of choice are a text editor and a command line compiler. In this case Visual Studio Code and ACME.
I started with a pretty much empty slate, the only given is the one line of BASIC code at the start, the line
6502 SYS4109
(the line number is irrelevant, but I always like to use 6502, because 6502)
I had some of my other assembler games open in another window for reference, so I could steal some of the system constants and any relevant code.
I also have a couple of web pages handy:
Which is a useful reference for the VIC20 memory map and things like the VIC and VIA registers and zero page addresses etc.
This is a handy reference for 6502 assembler as I occasionally need to check things like "does inc set the carry flag?" etc.
I followed the general structure of the code, at least initially. Once it was running, I shuffled things around where they felt most appropriate.
Save ££££££££s
The first thing I wanted to check was the spurious ££££££££ on the screen briefly at the top of the "PLEASE WAIT" title screen.
What was it waiting for anyway?
I did think it might be generating the skyline at this point, but that seems to happen on the fly when you complete a level and are presented with a new one.
Looking at the code, it was mainly lines 20 and 30.
20 fori=0to501:poke7186+i,peek(32768):next
Line 20 is odd. That takes most of the time, is responsible for the ££££££££ screen corruption and does not actually do anything useful.
If I load the game and delete line 20 before I run it, it still works fine, and starts much faster and without the £ signs.
30 fort=0to47:readd:poke7168+t,d:next
Line 30 is important. This reads some data statements in lines 40-90, and pokes 48 bytes of data into memory at 7168, note the "68", which is $1C00, a 512 byte area of code below the screen at $1E00.
Amongst other things, line 100 includes
POKE 36869,255
This sets the VIC addressing register 36869 ($9005) to 255, which sets the video to $1E00 (as it was), but the character data to $1C00 rather than the font ROM at $8000.
The code at line 30 defines six graphics used by the game, the parts of the building, the plane, the bomb. These are in positions 0-5.
The rest of the character set is the remaining 59 characters in $1C00-$1DFF, and then 64 characters from $1E00-$1FFF, which is the screen RAM, so those will be nonsense. Because of the way the VIC chips memory map wraps around, the last 128 characters are the first 128 characters in the font ROM.
On a standard VIC20, if I can run a bit of code to print out all 256 characters from the font ROM.
The first poke writes to screen RAM, the second sets the colour RAM to black so you can see it.
If I add that to the Rabbit Blitz program after the running the code with line 20 removed, I get the following. The horizontal lines come from the default initialisation values in the Vice editor. On a real machine, they would be random noise.
If I put line 20 back and run it again, I get stripes for the characters from 7-63.
Let's remind ourselves of line 20 (with some extra spaces added for clarity).
20 for i=0 to 501 : poke 7186+i, peek(32768) : next
This is setting 501 values from 7186 upwards (yes, that is 86, not 68 as before). This is easier to see in hex.
- 7168 is $1C00, the start of character RAM here.
- 7186 is $1C12, 18 bytes into the start of the character RAM.
18? I could understand if it was 48, that is the number of bytes used by the 6 custom characters, but 18 is two and a bit characters?
It also runs up to 7687 or $1E07, which is 8 bytes into the video RAM which starts at $1E00.
This explains the eight £ characters that appears at the top of the screen in the original game.
Why the £ sign? Well aside from the fact I do not know why the VIC20 has a £ character, on a dedicated key. The dollar is shift + 4, but the £ get's a key of it's very own. The PET didn't have £ at all. It has '\' at character $1C, the rest of the set is I think the same.
Not even the business keyboard PET had a £ sign, so why did the VIC20, a home computer for the US market get one?
Anyway, skipping over that, why the £ sign in this case?
Well, again it is back to line 20.
20 for i=0 to 501 : poke 7186+i, peek(32768) : next
For each of the 502 iterations of that loop, it reads the value at 32768 ($8000). Why?
Why not read it once at the start of the line?
Why even read it at all?
It is the first byte of the font ROM. It will never change, it is $1C on every VIC20. The top of the @ sign.
What is that even doing, it is just filling the character ROM with vertical stripes that are never referenced in the game?
I think it might have been originally something like this.
20 for i=0 to 511 : poke 7168+i, peek(32768+i) : next
This would read 512 bytes from the start of the font ROM at $8000 and copy them into the character RAM at $1E00.
You could then poke the new character data into certain characters and still retain the letters and numbers etc, if you need to write things to the screen.
For example, I have modified the code to do that copy, and to write the UDGs at positions 33 to 39, overwriting some punctuation.
There you see the UDGs are mixed in with the rest of the characters and you can type as normal.
I am not sure what happened with the game, was that the original plan and it didn't work for some reason? It just seems odd to leave that line in place when it is not doing anything useful, just adding a 10 second delay and writing eight £ signs to the top of the screen?
One possibility is to stop the program being listed? If you press RUN/STOP and type list, this is what you would get.
That is unless you type RUN and then press RUN/STOP on the title screen, or if you press RUN/STOP after your plane has crashed.
I could fix that by simply deleting line 20. But where is the fun in that?
Instead I recreated the whole game in assembler.
Where you are welcome to list the entirety of the code...
Tower Block Construction
One reason I decided to continue is that I was intrigued by the next set of lines. It seems to build up the screen using four strings which are mostly inverse Q characters?
Looking at the output of petcat, it shows those as {down} characters?
120
a$(1)="{blk}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}e{left}{down}@{left}{down}@{left}{down}@{left}{down}@{left}{down}@{left}{down}@"
125
a$(2)="{blk}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}e{left}{down}@{left}{down}@{left}{down}@{left}{down}@{left}{down}@{left}{down}@{left}{down}@{left}{down}@"
130
a$(3)="{blk}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}e{left}{down}@{left}{down}@{left}{down}@{left}{down}@"
135
a$(4)="{blk}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}e{left}{down}@{left}{down}@"
It is an interesting solution. It creates four strings at A$(1) to A$(4), then it generates a random number from 1-6 and prints that A$.
200 fort=0to21
210 print"{home}"tab(t);a$(int(rnd(1)*6)+1)
220 nextt
Each one is preceded by {home} symbol and a tab(t).
It goes through 22 columns of the display. For each one, it goes back to the top left using {home} and then moves along to the top of the column (TAB is single characters here, not x4 or x8 as we might be used to).
It then prints the string which moves the print cursor down, down, down until it gets to where the building should be and then prints the building using E and @ for the UDGs at positions 0 and 5. After each printed character, it uses {left} and {down} to go to the next one.
The four strings are different height buildings, 6, 8, 4 and 2 blocks plus a roof each.
There is no A$(5) or A$(6), those are the gaps between buildings which I can now confirm will occur 1/3 of the time.
That is a very unusual way of doing that, I don't think I have seen that sort of thing before.
Scoring
On the original game, there were two numbers printed on the bottom of the screen.
It wasn't clear what these were. Maybe it was explained in the cassette inlay (if it was published) or magazine article (if it was a type-in), but I have found neither.
That might also have explained by the was called Rabbit Blitz. Where are the Rabbits? Was it released by Rabbit Software? Was it written by a Rabbit?
These are the result of another magic string of characters in line 1111.
1111 forh=1toz:nexth:print"{rvon}{blk}{home}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{rght}{rght}{rght}"tb,b
This again goes to the top left and cursors all the way down to the bottom row, cursors right twice and then prints the TB and B variables.
I think those are "Tower Blocks" and "Bombs". TB increments whenever you hit a building, and B increments when you drop a bomb.
When you hit 30, it stops. Story of my life.
You get 30 bombs and that's it. Then all you can do is sit back and wait for the inevitable conclusion.
Oooof.
When you clear everything, you get to the end, and start again.
The bomb count is refreshed, but the building count persists.
It is not displayed on the screen, but there is a third variable used here, SC, presumably "SCore".
This is incremented each time you clear the field and land successfully.
There is a page which is displayed when this hits 10.
(Not that I have ever got there without cheating)
Introducing Bunny Blitz
I have re-themed my rewrite as Bunny Blitz, to make it a bit more cuddly as Blitz might be slightly out of favour after certain world events 25 years ago. #TooSoon?
I have taken the general look and concept of the game, but rewritten it from scratch in assembler.
I added symbols next to the buildings and bombs counters and displayed the score which was previously missing.
The bombs count goes red when it hits 30 and runs out (which inevitably happens when you are have almost completed the level).
I added more information to the "you crashed" page.
As well as a bit more on the "bunny" theme. I didn't have enough space for the full description of "patented lemon-scented building-cleansing bombettes", but I think that works.
As before, the "you won" page uses the same style.
I also applied that to the title page, to act as a sort of introduction to the game.
There is no need for a "please wait" as it only takes a second to setup the character set, which it has in fact done before the screen is displayed as it uses those characters.
I went for the character layout I described previously, a copy of the first 64 characters with the UDGs replacing the punctuation so I could combine them with text.
It looks rather pretty without the UDGs.
Game Mechanics
The rest of the game is a reasonably standard New York Blitz type game, nothing much to report.
The only oddity I found is that if you press the ↑ key it pauses the game until you press another key.
I had a few more ideas of things I could change, but decided not to over-complicate things.
One thing that always gets me with Blitz type games is the plane seems to pause (or in this case disappears completely) whilst the bomb is descending.
There was also the limitation in some games where the plane continues, but you cannot launch another bomb until the previous one has landed.
I did consider writing it so the plane continues and you can launch multiple bombs, but I thought that would add too much complexity.
One thing to note is the original game moves the plane on randomly 0-2 squares when it reappears, I guess to stop you holding down space and flattening the lot.
I also thought about making the plane land faster once you have cleared all the buildings, but that also seemed too complicated. It would need to keep checking if they had all been cleared.
Random Numbers
On the subject of random numbers, that was an interesting challenge in assembler, a random number from 0-5 and a random number from 0-2.
I had code in TimeBomb which was based on a routine George Beckett had dug up (more on that in the article)
That generates a 16-bit random number, as two 8-bit values, but I only needed 0-5.
I did think about masking it using 0000 0110, but that would only give me four values, 0, 2, 4, 6.
In the end I wrote some code to shift the 8-bit number 5 times, and each time add the shifted out bit to a running total.
If the number was 42, that would be 0010 1010, so my total accumulated would be 3.
The range would go from xxx0 0000, which was 0, to xxx1 1111, which would give 5 (as the final three bits would not be shifted out or counted).
That seems to work and gives a reasonable spread of pseudo-random numbers from 0-5.
I drew the towers is a more normal fashion. Starting at a point where the tallest building would be and stepping down 0, 2, 4 or 6 steps based on the random value, then drawing the roof and then stories below until it hits the ground.
This shows each of the four building heights.
Landing
I put that version up on Discord and to the TFW8b team.
One suggestion I got from Andy Hewco was the faster landing after clearing the level that I had previously ruled out.
Looking about it again, I realised I had been overthinking it. I added a counter each time a building was built, and decremented it each time one was knocked down.
When it reached zero, I descend to ground level, then cut the sound and taxi the plane off the screen to the right.
That's About It
The final version is 1688 bytes, still slightly shorter than the 1830 bytes of the original, but there isn't much it in with all the extra text I added.
I think it plays better, there is a bit more info on the screen and the graphics are less flickery. And gone is the startup delay and ££££££££ over-spill and on NTSC there is no misalignment after the first crash (but nothing I can do about the grass colour).
I will be adding that to the Penultimate Cartridge release candidate, but for now I have put this up on GitHub, along with the commented source. All written by me, by hand. No sloppy AI coding, just some hopefully not-too-sloppy human coding.
If anyone wants to give it a go on a real unexpanded VIC20 or your emulator of choice, let me know how you get on and if you have any suggestions or feedback, or any other games you think could be similarly reworked.
Adverts
The VIC20 Penultimate Cartridge +3 DCR is available now from the Future Was 8 bit.
All Tynemouth products are still available, and I can ship worldwide.
Including the limited edition 10th anniversary recreation of the very first Penultimate Cartridge:
International shipping is a bit complicated at the moment, so if you want to order from outside the UK, please contact me using the contact link at the top of this page.
See here for more information:
Sorry to have to do this, and I know this is going to affect sales, but please understand it is the only option I have right now.
Patreon
If you enjoy posts like this, you can support me via Patreon, and get access to advance previews of blog posts, and exclusive posts.
You also get progress updates on new projects and other behind the scenes updates, as well as access to my Patreon only Discord server for even more regular updates, and to discuss your own projects.

































