-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcopper.py
More file actions
74 lines (68 loc) · 3.51 KB
/
Copy pathcopper.py
File metadata and controls
74 lines (68 loc) · 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
"""Copper-list disassembler for the Amiga custom chips.
Used on `Lx_ChipI.cru`, the chip-RAM image the loader installs before the
game proper starts. Register names cover the AGA set, since the CD32 is an
AGA machine and the game does use registers the ECS chipset does not have.
"""
import struct, sys
REG = {
0x02:'DMACONR',0x04:'VPOSR',0x06:'VHPOSR',0x08:'DSKDATR',0x0A:'JOY0DAT',
0x0C:'JOY1DAT',0x0E:'CLXDAT',0x10:'ADKCONR',0x12:'POT0DAT',0x14:'POT1DAT',
0x16:'POTGOR',0x18:'SERDATR',0x1A:'DSKBYTR',0x1C:'INTENAR',0x1E:'INTREQR',
0x20:'DSKPTH',0x22:'DSKPTL',0x24:'DSKLEN',0x26:'DSKDAT',0x28:'REFPTR',
0x2A:'VPOSW',0x2C:'VHPOSW',0x2E:'COPCON',0x30:'SERDAT',0x32:'SERPER',
0x34:'POTGO',0x36:'JOYTEST',0x38:'STREQU',0x3A:'STRVBL',0x3C:'STRHOR',
0x3E:'STRLONG',0x40:'BLTCON0',0x42:'BLTCON1',0x44:'BLTAFWM',0x46:'BLTALWM',
0x48:'BLTCPTH',0x4A:'BLTCPTL',0x4C:'BLTBPTH',0x4E:'BLTBPTL',0x50:'BLTAPTH',
0x52:'BLTAPTL',0x54:'BLTDPTH',0x56:'BLTDPTL',0x58:'BLTSIZE',0x5A:'BLTCON0L',
0x5C:'BLTSIZV',0x5E:'BLTSIZH',0x60:'BLTCMOD',0x62:'BLTBMOD',0x64:'BLTAMOD',
0x66:'BLTDMOD',0x70:'BLTCDAT',0x72:'BLTBDAT',0x74:'BLTADAT',0x7C:'DENISEID',
0x7E:'DSKSYNC',0x80:'COP1LCH',0x82:'COP1LCL',0x84:'COP2LCH',0x86:'COP2LCL',
0x88:'COPJMP1',0x8A:'COPJMP2',0x8C:'COPINS',0x8E:'DIWSTRT',0x90:'DIWSTOP',
0x92:'DDFSTRT',0x94:'DDFSTOP',0x96:'DMACON',0x98:'CLXCON',0x9A:'INTENA',
0x9C:'INTREQ',0x9E:'ADKCON',0xA0:'AUD0LCH',0xA2:'AUD0LCL',0xA4:'AUD0LEN',
0xA6:'AUD0PER',0xA8:'AUD0VOL',0xAA:'AUD0DAT',0xB0:'AUD1LCH',0xB2:'AUD1LCL',
0xB4:'AUD1LEN',0xB6:'AUD1PER',0xB8:'AUD1VOL',0xBA:'AUD1DAT',0xC0:'AUD2LCH',
0xC2:'AUD2LCL',0xC4:'AUD2LEN',0xC6:'AUD2PER',0xC8:'AUD2VOL',0xCA:'AUD2DAT',
0xD0:'AUD3LCH',0xD2:'AUD3LCL',0xD4:'AUD3LEN',0xD6:'AUD3PER',0xD8:'AUD3VOL',
0xDA:'AUD3DAT',0x100:'BPLCON0',0x102:'BPLCON1',0x104:'BPLCON2',0x106:'BPLCON3',
0x108:'BPL1MOD',0x10A:'BPL2MOD',0x10C:'BPLCON4',0x10E:'CLXCON2',
0x1FC:'FMODE',0x1DC:'BEAMCON0',0x1E4:'DIWHIGH',0x1C0:'HTOTAL',
0x1C2:'HSSTOP',0x1C4:'HBSTRT',0x1C6:'HBSTOP',0x1C8:'VTOTAL',0x1CA:'VSSTOP',
0x1CC:'VBSTRT',0x1CE:'VBSTOP',0x1DE:'HSSTRT',0x1E0:'VSSTRT',0x1E2:'HCENTER',
0x1E6:'BPLHMOD',0x1E8:'SPRHPTH',0x1EA:'SPRHPTL',0x1EC:'BPLHPTH',0x1EE:'BPLHPTL',
}
for i in range(8):
REG[0xE0+i*4] = 'BPL%dPTH' % (i+1)
REG[0xE2+i*4] = 'BPL%dPTL' % (i+1)
REG[0x110+i*2] = 'BPL%dDAT' % (i+1)
REG[0x120+i*4] = 'SPR%dPTH' % i
REG[0x122+i*4] = 'SPR%dPTL' % i
for i in range(32):
REG[0x180+i*2] = 'COLOR%02d' % i
def disasm(data, off=0, limit=100000):
"""Yield (offset, text) until the list terminates or `limit` is hit."""
o = off
while o + 4 <= len(data) and o - off < limit:
w1, w2 = struct.unpack_from('>HH', data, o)
if w1 & 1:
kind = 'SKIP' if (w2 & 1) else 'WAIT'
vp, hp = (w1 >> 8) & 0xFF, w1 & 0xFE
ve, he = (w2 >> 8) & 0x7F, w2 & 0xFE
bfd = (w2 >> 15) & 1
txt = '%s VP=$%02X HP=$%02X, VE=$%02X HE=$%02X%s' % (
kind, vp, hp, ve, he, '' if bfd else ' (BFD=0)')
if w1 == 0xFFFF and w2 == 0xFFFE:
yield o, 'END (WAIT $FFFF,$FFFE)'
o += 4
return
else:
reg = w1 & 0x1FE
txt = 'MOVE %-8s, $%04X' % (REG.get(reg, '$%03X' % reg), w2)
yield o, txt
o += 4
if __name__ == '__main__':
d = open(sys.argv[1], 'rb').read()
start = int(sys.argv[2], 0) if len(sys.argv) > 2 else 0
lim = int(sys.argv[3], 0) if len(sys.argv) > 3 else 100000
for o, t in disasm(d, start, lim):
print('%06X: %s' % (o, t))