Amiga cracking

"Alcatraz" (c) 1992 Infogrames

Things you will need:

1. The original of "Alcatraz" (c) 1992 Infogrames. The CAPS (SPS) version (number 2073) is the one I’ve used here.
2. An Amiga or a copy of UAE.
3. Action Replay 3 cart, or rom for use with UAE.

This time our target is a novella/code protection – the sequel to popular action game "Hostages", this time called "Alcatraz". Making a copy of the 2 disks reveals that there is no disk protection whatsoever, despite the presence of this string in the bootblock:-

So of course the first step is to let the game load as normal, and get a look at exactly what kind of protection check we are dealing with…and eventually, we see a code-entry screen like this:-

It’s a joystick-controlled code-entry scheme, the codes are 3 digits long and can only contain the numbers 1-4. This clearly means that we can’t simply look at the key-irq or key-input routines to find the section of code dealing with the protection, nor can we search for a string that we entered in memory…
The easiest way to find the right area of code to look at, seems to be to find the text asking us to enter our code. The message reads:-


…where xx and yy are whichever numbers it is requesting this time around.

So we hop into the AR via the magic button, and do a string search looking for the "for line" part of the code request text:-

As you can see, the string was found at $17BE4. Then we look for code that references the part of the string where the line number is (because we know this is not fixed, so the game has to write it there once it has decided which line/column to ask us for). A quick count shows that we are looking for references to $17BED, so we use the ‘FA’ command and find only 1 match… it’s time to start disassembling the code around $17976. We can see that the code found just writes the ascii version of the code into the code request text (as we would expect!), but where is it fetching this value from? If we disassemble a few lines back, we see the following:-

017906  CLR.W $000169A0
01790C  BSR.W $00016314
017910  TST.W $000169A0
017916  BEQ.B $0001790C
017918  BSR.W $00016314			;generate 'random' number
01791C  AND.W #$00FF,D7
017920  CMP.W #$000A,D7			;value must be 0-10 range...
017924  BGE.B $00017918			;...or we go back and do it again
017926  ADD.W #$00000001,D7
017928  MOVE.W D7,$00017D0E		;save this (COLUMN)
01792E  BSR.W $00016314			;generate 'random' number
017932  AND.W #$00FF,D7
017936  CMP.W #$0014,D7			;value must be 0-20 range...
01793A  BGE.B $0001792E			;...or we go back and do it again
01793C  ADD.W #$00000001,D7
01793E  MOVE.W D7,$00017D10		;save this (LINE)
017944  MOVE.W $00017D0E,D0		;fetch COLUMN value
01794A  ADD.W #$0040,D0			;convert value to ascii "A" to "J"
01794E  LEA.L $00017BCD,A1
017954  MOVE.B D0,(A1)+			;and write it into the code request text...
017956  LEA.L $00017BF7,A1
01795C  MOVE.B D0,(A1)+			;... at the 2 places it needs to be
01795E  MOVE.W $00017D10,D0		;fetch LINE value
017964  BSR.W $00017662
017968  ADDA.W #$00000003,A0
01796A  LEA.L $00017BC3,A1
017970  MOVE.B (A0),(A1)+
017972  MOVE.B $01(A0),(A1)+		;and write it into the code request text...
017976  LEA.L $00017BED,A1
01797C  MOVE.B (A0),(A1)+
01797e  MOVE.B $01(A0),(A1)+		;... at the 2 places it needs to be

Well, that part was simple! In fact no need to do any breakpoints or messing around, the code is as human-readable as you’ll find in any game. Our next step is to find code that references either $17D0E or $17D10, now that we know this is where the game stores the correct COLUMN/LINE values respectively.

Using the ‘FA 17D0E’ command, we find 3 references. Two of them we already knew about, they are in the code above… let’s investigate the 3rd one, which is at $17D44.

Now that looks promising! This is obviously the comparison between the code you entered and the code the game requires. The first few lines you see in the screenshot above, simply take the code you entered (1 byte at a time) and convert it into a word value by shifting/or’ing. Then this value is compared against a value from a table indexed by the COLUMN/LINE values. If we look at the table at $1C862 we see 200 code words, eg: 0323 0312 0444 etc. This makes sense since we know the COLUMN value is limited to 1-10 range, and the LINE value limited to 1-20, giving us 10*20 possible code words.

So now all that remains is to decide how to patch it, and the patching itself. We have 3 options:-

    [1] Patch after the CMP yourcode,goodcode so that the FAIL flag (d7=$FFFFFFFF) is never set.

[2] Patch the entire code table to $0111, this means anyone using your crack only has to press fire 3 times at the code screen and they will succeed.

[3] Patch the code routines to lookup the correct code, and tell the user what to enter (by inserting the correct code into the code request text).

Now, #1 is obviously the easiest approach, and #3 is the hardest (not hard at all in fact, but it’s all relative!). However, both require modifying code within the protection-check part of the game, and as such are likely candidates for any evil checksum routines lurking elsewhere…therefore, we’re going to go with option #2, since I think it very unlikely the game will checksum the entire code table.

NOTE: I’ve chosen to edit the "Please enter code" text to tell the user to enter 111 as the code – if you were really worried about checksums you wouldn’t do this, and simply make sure you tell the user which code to enter in your crack-intro text.

Above you can see I’ve just read in the first half of the disk, and searched for the text we know should be in mem… thankfully it seems as if nothing on the disk is compressed, so we find the text at $2D5E4 – this means it is at offset $255E4 on the disk, since we started loading at $8000 in memory.

The second thing we need to look for on disk is the code table. We know this starts with 0323 0312 0444, so a quick search finds this at $32262 in memory which means it’s at offset $2A262 on disk. A couple of quick calculations (offset/$1600) tell us that the text we want to modify is on track $1B, and the codetable is on track $1E.

Now we need to modify what’s in memory – I just used the ‘M’ command to view/edit the text "enter weapons for " to say "enter code 111 " at $2D5D0 onwards. Once that is done, it’s time to write a few lines of code to overwrite the code table with $0111:-

000400  LEA.L $00032262,A0
000406  LEA.L $000323f2,A1
00040c  MOVE.L #$01110111,D0
000412  MOVE.L D0,(A0)+
000414  CMPA.L A0,A1
000416  BNE.B $00000412
000418  BRA.B $00000418

Not the most complex routine you will ever see (or the neatest!), but after assembling this at $400 and executing (‘G 400’ in AR), we can press the magic button again and see that the code table now contains what we want.

All that remains is to save our modifications to a copy of disk 1, and test our crack! ‘WT 1B 5 2D200’ writes out the tracks we need ($1B to $1F inclusive), once that’s finished it’s time for a reboot and playtest.

Everything seems ok, another novella protection laid to rest!



Publication author

offline 10 hours


Comments: 1983Publics: 20Registration: 15-05-2004

Notify of

Inline Feedbacks
View all comments
14 years ago

Short and Sweet!
I like it;)


This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Password generation

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Would love your thoughts, please comment.x