In order to make the game harder to crack, some copy protection routines were hidden in the graphics.dat file where the machine code was encoded like any other image. The main program of the game would load and run these routines on-demand and then dispose of them.
This mechanism was used on Atari ST, Apple IIGS and Amiga.
Dungeon Master 3.6 is not copy protected but the hidden code is still in the graphics.dat.
The X68000, PC-9801 and FM-Towns versions also have the Amiga hidden code in their graphics.dat. However it is not used in these versions as those computers do not have a 68000 processor.
The items were extracted from graphics.dat (see COD1, COD2, COD3 and COD4 formats on Data Files) and then disassembled.
This page shows the resulting disassembled code.
The following table lists all items that hide machine code.
Hidden code section name | Found in graphics.dat of games | Item index | Item type MD5 of raw item data in graphics.dat |
---|---|---|---|
Atari ST DM Item 21 | Dungeon Master Atari ST | 21 | COD1 hidden as IMG1 of 16x12 pixels `87DEDFCCAE727C7B1B50F2A7A1FB6CB6` |
Atari ST CSB Item 21 | Chaos Strikes Back for Atari ST | 21 | COD1 hidden as IMG1 of 16x13 pixels `EE4CB37C1A7A9D2AB63FC9726767FFA3` |
Apple IIGS Item 21 | Dungeon Master for Apple IIGS | 21 | COD4 hidden as IMG1 of 16x17 pixels `6D37A00139C3E6CF7AFFB10D067AD3F4` |
Amiga 2.x Item 21 | Dungeon Master for Amiga version v2.x Dungeon Master and Chaos Strikes Back for X68000 Dungeon Master for FM-Towns Dungeon Master for PC-9801 | 21 | COD2 hidden as IMG1 of 16x23 pixels `59F3A1C1F67470EA3689E2A7552E0AA6` |
Chaos Strikes Back for FM-Towns Chaos Strikes Back for PC-9801 | 21 | COD3 hidden as IMG2 of 16x23 pixels `45465FA8377AAAB4D96C4D03C509A026` | |
Amiga 3.x Item 21 | Dungeon Master and Chaos Strikes Back for Amiga version 3.x | 21 | COD2 hidden as IMG1 of 16x21 pixels `C3080E7CB930C7C5958C1BB7828EB860` |
Atari ST Item 538 | Dungeon Master and Chaos Strikes Back for Atari ST | 538 | COD1 hidden as IMG1 of 16x19 pixels `FD5FA12460F40E0AC7B614F23DD3C91C` |
Amiga 2.x Item 538/676 | Dungeon Master for Amiga version v2.x Dungeon Master for X68000 Dungeon Master for FM-Towns Dungeon Master for PC-9801 | 538 | COD2 hidden as IMG1 of 16x9 pixels `7E0F9A58B69350AA30566428C2D58E2A` |
Chaos Strikes Back for X68000 | 676 | ||
Amiga 3.x Item 538/676 | Chaos Strikes Back for FM-Towns Chaos Strikes Back for PC-9801 | 676 | COD3 hidden as IMG2 of 16x13 pixels `44B5330A26F08121C0AC8DD640925A4C` |
Dungeon Master and Chaos Strikes Back for Amiga version 3.x | 676 | COD2 hidden as IMG1 of 16x13 pixels `EA090463D44DCBA67F11455491E35124` | |
Atari ST Item 548 | Dungeon Master and Chaos Strikes Back for Atari ST | 548 | COD1 hidden as IMG1 of 16x6 pixels `646C9FFBAC48E3EBA2F8ED0641EE7AF9` |
Amiga Item 548/686 | Dungeon Master for Amiga version v2.x Dungeon Master for X68000 Dungeon Master for FM-Towns Dungeon Master for PC-9801 | 548 | COD2 hidden as IMG1 of 16x9 pixels `CC6D1DCBDB44BAD637B1AEB60027688C` |
Dungeon Master and Chaos Strikes Back for Amiga version 3.x Chaos Strikes Back for X68000 | 686 | ||
Chaos Strikes Back for FM-Towns Chaos Strikes Back for PC-9801 | 686 | COD3 hidden as IMG2 of 16x9 pixels `A019CAAD5456F2A216C8C9012A705ABD` |
There are three items in the Atari ST graphics.dat file that contain “hidden code”: items number 21, 538 and 548.
Sometimes, a function is called with the following parameters:
The victim function is modified so that it calls the code of the graphic item and then its own code.
It seems that the code in item 538 reads the protection, and the code in item 21 checks the protection.
The code in item 548 is not used at all. The same code is also present in the main program.
Note that the code in these graphic items is not taken into account in the checksums.
Below are listings of these items dissassembled and with comments by Meynaf (I translated his comments to english).
This is compiled code, not very nice to see…
w90a2 link a6,#0
movem.l a2-a3,-(a7)
movea.l 8(a6),a3
w90ae jsr $90(a5) ; rnd
and.l #$ffff,d0
divu $1e(a6),d0
swap d0
asl.l #2,d0
movea.l $1a(a6),a0
adda.w d0,a0
movea.l (a0),a2
move.w $3c(a2),d0
move.w $3c(a2),d0
bne.s w90ae
move.w #1,$3c(a2)
move.w #$2a,-(a7)
move.l a2,-(a7)
pea w9134(pc)
jsr 6(a5) ; memcpy
adda.w #$a,a7
w90ea cmpi.w #$4ef9,(a3)
bne.s w90f6
movea.l 2(a3),a3
bra.s w90ea
w90f6 move.w #6,-(a7)
lea $3e(a2),a0
move.l a0,-(a7)
move.l a3,-(a7)
jsr 6(a5) ; memcpy
adda.w #$a,a7
move.l a3,$2a(a2)
move.l $c(a6),$2e(a2)
move.w $10(a6),$32(a2)
move.l $12(a6),$34(a2)
move.l $16(a6),$38(a2)
move.w #$4ef9,(a3)+ ; 4ef9 = code of the jmp
move.l a2,(a3) ; the address follows
movem.l (a7)+,a2-a3
unlk a6
rts
The following code for the 68000 processor is found in the following graphics.dat files:
Note that there is a small difference in the code used in Dungeon Master and Chaos Strikes Back as outlined below.
Hex Label Instruction and operands
--------------------------------------------
48E70310 movem.l d6-d7/a3,-(a7)
206F0010 movea.l $0010(a7),a0
41E80014 lea $0014(a0),a0
266F0014 movea.l $0014(a7),a3
225B movea.l (a3)+,a1
3C3C01E9 move.w #$01E9,d6
7E10 moveq #$10,d7
7000 moveq #$00,d0
7200 L1A: moveq #$00,d1
7400 moveq #$00,d2
1618 L1E: move.b (a0)+,d3
6A06 bpl.s L28
03C2 bset d1,d2
0203007F andi.b #$7F,d3
0C030068 L28: cmpi.b #$68,d3
6704 beq.s L32
7000 moveq #$00,d0
6016 bra.s L48
5241 L32: addq.w #1,d1
5346 subq.w #1,d6
6704 beq.s L3C
B247 cmp.w d7,d1
66E2 bne.s L1E
B451 L3C: cmp.w (a1),d2
6702 beq.s L42
5240 addq.w #1,d0
32C2 L42: move.w d2,(a1)+
4A46 tst.w d6
66D2 bne.s L1A
205B L48: movea.l (a3)+,a0
30BC0088 move.w #$0088,(a0)
4A40 tst.w d0
6604 bne.s L56
----------------------------------------------------------------------------------
Dungeon Master | Chaos Strikes Back
----------------------------------------------------------------------------------
2653 movea.l (a3),a3 | 2053 movea.l (a3),a0
4293 clr.l (a3) | 4290 clr.l (a0)
| 266B0004 L56: movea.l $0004(a3),a3
| 36BC0200 move.w #$0200,(a3)
----------------------------------------------------------------------------------
4CDF08C0 L56: movem.l (a7)+,d6-d7/a3
4E75 rts
00000000 dc.l $00000000
The following code for the 68000 processor is found in the following graphics.dat files:
Hex Label Instruction and operands Comments
-----------------------------------------------------------------
260A move.l a2,d3
42A7 clr.l -(a7)
3F3C0020 move.w #$0020,-(a7) ; Super (switch to supervisor mode)
4E41 trap #1 ; Gemdos
2F400002 move.l d0,$0002(a7)
4A78043E tst.w $043E ; flag system for disk activity
666A bne.s L7E
31FC0001043E move.w #$0001,$043E
206F000E movea.l $000E(a7),a0
30FC0103 move.w #$0103,(a0)+
30BC0001 move.w #$0001,(a0)
307C8800 movea.w #$8800,a0
74F8 moveq #-$08,d2
40C0 move sr,d0
007C0700 ori #$0700,sr
10BC000E move.b #$0E,(a0)
C410 and.b (a0),d2
00020005 ori.b #$05,d2
11420002 move.b d2,$0002(a0) ; switch on the floppy drive
307C8606 movea.w #$8606,a0
30BC0084 move.w #$0084,(a0)
7207 moveq #$07,d1
613A bsr.s L86
13EF000DFFFF860D move.b $000D(a7),$FFFF860D.l ; dma adr low
13EF000CFFFF860B move.b $000C(a7),$FFFF860B.l ; dma adr mid
13EF000BFFFF8609 move.b $000B(a7),$FFFF8609.l ; dma adr high
30BC0090 move.w #$0090,(a0)
30BC0190 move.w #$0190,(a0)
30BC0090 move.w #$0090,(a0) ; read impulse
3140FFFE move.w d0,-$0002(a0)
323C0080 move.w #$0080,d1
3081 move.w d1,(a0)
610A bsr.s L86
46C0 move d0,sr
4E41 L7E: trap #1 ; Gemdos (switch back to user mode)
5C8F addq.l #6,a7
2443 movea.l d3,a2
4E75 rts
6104 L86: bsr.s L8C
3141FFFE move.w d1,-$0002(a0)
742E L8C: moveq #$2E,d2
5342 L8E: subq.w #1,d2
66FC bne.s L8E
4E75 rts
00000000 dc.l $00000000
The following code for the 68000 processor is found in the following graphics.dat files:
This code is both a part of the main program used by the preceding routine, and the code in item 548. It is exactly the same!
The programmers probably planned to put that routine outside the main program and finally could not do it (just guessing).
It is not executed directly but copied elsewhere in memory before being run. Several copies can exist simultaneously with different parameters.
Hex Label Instruction and operands Comments
---------------------------------------------------------
41FA003A L00: lea L00+$3C(pc),a0
4258 clr.w (a0)+
227A0022 movea.l X2A(pc),a1 ; restore the victim routine (address at X2A)
22D8 move.l (a0)+,(a1)+ ; (the first 6 bytes were modified)
3290 move.w (a0),(a1)
207A001E movea.l X2E(pc),a0
3F3A001E move.w L00+$32(pc),-(a7) ; n° of the graphic item (21 or 538)
4E90 jsr (a0) ; returns the address of the item
2040 movea.l d0,a0
2F3A001C move.l L00+$38(pc),-(a7) ; pass parameters
2F3A0014 move.l L00+$34(pc),-(a7)
4E90 jsr (a0) ; call the code
4FEF000A lea $000A(a7),a7
4EF9 dc.w $4EF9 ; jmp instruction
00000000 X2A: dc.l $00000000 ; jmp target address
0000 X2E: dc.w $0000
The following data is not part of item 548 but is referred to by its code (real data is here at runtime):
ds.w
X32: ds.w
X34: ds.l
X38: ds.l
X3C: ds.w ; specific parameters are copied starting here
The following code for the 65C816 processor is found in the following graphics.dat files:
Offset Hex Instruction and operands
----------------------------------------------
00/8000: 0B PHD
00/8001: A3 06 LDA $06,S
00/8003: 5B TCD
00/8004: 68 PLA
00/8005: 85 00 STA $00
00/8007: 68 PLA
00/8008: 85 0A STA $0A
00/800A: E2 20 SEP #$20
00/800C: 68 PLA
00/800D: 85 0C STA $0C
00/800F: C2 20 REP #$20
00/8011: 68 PLA
00/8012: 68 PLA
00/8013: 85 02 STA $02
00/8015: 68 PLA
00/8016: 85 04 STA $04
00/8018: 68 PLA
00/8019: 85 06 STA $06
00/801B: 68 PLA
00/801C: 85 08 STA $08
00/801E: A2 0E LDX #$0E
00/8020: 00 9B BRK $9B
00/8022: B7 06 LDA [$06],Y
00/8024: 95 0F STA $0F,X
00/8026: CA DEX
00/8027: CA DEX
00/8028: 88 DEY
00/8029: 88 DEY
00/802A: 10 F6 BPL $8022
00/802C: 64 0D STZ $0D
00/802E: A0 0D LDY #$0D
00/8030: 00 E2 BRK $E2
00/8032: 20 B7 02 JSR $02B7
00/8035: AA TAX
00/8036: 47 0F EOR [$0F]
00/8038: 48 PHA
00/8039: 8A TXA
00/803A: 29 1B AND #$1B
00/803C: 87 0F STA [$0F]
00/803E: C2 20 REP #$20
00/8040: E6 0F INC $0F
00/8042: D0 02 BNE $8046
00/8044: E6 11 INC $11
00/8046: E2 20 SEP #$20
00/8048: 68 PLA
00/8049: C2 20 REP #$20
00/804B: 29 1B AND #$1B
00/804D: 00 F0 BRK $F0
00/804F: 02 E6 COP $E6
00/8051: 0D C8 C8 ORA $C8C8
00/8054: C0 BF CPY #$BF
00/8056: 02 90 COP $90
00/8058: D8 CLD
00/8059: A5 0D LDA $0D
00/805B: D0 05 BNE $8062
00/805D: A9 00 LDA #$00
00/805F: 00 87 BRK $87
00/8061: 17 A9 ORA [$A9],Y
00/8063: 88 DEY
00/8064: 00 87 BRK $87
00/8066: 13 A9 ORA ($A9,S),Y
00/8068: 00 02 BRK $02
00/806A: 87 1B STA [$1B]
00/806C: 3B TSC
00/806D: 38 SEC
00/806E: E9 0A SBC #$0A
00/8070: 00 1B BRK $1B
00/8072: E2 20 SEP #$20
00/8074: A5 0C LDA $0C
00/8076: 48 PHA
00/8077: C2 20 REP #$20
00/8079: A5 0A LDA $0A
00/807B: 48 PHA
00/807C: A5 0D LDA $0D
00/807E: 48 PHA
00/807F: A5 00 LDA $00
00/8081: 5B TCD
00/8082: 68 PLA
00/8083: 6B RTL
00/8084: 00 00 BRK $00
00/8086: 00 00 BRK $00
The following code for the 68000 processor is found in the following graphics.dat files:
Hex Label Instruction and operands
----------------------------------------------------
4E55FFFA link a5,#-$0006
48E70F20 movem.l d4-d7/a2,-(a7)
246D0008 movea.l $0008(a5),a2
206D000C movea.l $000C(a5),a0
2B50FFFA move.l (a0),-$0006(a5)
7C00 moveq #$00,d6
426DFFFE clr.w -$0002(a5)
7A00 moveq #$00,d5
7E00 moveq #$00,d7
7814 moveq #$14,d4
3004 L20: move.w d4,d0
48C0 ext.l d0
E380 asl.l #1,d0
32320800 move.w $00(a2,d0.l),d1
700E moveq #$0E,d0
E069 lsr.w d0,d1
C27C0001 and.w #$0001,d1
3007 move.w d7,d0
E340 asl.w #1,d0
3E01 move.w d1,d7
8E40 or.w d0,d7
3006 move.w d6,d0
5246 addq.w #1,d6
B07C0010 cmp.w #$0010,d0
6700000A beq L4E
B87C01FC cmp.w #$01FC,d4
6600002E bne L7A
7C00 L4E: moveq #$00,d6
3005 move.w d5,d0
48C0 ext.l d0
E380 asl.l #1,d0
206DFFFA movea.l -$0006(a5),a0
32300800 move.w $00(a0,d0.l),d1
B247 cmp.w d7,d1
67000006 beq L68
526DFFFE addq.w #1,-$0002(a5)
3005 L68: move.w d5,d0
5245 addq.w #1,d5
48C0 ext.l d0
E380 asl.l #1,d0
206DFFFA movea.l -$0006(a5),a0
31870800 move.w d7,$00(a0,d0.l)
7E00 moveq #$00,d7
5244 L7A: addq.w #1,d4
B87C01FC cmp.w #$01FC,d4
6F9E ble.s L20
4A6DFFFE tst.w -$0002(a5)
6600000C bne L94
206D000C movea.l $000C(a5),a0
22680008 movea.l $0008(a0),a1
4291 clr.l (a1)
206D000C L94: movea.l $000C(a5),a0
2268000C movea.l $000C(a0),a1
32BC0200 move.w #$0200,(a1)
206D000C movea.l $000C(a5),a0
22680004 movea.l $0004(a0),a1
32BC0088 move.w #$0088,(a1)
302DFFFE move.w -$0002(a5),d0
4CDF04F0 movem.l (a7)+,d4-d7/a2
4E5D unlk a5
4E75 rts
The following code for the 68000 processor is found in the following graphics.dat files:
Hex Label Instruction and operands
----------------------------------------------------
4E560000 link a6,#$0000
48E71F18 movem.l d3-d7/a3-a4,-(a7)
286E0008 movea.l $0008(a6),a4
206E000C movea.l $000C(a6),a0
2650 movea.l (a0),a3
7A00 moveq #$00,d5
7600 moveq #$00,d3
7C00 moveq #$00,d6
7800 moveq #$00,d4
3E3C027B move.w #$027B,d7
60000052 bra L72
3004 L22: move.w d4,d0
D040 add.w d0,d0
3207 move.w d7,d1
48C1 ext.l d1
D281 add.l d1,d1
D28C add.l a4,d1
2041 movea.l d1,a0
3210 move.w (a0),d1
740E moveq #$0E,d2
E469 lsr.w d2,d1
02410001 andi.w #$0001,d1
8041 or.w d1,d0
3800 move.w d0,d4
3005 move.w d5,d0
5245 addq.w #1,d5
0C400010 cmpi.w #$0010,d0
6706 beq.s L4E
0C470463 cmpi.w #$0463,d7
6622 bne.s L70
7A00 L4E: moveq #$00,d5
3006 move.w d6,d0
48C0 ext.l d0
D080 add.l d0,d0
D08B add.l a3,d0
2040 movea.l d0,a0
B850 cmp.w (a0),d4
6702 beq.s L60
5243 addq.w #1,d3
3006 L60: move.w d6,d0
5246 addq.w #1,d6
48C0 ext.l d0
D080 add.l d0,d0
D08B add.l a3,d0
2040 movea.l d0,a0
3084 move.w d4,(a0)
7800 moveq #$00,d4
5247 L70: addq.w #1,d7
0C470463 L72: cmpi.w #$0463,d7
6FAA ble.s L22
4A43 tst.w d3
660A bne.s L86
206E000C movea.l $000C(a6),a0
20680008 movea.l $0008(a0),a0
4290 clr.l (a0)
206E000C L86: movea.l $000C(a6),a0
2068000C movea.l $000C(a0),a0
30BC0200 move.w #$0200,(a0)
206E000C movea.l $000C(a6),a0
20680004 movea.l $0004(a0),a0
30BC0088 move.w #$0088,(a0)
3003 move.w d3,d0
4CDF18F8 movem.l (a7)+,d3-d7/a3-a4
4E5E unlk a6
4E75 rts
The following code for the 68000 processor is found in the following graphics.dat files:
Hex Label Instruction and operands
----------------------------------------------------
4E550000 link a5,#$0000
48E70000 movem.l ,-(a7)
206D000C movea.l $000C(a5),a0
22680004 movea.l $0004(a0),a1
48E70002 movem.l a6,-(a7)
2C680008 movea.l $0008(a0),a6
4EAEFFEE jsr -$0012(a6)
4CDF4000 movem.l (a7)+,a6
13FC007B00BFD100 move.b #$7B,$00BFD100.l
13FC007300BFD100 move.b #$73,$00BFD100.l
23ED000800DFF020 move.l $0008(a5),$00DFF020.l
206D000C movea.l $000C(a5),a0
30BC0001 move.w #$0001,(a0)
4CDF0000 movem.l (a7)+,
4E5D unlk a5
4E75 rts
The following code for the 68000 processor is found in the following graphics.dat files:
Hex Label Instruction and operands
----------------------------------------------------
4E560000 link a6,#$0000
48E71F3E movem.l d3-d7/a2-a6,-(a7)
2A6E000C movea.l $000C(a6),a5
08ED0000000C L0C: bset #$00,$000C(a5)
66F8 bne.s L0C
226D0004 L14: movea.l $0004(a5),a1
2C6D0008 movea.l $0008(a5),a6
4EAEFFEE jsr -$0012(a6)
4A80 tst.l d0
661A bne.s L3E
2C780004 movea.l $0004 ,a6
286D0004 movea.l $0004(a5),a4
206C000E movea.l $000E(a4),a0
4EAEFE80 jsr -$0180(a6)
206C000E movea.l $000E(a4),a0
4EAEFE8C jsr -$0174(a6)
60D6 bra.s L14
4CDF7CF8 L3E: movem.l (a7)+,d3-d7/a2-a6
707B moveq #$7B,d0
13C000BFD100 move.b d0,$00BFD100.l
7073 moveq #$73,d0
13C000BFD100 move.b d0,$00BFD100.l
23EE000800DFF020 move.l $0008(a6),$00DFF020.l
206E000C movea.l $000C(a6),a0
7001 moveq #$01,d0
3080 move.w d0,(a0)
4E5E unlk a6
4E75 rts
0000 dc.w $0000
The following code for the 68000 processor is found in the following graphics.dat files:
Hex Label Instruction and operands
----------------------------------------------------
41FA003A lea X3C(pc),a0
4258 clr.w (a0)+
227A0022 movea.l X2A(pc),a1
22D8 move.l (a0)+,(a1)+
3290 move.w (a0),(a1)
207A001E movea.l X2E(pc),a0
3F3A001E move.w X32(pc),-(a7)
4E90 jsr (a0)
2040 movea.l d0,a0
2F3A001C move.l X38(pc),-(a7)
2F3A0014 move.l X34(pc),-(a7)
4E90 jsr (a0)
4FEF000A lea $000A(a7),a7
4EF9 dc.w $4EF9
00000000 X2A: dc.l $00000000
00000000 X2E: dc.l $00000000
0000 X32: dc.w $0000
00000000 X34: dc.l $00000000
00000000 X38: dc.l $00000000
0000 X3C: dc.w $0000
00000000 dc.l $00000000
0000 dc.w $0000
00000000 dc.w $0000,$0000