More techniques analysed for squeezing the last few bytes space out of an unexpanded VIC20. Also some more methods of converting these multipart games into single PRG files or CRT images for inclusion in the Penultimate +2 cartridge.
This is another initially simple looking one. Two files in a TAP image, a nice little Defender type game (or is it Scramble type, I can never remember the difference).
The first part loads up, displays a title screen and then loads the second part.
OK, that's going to be an easy one, isn't it?
Based on previous games, I did try just loading and running the second part, but there is more to it than that.
A lot more.
Further investigation shows the first part runs a few lines of BASIC then jumps to some assembler after the BASIC program.
There is also something nice / weird going on that whenever you list the file, it clears the screen and prints up that title.
The first part of code is run from 413 + PEEK(43) + PEEK(44)*256, which is quite neat. It is using the offset from the load address, so it will cope with 0K, 3K or larger expansion RAM.
On the unexpanded VIC20, that translates to address 0x11B0.
The code there does some setup, including copying a block of code to 0x0200. It then does another calculation about where the next block of code is at, which works out to 0x12A8 and jumps there. Why not use a relative branch instruction? Why not just have the code in a contiguous block? Seems to be deliberately obfuscated.
This second block of code at 0x12A8 does more video setup and finally returns to BASIC.
I didn't investigate fully, but it may only have been doing the graphics for that title screen, nothing actually useful for the game.
BASIC then prints the titles and finally a SYS 512 call, this time a fixed address, 0x0200, where code was previously copied.
This code setups the file operations to load the second program, the game itself. Once the second part is copied into RAM (the call to 0xFFD5), it returns to that code at 0x0218 which runs the game by jumping somewhere into the middle of it (0x1830).
I tried a few ways to convert this, my first plan was meant to be a quick fix. I didn't disassemble the rest of the code, but I found the section in the first file which is copied to 0x0200.
I modified that to jump back into the cartridge ROM and copy the second part into RAM and run it. (looks like this screenshot is a later version where I returned to this code at 0x0218 to run the game)
I was worried that it would leave a flash of the white title screen before starting the game, but when I ran it, it did flash up the white screen, but then locked up and went back to a READY prompt.
I tried a few modifications to the code at 0x0200, but in the end I went for the simpler option of copying the first program into RAM, but not actually running it and instead just jumping to the first block of code, which in turn jumps to the second block, and then the RTS instruction will return to the cartridge loader code.
From here it can copy the second program into RAM and jump to the same spot as the original code block from 0x0200 did.
But that didn't work either.
Stepping through the code, I found where it stopped, it tried to jump to some code at 0x03F2.
I don't remember any of the previous code copying anything to 0x03F2?
I went back to the TAP version and ran it and checked what was at 0x03F2.
Ah, OK, some valid code, but how did it get there?
This took me far too long to work out.
The first program did not write to that area. I watched for writes from the second program, but it didn't write there either.
I also looked through the code to see where this was being copied from, but I couldn't find it.
I have seen code that was obfuscated by XOR or negation, but was hoping it wasn't that in this case. (must remember to write that one up)
I put the watch on the full program and tried again, and then I finally saw a write to that area, but it was coming from the KERNAL LOAD routine? How was it doing that?
LOAD was only being called once, and that was to load the second part. That had a load address of 0x1001, the default for an unexpanded VIC20, so whether it is doing the equivalent of LOAD "game",8,1 or LOAD "game",8 it will be going to 1001. The only way it could get to a lower address is to loop around, but it wasn't big enough for that?
I scratched my head for a while, then had one of those "no, surely it can't be that, can it?" moments.
And yes, it was.
That code is in the cassette buffer.
But it isn't in the file, so it must be the overrun at the end of the file.
Code in the overrun of a TAP file in the cassette buffer.
Wow that's quite unusual. I've not seen that before.
I tried saving that block from the TAP file version, then pausing my cartridge version just before it called that code and loaded it back in. And it worked.
I added an extra section to the cartridge loader to copy that block of code into the cassette buffer and it's now working.
That was quite a lot of work, but satisfying to get to the bottom of this little 40 year old mystery.
This one is a Duck Hunt game, as two PRG files in a D64. Hopefully this will be nice and simple.
It is a shooting gallery / duck shoot type game, although there are 10 pages of instructions to tell you that.
Yes, 10 pages.
The final page offers you an opportunity to read all 10 pages again, or load the game.
I don't think anyone reads them anyway, they just hit whatever key is required enough times to get into the game.
The game itself will load and run separately, so I did think about just using that and ignoring the instructions, however, it starts with a plain "PRESS RUN/STOP"
So you don't get an on screen title or accreditation.
That's not great, I like to leave those in where possible, so back to plan A.
Since I had to modify the intro program anyway to replace the LOAD command with a SYS command to load from the cartridge, I made another slight change.
Now it shows the title screen, but then goes straight to the last screen, which now offers a change to read the instructions (which I don't expect anyone will), or go straight to playing the game (which is what everyone will do).
I had a quick look at seeing if I could bypass the "PRESS RUN/STOP" on the first play, but it is using it's own code to read the keyboard, so I just left it as is.
So that's another one done. What lies in wait next time?
A word on copyright.
These games were all released in the 1980s, and as far as we are aware, are not commercially available any more.
The only way to get these games is to buy a copy of the tape in a freezer bag from ebay, which only benefits the ebay sellers, or download free from any number of websites online.
All these cartridge conversions are doing is making access easier. The main points of the Penultimate +2 Cartridge is the RAM expansion, the file browser and things like that, and the TFW8b titles including many new and exclusive titles. This is currently around 25% of the games of the cartridge. Titles like the ones in this post are added to give you more choice and easier access to them. These will, over time be replaced by more new TFW8b titles.
If anyone has any claim on any titles currently in the cartridge, let TFW8b know via the contact form on their website if you want them be removed from future versions of the cartridge.
Penultimate +2 Cartridge
The Penultimate +2 Cartridge with these and a host of other games is now in stock at The Future Was 8 bit:
- https://plant42.co.uk/product/vic20-penultimate-plus-two/ (new site)
- https://www.thefuturewas8bit.com/vic20-penultimate-plus-two.html (old site)
More info in a previous post:
You can support me via Patreon, and get access to advance previews of posts like this and behind the scenes updates. These are often in more detail than I can fit in here. This also includes access to my Patreon only Discord server for even more regular updates.