Saturday, November 14, 2026

Using an Emulator to Fix Stuff - Torch Triple X (Emulator?) - Part something something...

With the Torch emulator working like a trooper I started to wonder if I could use it to help out in some way in the repair of the real thing. As a reminder, the Torch hardware frequently appeared to have problems with the Limpet RAM expansion board. On one occasion I got a bit cross and some force was applied to the Limpet and, bizarrely, that seemed to fix it. This led me to think it was the connectors it used into the motherboard. It, apparently, was not and after a while it became worse and worse until one day, the Torch would not boot.

I wasn't going to take this lying down, so on the somewhat presumptive assumption the Limpet was at fault, I went and created a new Limpet board which, on it's first couple of tests, actually freakin' worked. 

 

Shiny new Limpet board. Yay!

 

Happy days. Working Limpet.. 


But sadly, not for long. Now, the Torch will not get past the initial pale blue boot screen.

 

Sad face. No boot. :(

The LED on the Limpet only flashes once, and frequently, it displays garbage on screen which is similar to that seen waaaaay back when I was first trying to get the Torch booting. 

A few other things I noted before it went into storage while we moved from Crashed Towers to Crashed Tiny Abode:

  • The LED on the Limpet should normally flash four times during a proper boot. 
  • The voltages across the board were very, very low (down to 4.3v in most places).
  • The Torch did boot a few times with a very upsetting bend in the motherboard.

 

The horror - arrrgh!

 

So, my assumption now is that the Limpet is OK and that there is some mechanical issue with the board, or there is a failed IC hiding somewhere either on the motherboard or (potentially worse) on the Limpet. There are several PAL chips that are basically irreplaceable across both the motherboard and Limpet. This is the worst case scenario that I don't want to think about...

Anyway, on Torch startup it appears that there is some sort of RAM test, and I assume this is signified by the four flashes. Then the screen goes dark blue and shows the Caretaker version (this is basically the BIOS) before starting to boot proper. I wondered if we could nail down exactly what the thing was doing whether that might help in the quest to fix it. 

Fortunately, we have pretty much everything we need. We have the ROM, excellent schematics (redrawn by yours truly), a technical manual, and (thanks to the most excellent chap on the VCF forums) a working emulator. 

Torch Emulator - Talking to the outside word!

First things first, let's disassemble the Caretaker ROM.

But to do that, I needed to get a disassembler installed. And for this there is the most excellent (if rather powerful i.e. complex) Ghidra tool, as recommended by such luminaries as Ken Shirrif (a regular contibutor to Curious Marc's youtube channel). Installing this was a little bit of a chore but not too hard considering I was installing it on Pop OS on my new laptop (did I mention I have a new laptop?) which is a variation of Linux.

Once it was installed I threw the ROM in and it just told me everything... Just kidding. I had to install a specific extension to support the 6303 CPU. Even then, Ghidra still needs to be told what to do. And that includes where to load it... For the Caretaker ROM this needed to be at address $C000. The 6303 documentation identified that the reset vector was at $FFFE which then points back to $C2DC and that was the starting point.

 

On your marks! Reset! Go!
 

But that's not all that lurks in the Caretaker. I know that there is a section of bootstrap code for the 68010 main CPU. And to get this I ran the command:

 

Gimme the code.

So now I had another file that could help enormously. At this point I'm fairly certain that the service processor would copy Caretaker into VRAM before doing stuff, including I assume a RAM check, and then handing off control to the 68010. The questions I had were, is the RAM check carried out by the 6303 or the 68010? Is the RAM test just the VRAM or does it include the main system RAM? If the system RAM, how does it know if there's a Limpet installed? 

The first major discovery was around the 6303 service processor's diagnostic error-reporting routine. At address $C087, Caretaker enters an error handler that initialises several timing parameters before repeatedly calling a routine at $C277. That routine read the diagnostic byte store at $00B9.

But how it interprets that byte is really interesting.

Each diagnostic message consists of four beeps, with two bits controlling each beep:
- The first bit determines whether the beep is short or long.
- The second bit determines whether the pause following it is short or long.

For example, error $21 is binary 00100001. This produces short–long–short–short, with a longer pause after the fourth beep to separate each four beep sequence. That tied up with what I was seeing when the Torch wouldn't boot either with the Limpet (long-short-short-short) or without the Limpet (short-long-long-long).

The HD6303 generates these sounds using its internal timer and output-compare circuitry. The original Caretaker manual confirmed the codes identified in the disassembly and meant that Ghidra was on the right track. :)


Code    Beeps   Description
$01     SSSS    ROM checksum error
$03     SSSL    Video controller faulty
$09     SSLS    RTC stopped
$0B     SSLL    HD6303 internal RAM error
$21     SLSS    Video RAM fault
$23     SLSL    HD6303 serial port timer failure
$29     SLLS    VRAM inconsistent with copied ROM data
$2B     SLLL    Main CPU timeout


This didn't solve the code that I was seeing with the Limpet attached (long-short-short-short) but it might appear somewhere else in the code maybe (foreshadowing...).

Next thing, how the first part of RAM is tested. In actual fact, the 6303 tests the video RAM through a 32KB window located at $4000 to $BFFF and uses bit 2 of its port 1 register to determine which bank is being checked. The firmware writes a test pattern into both banks before reading the data back and comparing it.

The pattern is generated using:
         

        Next byte = (225 x Current byte + 205) mod 256

 

If any comparison fails then Caretaker stores $21 at $00B9 and runs the diagnostic routine i.e. it starts the four beep message, in this case for Video RAM fault.

The next big breakthrough was working out how error $2B gets initiated. This is one I'd seen many, many times (short-long-long-long) almost from day 1 of having the Torch. What happens is that Caretaker does the following:

 

Release the hounds, err, 68010 actually.

 

This code snippet selects VRAM bank 1, writes $FF to $BFFF, and releases the main processor by clearing Port 1 bit 3.

The service processor then repeatedly reads $BFFF, waiting for the value to change, which indicates the main CPU has started doing stuff (or not).

There are three outcomes:

Value              Meaning
$FF                Main processor has not yet responded
$00                Main processor has successfully acknowledged startup
Other value        Main processor has returned a diagnostic code


If $FF remains unchanged until the timeout expires then Caretaker generates error $2B and triggers the diagnostic routine. But if it does change to another non-zero value, then could this be the undocumented 'long-short-short-short' beep error message seen when the Limpet is connected?

Based on what we know about the beeps it's easy to see that 'long-short-short-short' should work out as '10000001' or $81. So, where does this come from? Is it a random number the just so happens to end up in $BFFF? Or is it a specific value that is inserted by some part of the system?

The answer was relatively straightforward.  

Although the HD6303 code we'd examined didn't explicitly generate it, I suspected that the 68010 might be returning the value through the video RAM or main RAM.

To test this, some logging was added logging to the emulator around the $BFFF handshake.

That produced:

[BFFF] SP WRITE PC=C54F bank=1 host=0FFFF old=81 new=FF
[BFFF] SP P1.3 PC=C552 old=1E new=16 host_release=YES
[BFFF] HOST WRITE PC=001011FA logical=0000FFFF physical=0FFFF old=FF new=00
[BFFF] SP READ PC=C55A addr=BFFF bank=1 host=0FFFF actual=00 returned=00

 

This is basically the processors (virtual in the emulator) communicating with each other. The HD6303 wrote $FF, released the 68010, and subsequently received $00.  

Interestingly, the initial behaviour in the emulator was a lie. The emulator had a bit of a shortcut that basically checked the value three times and then just returned '00'. Cheeky. There wasn't actually a need to do this as the code was written to process the communication properly and a quick modification to remove the shortcut was made, and the emulator still booted. Nice.

And now the smoking gun. Disassembling the 68010 bootstrap code revealed:

        0000004A  move.b  #$81,$0000FFFF
        00000052  bra     $00000052 

 

Bingo! The 68010 explicitly writes diagnostic $81 to the memory location monitored by Caretaker, then enters an endless loop. Tracing backwards revealed the reason for this. Immediately before reporting the error, the processor compares a value read from main RAM against an expected test pattern: 

        00000042  cmp.l   (A0)+,D1
        00000044  dbne    D0,$00000042
        00000048  beq     $0000003E
        0000004A  move.b  #$81,$0000FFFF

 

If the comparison fails then, boom!, $81 is written to $FFFF and the 68010 checks out into an infinite loop.

Weirdly, there is also another diagnostic value of $83 which converts to long-short-short-long. I haven't figured out what could trigger that yet...

Anyway, digging further into the 68010 code shows that the main RAM is tested by two passes, the first writing a pattern of 5A5AA5A5 and the second a pattern of A5A55A5A. Rather strange though, the code doesn't know how much RAM is present. It starts the test at $100000 and then just keeps going up until there is a bus error which indicates the end of available RAM. Then it repeats with the second pattern. Very odd but very clever as it means the system can use any amount of additional memory (although I'm not sure what any limit might be..).

Once the two sweeps are complete it writes $00 into $0000FFFF to tell Caretaker the RAM check is complete and all OK.

To check that all this was as expected, the emulator got another modification to deliberately put an error into the RAM test. At address $100000 instead of '5A' the value '5B' was inserted. The results were:

        [RAM-FAULT] First verification pass:
        physical $00100000 5A -> 5B

        [BFFF] HOST WRITE PC=00000052
        logical=0000FFFF physical=0FFFF old=FF new=81

        [BFFF] SP READ PC=C55A
        addr=BFFF bank=1 actual=81 returned=81

 

In other words, it's gone pear shaped! Stick $81 in $0000FFFF!

And the emulator also made the same beep pattern (but a little bit quicker) of long-short-short-short but also showed garbage on screen.

 

Beep, beep, beep, beep (I'm a sheep)

And this is very, very similar to the garbage that the real hardware presents when it's switched on:

 

It's the real thing...

 

So, where does that leave me? Well, I now have a much better understanding of the 'long-short-short-short' beep diagnostic. It indicates that the main 68010 has encountered a RAM readback mismatch during the main RAM tests. That could result from faulty memory chips, but also from problems elsewhere in the memory-access circuitry (address decoding, data buffers, RAM multiplexers or timing/control signals etc).

The Limpet expansion changes the physical configuration of the system, and the bootstrap tests whatever contiguous RAM the hardware makes available, but I can't run the system without it due to the missing U169 chip - which the Limpet effectively replaces. 

So I still can't say whether the failure is in mainboard RAM, Limpet expansion RAM or shared circuitry affected by fitting the Limpet.

But it does mean that my hardware tests can be much more targeted now that I have some idea on how the Torch actually starts up. I'll be using the oscilloscope and logic analyser to have a closer look at:

  • The 68010's /AS, R/W, /UDS, /LDS and /DTACK signals.
  • The DRAM /RAS and /CAS0–/CAS3 signals.
  • Memory address activity during writing and verification.
  • How the Limpet changes memory selection or bus acknowledgement (maybe allowing me to put something in to replace the missing U169)

 

Now, if the weather would just get a bit warmer and I could get over COVID (again), that would be great. 

 

 

No comments: