Bypassing copy protection in old RISCOS software

Several months ago I became nostalgic about games I got the chance to play at school (aged about 9). Back then the school I went to hadn’t moved over to IBM PC – but had a suite of BBC Micro‘s and Acorn Archimedes computers. Unfortunately for me this made “scratching the itch” of re-playing these games somewhat more complex.

It’s not too hard to get a virtual Acorn computer up and running thanks to RPCEmu , however it took me several months to get hold of some of the games I remembered playing:

  • Sherston Software – Time Detectives The Victorians
  • Sherston Software – Aztecs
  • Sherston Software – ArcVenture I-IV (Probably Romans, but potentially others)

Whilst I’m still searching for Aztecs, I did manage to source the others. The next challenge became getting the physical floppy disks accessible to RPCEmu. After plenty of research, it turned out that none of the computers I have access to have a real Floppy Disk controller any more (and USB floppy drives wont work, as they expect an IBM PC disk geometry). I decided to pick up an old TEAK floppy disk drive and build myself a FluxEngine – This is a great project which allows you to read and store the magnetic signals from the disk.

Armed with my disk images created by FluxEngine, I was then able to install these games on my virtual Acorn. I was certain this would be the last hurdle, unfortunately for me – it wasn’t.

It turned out that even early-90s educational software came with copy protection. My understanding is that this relies on expecting to read or not read content from the disk (e.g. based on intentionally invalid CRC checks). Emulators really only work with the data in the image file, which doesn’t really capture this (although the FluxEngine copy does, the conversion to a format usable by RPCEmu loses this data). This left me with the option of either buying a physical Acorn Archimedes, or bypassing the copy protection.

Time Detectives – The Victorians

I decided to start with the game I remembered most fondly, Time Detectives. Luckily this was also the most straightforward to get working. RiscOS has application folders in a similar manner to MacOS, shift-clicking into an application folder displays additional files. After an hour or two poking around in BASIC code and associated scripts, a single line of code could be commented out to bypass the checks.

Bypassing !Runimage for Time Detectives so that it can run in an emulator

If you’re looking to get this working too, you can add “REM” to the start of “quit%=NOTFNpalset” in !Victorian.!Runimage

Hurray! Some 20+ years later I got to complete a game I remembered so fondly

ArcVenture I – The Romans

After managing to locate the original author of the ArcVenture series, he kindly provided me with the images of all ArcVenture games so that I could bypass the protections and return them to him with the protections bypassed.

Sherston Software had stepped up their copy protection efforts for the ArcVenture series – getting increasingly more complex as the series went on. After several efforts commenting out bits of BASIC code, I eventually narrowed down the copy protection to a binary “module” named ShAlloc. Thankfully there’s a really nice hex editor available for RiscOS named !Zap that made disassembly a breeze.

After getting my head round the ARM instruction set and RiscOS’s built-in debugger I was able to load the module, set a few breakpoints (on the XADFS_DiscOp calls) to figure out the execution flow. My best-guess to bypass the protection was then to modify the branch instruction at 0x208 (as shown above).

If you’re looking to liberate your ArcVenture I disk, you can modify !AVStart.ShAlloc at 0x208 to branch to &00000178.

ArcVenture II – The Egyptians

The Egyptians used similar methods (Calls to XADFS_DiscOp), however they were better obscured. Checking !AVStart.!RunImage the startup module is a binary file, with lots of garbage instructions in it. After some head scratching I realised the binary had probably been compressed in some way and was probably de-compressed in memory.

Fortunately, research led me to “!UNSQUEEZE” (Written by Colin R. Smale).Once decompressed, the binary could be examined more easily. Unfortunately this still left a large file which would be difficult to debug with the built-in RiscOS tools, enter !DDT

!DDT is an interactive Debugger, allowing you to more easily set breakpoints and step over instructions. I stared by setting breakpoints on calls to XADFS_DiscOp and then making notes of branch instructions before and after those calls. After several hours of trial and error I settled on a branch instruction to patch and was rewarded with success!

If you’re looking to bypass the protection, you need to decompress !AV2Start.!Runimage and modify the instruction at 0x81A0 from “BL &0000D84C” to “BL &000081A4”. You can then optionally re-compress with SQUEEZE.

ArcVenture III – The Vikings

The Vikings used XADFS_DiscOp, but did so without external files. Instead BASIC was being used to load words into memory and execute them. This took me some time to spot, eventually identified by adding “TRACE” commands to the basic file to spot where execution was stopping.

After the closing square-bracket I added the following to dump the relevant memory to disk so I could disassemble.

OSCLI "Save AV2-Test "+STR$~(palcode%)+" "+STR$~(P%)

This left me with a ARM binary that I could work my way through and patch, then translating the change back to the words being loaded by !RunImage.

I settled on two changes this time. My changes was to make the following changes to !AV3.!RunImage:

On BASIC line 4316, change EQUD &EB000029: to EQUD &EB000025:
On BASIC line 4317, change EQUD &EB000025: to EQUD &EB000021:

ArcVenture IV – The Saxons

This was by far the most complex of the ArcVenture series to bypass. I must have spent a day or more single-stepping through with !DDT (made even more frustrating due to frequent !DDT crashes). Again, !RunImage had been compressed with SQUEEZE.

This time the entire game had been written in C (rather than BASIC, with protection written in machine code). This meant that debugging required stepping through a single large binary. I dread to think how many different breakpoints I’d set, but eventually succeeded!

To reproduce this, you need to change !AVIV.!RunImage at 0x2F178 from “BL &0002FD20” to “BL &0002F184”.

And so there we have it. All that remains if Aztecs. I’d love to get a copy to poke around – so please get in touch if you can source one.

Published by

Dave Hope

Dave is a Principal Software Analyst for a UK based retirement developer, in his spare time he enjoys digital photography and rock climbing.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.