-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathanalyze_olp.py
executable file
·197 lines (179 loc) · 5.83 KB
/
analyze_olp.py
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#!/usr/bin/env python
from zipfile import ZipFile
from sys import exit, argv
def detect_rise(last, sample, bit):
mask = 1 << bit
return (not last & mask) and (sample & mask)
def detect_fall(last, sample, bit):
mask = 1 << bit
return (last & mask) and (not sample & mask)
def detect_high(sample, bit):
mask = 1 << bit
return sample & mask
def detect_low(sample, bit):
mask = 1 << bit
return not sample & mask
def get_value(sample, bits):
value = 0
for i in xrange(0, len(bits)):
bit = bits[i]
value |= (sample >> bit & 1) << i
return value
def swizzle_mode4(row, col):
return (col & 1) | (row << 1) | (col << 8 & 0xFE00)
def analyze_delays(chanmap, datafile):
if 'M68K_CLK' in chanmap:
m68k_clk = chanmap['M68K CLK']
elif 'CLK' in chanmap:
m68k_clk = chanmap['CLK']
m_as = chanmap['!AS']
ram_oe = chanmap['RAM !LOE/!RFSH']
ram_ce = chanmap['RAM !CE']
last = False
prev = False
prevRefresh = False
clks = 0
as_start = 0
for line in datafile.readlines():
line = line.strip()
if line and not line.startswith(';'):
sample,_,num = line.partition('@')
sample = int(sample, 16)
if not (last is False):
if detect_rise(last, sample, m68k_clk):
clks = clks + 1
if detect_rise(last, sample, m_as):
as_clks = clks - as_start
if as_clks > 2:
if not (prev is False):
print '!AS held for', as_clks, 'cycles starting (delay of ' + str(as_clks - 2) + ') at', as_start, 'and ending at', clks, 'delta since last delay:', as_start - prev
else:
print '!AS held for', as_clks, 'cycles starting (delay of ' + str(as_clks - 2) + ') at', as_start, 'and ending at', clks
prev = as_start
elif detect_fall(last, sample, m_as):
as_start = clks
if detect_fall(last, sample, ram_oe) and detect_high( sample, ram_ce):
if prevRefresh is False:
print 'RAM refresh at ', clks
else:
print 'RAM refresh at', clks, 'delta since last:', clks-prevRefresh
prevRefresh = clks
last = sample
def analyze_refresh(chanmap, datafile):
if 'M68K_CLK' in chanmap:
m68k_clk = chanmap['M68K CLK']
elif 'CLK' in chanmap:
m68k_clk = chanmap['CLK']
ram_oe = chanmap['RAM !LOE/!RFSH']
ram_ce = chanmap['RAM !CE']
clks = 0
last = False
prevRefresh = False
for line in datafile.readlines():
line = line.strip()
if line and not line.startswith(';'):
sample,_,num = line.partition('@')
sample = int(sample, 16)
if not (last is False):
if detect_rise(last, sample, m68k_clk):
clks = clks + 1
if detect_fall(last, sample, ram_oe) and detect_high( sample, ram_ce):
if prevRefresh is False:
print 'RAM refresh at ', clks
else:
print 'RAM refresh at', clks, 'delta since last:', clks-prevRefresh
prevRefresh = clks
last = sample
table_start = 0x3800
table_end = table_start + 0x600
sat_start = 0x3E00 #0x3F00
sat_xname = sat_start + 0x80
sat_end = sat_start + 0x100
def analyze_vram(chanmap, datafile):
address_bits = [chanmap['AD{0}'.format(i)] for i in xrange(0, 8)]
ras = chanmap['!RAS']
cas = chanmap['!CAS']
hsync = chanmap['!HSYNC']
state = 'begin'
last = False
for line in datafile.readlines():
line = line.strip()
if line and not line.startswith(';'):
sample,_,num = line.partition('@')
sample = int(sample, 16)
if not (last is False):
if detect_fall(last, sample, hsync):
print 'HSYNC low @ {0}'.format(num)
elif detect_rise(last, sample, hsync):
print 'HSYNC high @ {0}'.format(num)
if state == 'begin':
if detect_fall(last, sample, ras):
state = 'ras'
row = get_value(sample, address_bits)
elif detect_fall(last, sample, cas):
state = 'cas'
elif state == 'ras':
if detect_fall(last, sample, cas):
col = get_value(sample, address_bits)
address = swizzle_mode4(row, col)
if address < table_end and address >= table_start:
offset = (address - table_start)/2
desc = 'Map Row {0} Col {1}'.format(offset / 32, offset & 31)
elif address >= sat_start and address < sat_xname:
offset = address - sat_start
desc = 'Sprite {0} Y Read'.format(offset)
elif address >= sat_xname and address < sat_end:
offset = address - sat_xname
desc = 'Sprite {0} X/Name Read'.format(offset / 2)
else:
desc = 'Tile {0} Row {1}'.format(address / 32, ((address / 4) & 7) + (0.5 if address & 2 else 0))
print '{0:02X}:{1:02X} - {2:04X} @ {3} - {4}'.format(row, col, address, num, desc)
state = 'begin'
elif state == 'cas':
if detect_fall(last, sample, ras):
print 'refresh @ {0}'.format(num)
state = 'begin'
last = sample
def analyze_z80_mreq(chanmap, datafile):
m1 = chanmap['!M1']
mreq = chanmap['!MREQ']
addressMask = 0x3FF
last = None
lastWasM1 = False
for line in datafile.readlines():
line = line.strip()
if line and not line.startswith(';'):
sample,_,num = line.partition('@')
sample = int(sample, 16)
if not (last is None):
if detect_rise(last, sample, mreq):
address = last & addressMask
if detect_low(last, m1):
print 'M1 read {0:02X} @ {1}'.format(address, num)
lastWasM1 = True
elif lastWasM1:
print 'Refresh {0:02X} @ {1}'.format(address, num)
lastWasM1 = False
else:
print 'Access {0:02X} @ {1}'.format(address, num)
last = sample
def main(args):
if len(args) < 2:
print 'Usage: analyze_olp.py filename'
exit(1)
olpfile = ZipFile(args[1], "r")
channelfile = olpfile.open('channel.labels')
channels = [line.strip() for line in channelfile.readlines()]
channelfile.close()
print channels
chanmap = {}
for i in xrange(0, len(channels)):
chanmap[channels[i]] = i
datafile = olpfile.open('data.ols')
#analyze_delays(chanmap, datafile)
#analyze_vram(chanmap, datafile)
#analyze_refresh(chanmap, datafile)
analyze_z80_mreq(chanmap, datafile)
datafile.close()
if __name__ == '__main__':
main(argv)