Sunday, 9 March 2025

Finally Fixing VIC20 Tornado

One of the early requests for games to add to the Penultimate Cartridge was a game called Torndao (from TFW8b himself). It's quite a nice Defender clone (or is it Scramble, I get confused)

The only problem is, it is broken.

Apparently it was like that from day one.

It has been broken since 1982.

It has always been broken.

What happens is it locks up. Usually after a few seconds.

But it is not consistent. Sometimes it plays fine, other times it locks up.

That's easy to fix then, wait until it locks up and then debug what is going on.

Well, no, you see rather frustratingly, the other problem is that is always works in Vice.

I have tried all sorts of things to make it break, initialising memory to 00, to FF, to random, different models, memory settings, ROM sets. etc. All work flawlessly every time.

Whenever we look at adding new things to the Penultimate Cartridge, we draw up a list of potential candidates to be removed. Tornado is always on there, but always gets saved because when it works it's not a bad little game.

That's where we are now. For me, it had been failing pretty much every time, but TFW8b had a bit of a run of it working. It is not consistent.

As part of some other testing, TFW8b asked the team to run through loading it multiple times, and keep a note of how many times it worked, so we could judge if we could justify keeping it.

One of the testers took things a bit further, and tried all sorts of combinations. I was getting the results second hand, but I was a little dubious of their findings.

It sounded to me a bit like "it only works when I wear my red jumper". Correlation does not imply causation.

The theory was, it always fails after running the game Final Orbit (and later several others were added to this list).

I was dubious because I could not see how the two things could affect each other. Between playing Final Orbit and loading Tornado, you would have gone through the menu. That means two reset cycles and various changes of memory mapping and memory been overwritten.

That can't have any affect, can it?

TFW8b did some testing and it seemed that there might be something in the theory - Tornado always crashed after you had loaded Final Orbit.

OK, I thought, let's try this out

I loaded up Final Orbit in Vice and played that for a bit.

I then changed the cartridge image for Tornado and tried that.

I selected 1 player and it started up.

As usual, it started moving.

Scrolling along for a bit.

And then it stopped.

It had locked up.

In Vice.

This was the first time I had seen it lock up in the emulator.

OK. Do not touch anything! Let's find out what is going on.

.C:18e0  AD 14 91    LDA $9114

.C:18e3  29 0F       AND #$0F

.C:18e5  A8          TAY

.C:18e6  B9 4A 19    LDA $194A,Y

.C:18e9  C5 36       CMP $36

.C:18eb  D0 F3       BNE $18E0

It seems to be stuck in this loop, going around and around.

It loads VIA #1, Timer 1 low byte from $9114. Masks off the upper nibble to leave a number from $00-$0F. It then uses that to index a table at $194A.

>C:194a  01 02 01 02  01 02 ff ff  ff ff ff 00  00 00 00 ea

It compares this with the value at $36 and if it does not match, it keeps going around the loop. 

And it never matches.

The value from the timer seems to go through the same cycle of even numbers $0E, $0C, $0A, $08, $06, $04, $02, $00 etc. (OK, no matter how much I know it is true, I refuse to accept A, C or E are even, they just look like they should be odd numbers, probably since I am used to thinking of them as the first, third and fifth letters of the alphabet.)

The value of $36 remains constant at $02. The only time this would trigger is if the value of the counter was $01, $03, or $05. That would return $02 from the lookup table and there would be a match.

So there it sits in its loop. What is going on?

There are four registers in the VIA that refer to timer 1.

  • $9114 - Timer 1 low order counter
  • $9115 - Timer 1 high order counter
  • $9116 - Timer 1 low order latch
  • $9117 - Timer 1 high order latch

The 16 bit value in $9114 and $9115 counts down until it reaches zero, then it loads the values from $9116 and $9117 and starts counting down again. It counts at the CPU clock rate, 1.023MHz on NTSC systems, 1.108Mhz for PAL. The maximum count if $FFFF, so a maximum cycle time of 64ms (NTSC) or 59ms (PAL).

The values in the version that had locked up were:

>C:9114  08 27 00 aa

The timer was currently at $2708, and would count down to $0000, then be reset to $AA00.

In a separate window, I opened another Vice session and loaded Tornado without having first loaded Final Orbit (or put on a red jumper).

This worked, as it normally does, so I checked the values of the timer.

>C:9114  ac 64 ff df

That one was currently at $64AC, and would reset to $DFFF

I went back to the locked up version and changed the value of $9116 to $FF and kept watching. After a cycle or two, the value of the timer came back as $05. The value from the lookup table was $02. That matched the value at $36 and away it went!

Why were the values different?

I looked through the code, and I couldn't find anywhere that it actually set those values. Ah, is that it?

But surely they get reset by the VIC20 startup code?

Well, no. I thought they did. Most of the other registers are set to appropriate values, but the timer is not initialised.

It seems that Tornado is relying on those values being something reasonable. But what is reasonable?

.C:18e0  AD 14 91    LDA $9114    (4 cycles)

.C:18e3  29 0F       AND #$0F     (2 cycles)

.C:18e5  A8          TAY          (2 cycles)

.C:18e6  B9 4A 19    LDA $194A,Y  (4 cycles)*

.C:18e9  C5 36       CMP $36      (3 cycles)

.C:18eb  D0 F3       BNE $18E0    (3 cycles)*

Looking at the timing, it is taking 18 cycles going around that loop (it would be more cycles if either of the * functions crossed a page boundary, but neither do). That makes sense, if the first sample was at $00, next time it was checked, it would have counted down by 18 decimal, $12, so would be $EE. 18 more cycles and it would be at $DC, then $CA, $B8, $A6, $94, $82, $70, $5E etc. When the top nibble is masked off you get the sequence we saw previously $0E, $0C, $0A, $08, $06, $04, $02, $00 etc. on and on.

I think it is always going to get stuck in that same pattern, going up two at a time, always even, never odd.

Over on the copy of vice where it was working, it would get to $0000, following that pattern, and then would reload to $DFFF. The next time it checked, it would get $ED, then $DB, $C9, $B7, $A5 etc. Bingo. Odd numbers. The value would match the lookup table and the game would continue.

So it turns out, the "reasonable" value we need to initialise it to is "anything odd" (and probably greater than 15). When the number is odd, it will cycle between odd and even numbers and so it will never get stuck with all even numbers. If the reset value is even, all the cycles will be even, so it will get stuck in the loop.

At power on, those registers contains some unknown values. If you run Tornado it will lock up if that value is even, run fine if it is odd. 50:50 change of success in an ideal world, in practice it seems some machines may be more likely to settle on a certain value, maybe odd, maybe even. It may work, it may not.

If a game (i.e. Final Orbit) sets those values to something different it may always work, or always fail, depending on what those values are.

I couldn't find anything in the manufacturers datasheet saying what those values were initialised to. Other than the WDC version which states

Reset clears all internal registers (except T1 and T2 counters and latches, and the SR).

So the power on values are random, probably most likely to float high.

I had a look at the vice source code, and it resets those values to $FF at power on. Seems reasonable.

Rather than make any changes to Tornado itself, I thought it would be better to add some code to the Penultimate Cartridge menu. That will load those registers with $FF, in case any previously loaded games have changed them.

The counters cycles through tens of thousand times a second, so the value when a game loads is dependent on when the user navigates the menus. Effectively random, just in case any of them use that to seed their random number generators.

I have tested loading Tornado from the updated Penultimate Cartridge dozens of times now from cold starts and with various games loaded first (including Final Orbit) and it has always worked. Even with my red jumper on.

Thanks to Tim for persistence in testing, apologies if I initially doubted your theory.

I have sent the updated ROM to TFW8b, and that is being sent on to the testers. As far as I can see, I have finally fixed Tornado after 43 years, and hopefully haven't broken anything else in the process.

Rod has made a video playing through Tornado on the updated cartridge and everything is working nicely.


Advertisements

The new Penultimate +3 with built-in SD2IEC drive and Turboload (and a working Tornado) is shipping now from TFW8b.com.


Tindie

Minstrel 2 and 3 kits are available from my Tindie store, with worldwide shipping. Versions avaiable for ZX81 case or standalone with keyboard, and also Misntrel 3 with ZXpand microSD card interface (andn now available as PCB only).

I will slowly be moving things over there from my SellMyRetro store, so if there is anything that you want, let me know and I'll add it.

Patreon

You can support me via Patreon, and get access to advance previews of posts like this and behind the scenes updates. Patreon supporters had advance notice of this new feature, and are currently getting a run of posts as I catch up after spending the last few months testing Turboload. This also includes access to my Patreon only Discord server for even more regular updates.

Sunday, 2 March 2025

Penultimate +3 Turbo - VIC20 Fastload

TL;DR

The Penultimate +3 Cartridge is now the Penultimate +3 Turbo, and has a built in fastloader, the speed of which is comparable to JiffyDOS (without having to open your machine or lose access to your datasette drive). Get yours now from TFW8b.com.

The long version

In the development folder for the Penultimate Cartridge, there is a text file with a list of features and games to add, things I have thought of, or ideas from TFW8b, suggestions from Patreon and social media, messages to support etc. Each time I revisit the code, I go through that and see what we can add next.

One thing on there that kept getting pushed back was a fastloader. This is something on the list of "it would be nice to add, but might take a long time or may not even be possible" - TFW8b has added quite a few pie in the sky ideas in there.

One reason I had pushed the fastloader back, is I have history with it. I spent several months in 2017 reverse engineering and disassembling the Epyx Fastload cartridge, with an aim of producing our own improved version.

Dubbed the "Epic Fastload" (see what I did there?), it was very close to production, but never quite made it over the line.

Hardware wise, the Epyx Fastload was not always the most compatible with non-standard machines. It relied on keeping a capacitor charged to keep the ROM overlay enabled, topped up by accessing specific addresses. The speed of discharge of that capacitor, and the logic level it switched at, were down to the PLA, and I am sure you know how many different variations of those there are these days. All sorts of different implementations with CPLD, FPGAs, GALs, EPROMs etc. (I am sure someone will do one with a Raspberry Pi one day, if they haven't already).

(My GAL based PLA replacement from 2015, another thing that I didn't think was good enough to release as it was not 100%)

To try to make the Epic Fastload it more compatible, I changed to use a flip flop to enable or disable the ROM. And it almost worked, but there were some weird timing issues, and problems remembering states when dealing with interrupts, particularly the scan line interrupts.

As you can see, I went through quite a few variations trying to find the best way to do it.

We even got as far as getting the production boards made, although I got overruled on the name, these were called FutureLoad (everything was "Future" at that time). (Rod likes to remind me of my failure of that project from time to time. Sorry Rod)

But it wasn't to be. I couldn't get a version that I was happy was good enough to go. It worked most of the time on most machines, but that's not good enough.

I have revisited it a few times since then, but it has mostly been sitting in a box in the back of the cupboard.

Roll on to 2024

Another feature that is on the "one day" list for the Penultimate Cartridge is a freezer cartridge. To that end, in the last hardware revision, I added a way to use the second half of the RAM chip (which was previously unused). My plan was that could be useful for a freezer cartridge, giving it an area to work in, or to backup to.

Since that was there, and the freezer cartridge wasn't likely to happen any time soon, I made that available to the user in a special mode that TFW8b dubbed "enhanced mode". This allows the user to select between the full 35K expansion RAM, and a second full bank of 35K. The base memory in the VIC20 remains fixed, so any code which switches banks needs to be in the base 5K of RAM.

I was speaking to Robin Raymond (who wrote the C64 game "Kingdom of the Seven Stones") about a future VIC20 game that could make use of this and how that could load in one bank full of data, switch banks and then fill the second and then set the game running.

One issue with that is it will be quite slow loading from disk on a VIC20. I told him about the fun I had with the fastload and said it would be interesting to see if that could be adapted for the VIC20. I was busy testing the next release at the time, so I sent him my reverse engineered version of the Epyx fastload code to see if he could get that running on a VIC20.

I was rather surprised to hear a few days later that he had got it running. The VIC20 does not need to deal with switching the ROM in and out, scan line interrupts, or the processor state register.

There were still various issues to resolve, I will go into them in a separate post, lots of little things like squeezing it down into 1K and dealing with the various clock frequencies of the different Vic models.

We spent the next couple of weeks sending versions back of forth, trying to improve it, make it smaller, speed it up.

But, by the end of that, we had a version that I could fit into the 1K that was available at the time.

Then followed lots and lots of testing (which is what I have been busy with recently).

I found (and fixed) several issues, and it is now working on everything I have tried.

Well, with two exceptions. The Pi1541 and the 1581.

Other than that, it works on the main targets, the built-in SD2IEC and real 1541 disk drives. Since it is using a version of the Epyx fastload protocol, it is supported on existing SD2IEC devices as well.

This video from Rod shows how it compares when loading the VIC20 version of Elite.

You can see immediately how the splash screen loads in comparison to the standard loader.

  • New VIC20 TurboLoad - 9.07s
  • JiffyDOS - 8.53s
  • Standard VIC20 - 76.56s

About 8x times faster that standard, pretty much the same as Jiffy DOS, I am happy with that. JiffyDOS is great, but requires opening the case and desoldering the ROM chip and also losing your datasette drive (unless you fit a switch to go back to the standard ROM).

This works from the built in file browser without any modifications to the VIC, and without losing your datasette port.

It can be disabled using the T key, which is now on the menu screen where help used to be.

Now you can see the bits I had to censor in the previous post on the new help pages.

Files selected in the file browser will load with the turbo load by default, and it will remain resident after loading the first file (so will work for multi-part loaders).

It is not enabled by default when you exit to BASIC. To activate it, you type

  • SYS 40000

I was pleased with that, hopefully it's easy enough to remember, SYS 4 and 4 zeroes.

From that point it will remain resident until reboot. It will speed up any file loads using the LOAD command or the standard kernal calls.

It does not speed up anything else, save and other disk operations will remain at normal speed. Also directory load for complicated reasons, although we have a solution for that in the works.

Roadmap

Things might get a little confusing at this point. Things were planned for the future, but this is too good to not add it as soon as possible.

Penultimate +2 (now)

This was frozen at 7.47 and will not be getting updated with the Turboload.

Penultimate +3 Turbo (now)

The Penultimate +3 is currently shipping with this version of Turboload, and has been for a couple of weeks now. This version has a built in SD2IEC with a microSD card.

Penultimate +3 Turbo DCR (Q2 2025)

This is the single board version of the Penultimate +3, with the SD2IEC integrated, and will have a full size SD card. This version is expected Q2 2025, the prototype boards are currently in production. More features to come in this one, and it should end up slightly faster than Jiffy DOS. (named the DCR after the C128 DCR which was similarly combined mainboard and disk drive, although we have no plans to put it in a metal box. Yet.....)

Penultimate +4 (2026+)

This is likely to be some time in 2026, and will be all new hardware, I have been wanting to upgrade various bits for a while, and I think the DCR will be squeezing that last possible drops out of the current chipset.

So, consider this a heads up, it might be a good time to stick your Penultimate cartridges on ebay and get one of the new ones.


Advertisements

The new Penultimate +3 with built-in SD2IEC drive and Turboload is shipping now from TFW8b.com.


Tindie

Minstrel 2 and 3 kits are available from my Tindie store, with worldwide shipping. Versions avaiable for ZX81 case or standalone with keyboard, and also Misntrel 3 with ZXpand microSD card interface (andn now available as PCB only).

I will slowly be moving things over there from my SellMyRetro store, so if there is anything that you want, let me know and I'll add it.

Patreon

You can support me via Patreon, and get access to advance previews of posts like this and behind the scenes updates. Patreon supporters had advance notice of this new feature, and are currently getting a run of posts as I catch up after spending the last few months testing Turboload. This also includes access to my Patreon only Discord server for even more regular updates.