Sunday, 27 August 2023

Inexplicable Autofire Explained (sort of)

Today we have a Patreon post during the development stages of the Penultimate Cartridge. Trying to fix a problem with a couple of the games.


During testing of the Penultimate+2 Cartridge, many games have been played and tested by many people.

There are too many in the cartridge at the moment, we have a few more to add, so we need to remove some, and are trying to weed out the weakest of the titles currently in there.

Some are down for removal because they aren't very good, or because they are too similar to another game etc.

Some are marked up because they have issues. We could just take those as a given and remove them, but I would like to know what is going on.

One of the games that is a problem is Bandits. Ever since I was asked to add it, I have been reporting that it seems to be stuck in autofire.

This wasn't always seen by the other testers, some of which reported no problem and it played normally.

This has been through various rounds of testing and various theories. One being related to another oddity seen previously, a couple of games with "please stop tape" messages.

In the post on those conversions I mentioned that seemed redundant as the Commodore Datasette had motor control, but it turns out that was due to the way the joystick is read.

OK, here goes.

Ports A and B on the user port VIA chip has various things connected to them:

  • PA0    Serial CLK in
  • PA1    Serial DAT in
  • PA2    Joystick 0 (up)
  • PA3    Joystick 1 (down)
  • PA4    Joystick 2 (left)
  • PA5    Joystick Fire
  • PA6    Cassette Sense
  • PA7    Serial ATN out
  • PB7    Joystick 3 (right)

It may seem odd that three of the directions and fire are on the one port, and the forth direction is on a different port. Indeed it is. Would have made more sense if they were all on the same port, or at least the four directions on one port and fire on the other.

Who knows why they did that. May have been to do with routing the board or a last minute shuffle of pins? But I am sure it has been annoying game developers for 40 years.

The problem is when the game designers for whatever reason expect the values for the other signals to be at some fixed value (as they are on their system), but they are read differently on your system. It should be possible to mask out those bits, but maybe they didn't think that was necessary, or wanted to save space or improve response times.

In simple terms, in BASIC do a PEEK and check the value returned. If fire is not pressed, it read 126, and 94, if fire is pressed. But when the datasette sense line is active (i.e. play is pressed), the values read will be 64 less that those before, so 62 or 30. If you code is checking for 94, it will never detect fire being pressed if the play button is also still pressed.

Also in that 8 bit port are the inputs for the IEC serial CLK and DAT signals. Those can also affect the value read.

If you do a LOAD "$",8 and then repeat the PEEK, you now get 127 instead of 126. Again, if you mask out the bits you don't care about you should be fine, but if you are checking absolute values, it will fail.

As seen in a previous post on IEC fault finding (http://blog.tynemouthsoftware.co.uk/2023/06/diagnosing-iec-bus-faults-on-vic20-c64.html), writing to the output pins affects the values read on the input pins, so again you can break the simple value comparisons.

Testing this theory, Bandits with no IEC device connected works fine. Bandits with an IEC device autofires. If you reset the IEC device, the autofire stops.

I have tried with a datasette, and that made no difference, so it is only the IEC lines

I think we have the culprit. But what is going on?

I went through reverse engineering the process, basically it rotates the byte that is read around to make it easier to test the lower bits, and somewhere along the line, the two versions diverge. 

However, I was not able to pinpoint 1) where the test fails, or 2) anything that could be changed to fixed that.


The hardware level

To test the theory, I setup the scope to monitor the CLK and DAT lines, with a trigger on reset.

Booting up the VIC20 with no cartridge installed. With or without an IEC device connected, at reset (blue), the clock (yellow) and data (green) lines both are pulled low and then released and stay high unless a device on the bus wants to talk.

Booting up the VIC20 with the Bandits cartridge and no IEC device connected is different, but still returns to normal.

Booting up Bandits with an IEC device connected, however, is a problem.

As you can see, clock does not get raised. It stays low, and affects the value read on that port, causing the autofire. The VIC is not pulling CLK low, it is the external IEC device.

If, you reset the IEC device (which was pulling CLK low), it is released and things return to normal. The firing stops.

So let's unpack that.

What is happening is even though the VIC has released CLK and DAT, the external IEC device is still holding down CLK. But why doesn't that happen in normal circumstances?

Well, a series of events happen which clear the bus. This is not happening with Bandits as it bypasses all the standard initialisation stuff and does that it's own way (which doesn't clear the bus properly).

How to fix it?

I have tired various ways, and not found one I like.

The first I tried was to make sure this was actually the problem.

The code is full, so no easy easy way to add anything to the ROM.

I modified the code and replaced the LDA $9111 instruction which reads the port with JSR $2020 (why 2020? well, JSR is opcode 20, so the changed bytes were 20 20 20, and that appeals to my sense of balance)

RAM at 2000 onwards was not being cleared, so I preloaded that with some code:

LDA $9111

ORA #$03

RTS

All that does is read the port, OR the value with 3, which sets bits 0 and 1 high, acting as if both CLK and DAT were high, as they should be. It then does an RTS, and goes back to the original code.

I tried that, and it worked.

I don't plan to use this solution as 1) it affects the timing, and 2) would need a different change for each game (did I mention there were two versions of Bandits, PAL and NTSC, and also the same with Final Orbit, and possibly some other games?).

So, plan B.

I added some code to the Penultimate Cartridge launcher that would do the proper bus initialisation before starting the cartridge, so that it should already be set. However, that didn't work. It seems the way the port is being setup in Bandits is deliberately antagonising the IEC port and failing.

However, oddly, it did fix the problem on Final Orbit, so I have left that fix in place for that game, but I don't understand why Bandits isn't?

Comparing them, they both use loops to write a series of values to 90xx, 91xx and 92xx (the VIC and the two VIA chips).

They are different though, Final Orbit writes 01 to 9111 (port A), Bandits writes 07, although that should have no effect as those pins are inputs.

I have tried changing them and that didn't fix it.

Just as I was writing this up, I remembered about the other address for port A, 911F, and sure enough Final Orbit writes 88, and bandits 80.

Again, changing those made no difference.

It writes them in reverse, from 911F down to 9111, so 911F gets written first, then 9113 (which is the data direction register), then 9111.

So those pins are briefly used as outputs, but set low, so it shouldn't be a problem.

One more thing.....

Another thing I noticed is that maybe there is a bug in the code for Bandits. Shouldn't that be LDX #$0C at $A7Ef ? not LDY?

X is set earlier, but Y isn't used, and X is used as the offset by the LDA and STA instructions. Similar code in Final Orbit uses LDX (and the offsets are slightly different)

I did try changing that, but it still autofires, but now the graphics are messed up.

This one has me stumped. I've spent a bit too long on it now, need to get on with some other stuff and will maybe look at it again later.


I didn't get around to looking at this again, so the versions of Bandits on the release cartridge still has the auto fire issue. If anyone has any ideas how this can be fixed, please let me know.


Advertisements

Penultimate +2 Cartridge

The Penultimate +2 Cartridge, containing Key-Quest for PAL and NTSC, and many other games in stock at The Future Was 8 bit:

More info in a previous post:

http://blog.tynemouthsoftware.co.uk/2023/06/penultimate-plus-2-cartridge.html

See also a great video from Robin, 8 bit show and tell:


Patreon

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.

https://www.patreon.com/tynemouthsoftware