Tracking down crashes related to the Action Replay bank switching hardware

A few days back Flavioweb and I were having a chat and he mentioned that Jazzcat reported a crash for one of his releases. Here’s the actual comment on the crash:

Crashes with Action Replay 6 ROM after leaving intro in VICE 3.6.1 (r41663) x64. Have not tested on real hardware.

I joined the effort to track the root cause of the crash. The code used to handoff execution from the intro to the linked game looks as per below:

        LDA $DD0D
        CLI
        LDX #$00
        TXA
        TAY
        JSR $A871        ; Perform the RUN command
        JMP $A7AE        ; Next statement

When executing the RUN command, the BASIC interpreter comes across the SYS instruction and eventually executes code at $AE83:

        JMP ($030A)

The standard value at $030A/B points to $AE86, which gets the arithmetic element into the floating-point accumulator. When the Action Replay 6 fastloader is installed, it sets such vector to $DFB1. Therefore the fix seemed simple enough: just restore the vector at $030A/B before handing off execution to the linked game.

However, it wasn’t clear why the crash would not happen with any other emulator or version of VICE. The crash would not even occur while using the U2+ with the Action Replay 6 ROM active on real hardware, but it would occur with an Action Replay 6 on real hardware.

A day or so later, Flavioweb shared the details of another really strange crash: while making changes to one of his crack intros, changing the value at $071C (in the Video RAM) from $20 to $A0 caused a crash with the Action Replay 6 fastloader active. $071C is not even a vector so the crash looked really strange. Armed with patience, Flavioweb rebuilt the crack intro iteratively, starting from the initialization and exit code, adding IRQs for screen transition effects and music playback. It was towards the end that he identified the offending instruction (used for timing):

        BIT $DEAD

At that point a light bulb went off in my head: I knew exactly what was going on. The instruction BIT $DEAD causes the address $DEAD to appear on the address bus of the C64, which in turn causes the assertion of the /IO1 line of the cartridge port (it goes from 5V to 0V briefly). Whenever the /IO1 line is asserted while Phi2 is high, the bank switching hardware of the Action Replay 6 latches the value of the data bus and makes adjustments.

As an example, the below code has the unintended consequence of causing a hardware reconfiguration of the Action Replay that results in an unwanted bank switching:

        LDA #$24
        STA $D0XX
        NOP
        NOP
        NOP
        NOP
        BIT $DEAD

Update: see this comment by schumi for an accurate description of the actual value latched by the AR hardware.

In the above example, the Action Replay will latch the value $24 upon seeing /IO1 asserted with Phi2 high and it will interpret it as a request to reconfigure, according to the below (taken from VICE’s code, src/c64/cart/actionreplay.c):

io1 (writes)
    7    extra ROM bank selector (A15) (unused)
    6    1 = resets FREEZE-mode (turns back to normal mode)
    5    1 = enable RAM at ROML ($8000-$9FFF) &
             I/O2 ($DF00-$DFFF = $9F00-$9FFF)
    4    ROM bank selector high (A14)
    3    ROM bank selector low  (A13)
    2    1 = disable cartridge (turn off $DE00)
    1    1 = /EXROM high
    0    1 = /GAME low

Of particular concern are bits from 2 to 5 of the data bus. As an example, setting bit 5 disables ROM memory mapping at $DF00, meaning that the Action Replay fastloader vectors that point to an address in the $DF00-$DFFF area now all point to “dirty” RAM memory contents and can cause a crash.

VICE version 3.6.1 is the only emulation solution that seems to act exactly as the real hardware does in the above scenario.

The final fix? For timing purposes don’t use the area $DE00-$DFFF as it might interfere with the bank switching hardware of cartridges. My favourite alternative would be:

        BIT $BEEF

About Luigi Di Fraia

I am a Senior DevOps Engineer so I get to work with the latest technologies and open-source software. However, in my private time I enjoy retro-computing.
This entry was posted in Retrocomputing, Technical and tagged , , , , , . Bookmark the permalink.

2 Responses to Tracking down crashes related to the Action Replay bank switching hardware

  1. schumi says:

    The explanation isnt 100% correct – the value the AR latches is whatever was on the databus in the previous halfcycle – usually this is what the VICII fetched.

    Also, next time try looking at the VICE log – it actually prints a warning when this happens 🙂

Leave a comment