forked from devdri/awake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnote.txt
352 lines (279 loc) · 8.52 KB
/
note.txt
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
-- ARCH: ---
effect:
- read-write dict: registers and mem
- timestamped memreads/writes? -> doesn't matter right now, it is
implementation dependant. Only public api matters now.
- handle unknown address read/write
- just use ambiguous addr
- what about many memwrites?
loop XXX:
[FF10] = YYY
- value propagation
- select: only constants / expand expressions
- unused expression removal
- extra dependencies - for conditional code
- plus for proc signature
- could use PC target instead
effect = Effect((addr, value), BC=value2)
Effect.join(effect1, effect2) -- serial combination of effects
effect3 = effect1.withContext(effect2) -- effect3 is effect1 with propagated values from effect2
effect3 = effect1.limitTo(effect2{{{.getDependencies()}}}) -- effect1 with removed values unused in effect2
address
rom
database -> depend address procedure
tag
html -> tag
###
regutil
operand -> address regutil html
operator -> operand
expression -> operator operand
context -> operand operator regutil
depend (DependencySet) -> regutil
placeholders -> address operand
opcodeeffect -> regutil placeholders expression
singledecoder -> instruction operand placeholders opcodeeffect context expression
opcodedispatcher -> singledecoder instruction
disasm -> rom opcodedispatcher
graph -> tag address database flow
instruction -> jumptable regutil placeholders operand address html depend database
jumptable -> operand address disasm
procedure -> database disasm address html instruction operand tag
flow -> tag procedure regutil context flowcontrol address depend operand database
flowcontrol -> instruction operand context regutil html depend placeholders address
NOTES:
- flowcontrol: remove placeholders?
- operand: regutil could be removed. address except computed and deref
- operator: could be less specific, but is cool; isConstant() bad
- placeholders: separate register names from opcode details (or merge placeholders to disasm)
- procedure: refactor manualJumptableLimit. Maybe rename module because of range-analysis, etc.
- regutil: could be less specific / moved
- singledecoder: context used for instruction instantiation
- flow: analyze - hardcoded hacks
---------------------------------
Instruction, CompoundInstruction
-> dependencies, context, etc.
-> memreads, memwrites to depset
-> split to simple as pass
-> remove calls/jumps/hasContinue, use function
specific instructions
decoder -> specific instruction
flow analyzer -> compound instructions
-- AGES / RESUME LOG: --
found microthreads
initial microthread table
obtain huge graph
draw dependencies by bank
-- LINKS AWAKENING NOTES FOLLOW: --
sprites in banks: 0x0C -- 0x13
1:6341 - data (pointers)
select * from calls where not exists (select * from procs where procs.addr=calls.source) and calls.source != "FFFF:0000"
select * from procs where not exists (select * from calls where procs.addr=calls.destination)
select * from procs where has_suspicious_instr=1
select * from memref where addr not like "WORK:%" and addr not like "IO:%" and addr not like "HRAM:%" and addr not like "BATT:%"
0000:0B53:
bank remember/restore
0002:529A:
empty if -- ok
0018:5168:
crazy stuff:
JP ..., FZ
RET FNZ
Configurable:
- rombank shadow in var
- dma routine mapping (ex. 0xFF80 -> 0001:4BFB)
- manual entry points
D300 - D410 -- music vars
D480 -- probably dungeon minimap (refreshed on start menu (in dungeon) and enter dungeon)
D500 -- map backup below text box
D600 -- some vars, restored on move screen
D650 -- stuff restored on enter dungeon
D6FD -- desired lcdc low
D700 - D79F -- room data (collision etc.)
related procs: 0000:30DC, 0001:7CDE
DB00 -- equipment, etc.
DB47 -- seconds counting upwards from some val, stops at FF
TODO:
- speedup database.
sqlite transactions?
drop sqlite, use pickle?
- non-continuous procs: exist and make sense.
pro:
less small procedures - manageable graph
flow control more visible
more optimizations possible
con:
must keep each byte's ownership
discovering new procs requires recalculating old ownership (or does it? just take over bytes, a full control subtree is moved)
- refactor operator optimizations
optimizations separate from substituting regs
heavier usage of masks, move limiting operations (and, shift) higher
- better context deduction: from conditions
- new context propagation algorithm, two options:
1) use just registers
pro:
simple, just few variables to look at
con:
in some cases (stack) more vars needed to keep accurate context
2) produce new variables
pro:
all possible info is saved
con:
hard to not produce junk
- better bad-op handling:
display page anyway
- handle elseif chains
- logical and/or instead of nested ifs
- better jumptable size heuristics
- understand loops and make rich instructions
memcpy dest, src, size
memset dest, val, size, [stride]
multiply-add loop
dec16 from dec lo, if zero(lo): dec hi
copy-word
New idea:
DataAddress(Operand)
- contains a Constant or sth. else instead of subclassing it
- manages ROMBANK dependencies etc.
- probably better place to do optimizations than Dereference
doesn't have to mean actual access to data
con: doesn't 'serialize' nicely into expression, is just an artificial product of Dereference
pro: could be easily used as lvalue
database:
- check byte ownership, add/remove ownership
procedure:
- owned bytes
- easy to add/remove content
- proc references ((tail-)call, ambiguous, known args, etc.)
- data references (read/write, base addr, size, indexing mode, etc. (maybe also as jumptable))
- depset, known output
- user content: name, arg names
jumptable:
- size, owned bytes
- canBeExpanded()
dfs:
- start point
- limit (next proc addr) any jump beyond that is a tailcall/etc.
- calls could probably move the limit backwards
- dfs everything within limit. could still be large.
- jump tables are expanded last (separate queue)
- isLocalAddr(addr)
- detect conflicts with jumptable space... and also overlapping instructions etc. report that
- return: set of reachable addresses within limit, jump table sizes
next pass:
- set limit to first gap.
- compute label set
- remember jump table sizes (or just use next label...)
- now disassembly possible
graph construction:
- make ordered list of basic blocks (started by labels or entry point)
- make dict: addr -> block_id
- add basic blocks, removing jump instructions
- replace with mapping: block_id -> ordered list of exits
- for far jumps add pseudo blocks (or replace with tail-call)
- possibility: merge same tail calls into one block...
- return: list of basic blocks, dict of jumps between them
early optimization:
- traverse graph, optimize with context.
BANKS:
00 MAIN CODE
01 MAIN CODE
02 some logic code
03 code with some data
04 unknown stuff
05 code and data (stuff at top)
06 code and data (stuff at top)
07 unknown stuff
08 DATA
09 stuff then text from 2700
0A unknown stuff
0B unknown stuff
0C SPRITES
0D SPRITES
0E SPRITES
0F SPRITES
10 SPRITES
11 SPRITES
12 SPRITES
13 SPRITES
14 unknown code
15 unknown stuff, some code
16 stuff, then text from 1700
17 some scroll code, credits text, logic
18 data, code
19 stuff and empty space
1A stuff and empty space
1B MUSIC
1C map? and text from 0A00
1D TEXT
1E MUSIC
1F MUSIC
DB54 -- current area location
DB9A -- start menu scroll (0 - in menu, 80 - hidden) (desired_WY)
start menu doesn't change mode_1 or mode_2
DBA6 -- player select cursor location
sprite 2-3 -- Link
sprite 4-5 -- sword
Screen warp modes:
mode_1 -- DB95
mode_2 -- DB96
mode_1 == 0:
intro.
mode_2 >= 8:
do logo warp
mode_2 == B:
logo screen
mode_1 == 1:
outro.
mode_1 == 2:
player select
mode_2 == 7 -- idle
mode_1 == 3:
new player
mode_2 == 2 -- idle
mode_1 == 4:
erase screen
mode_1 == 5:
copy screen
mode_2 == 4 -- select source
mode_2 == 5 -- select destination
mode_1 == 6:
save screen
mode_1 == 7:
map view.
mode_2 == 4:
idle
mode_2 == 5:
return to game
mode_1 == 8:
Christine photo.
mode_1 == 9:
Marin talk.
mode_1 == A:
Windfish tablet.
mode_1 == B:
normal game mode
game over screen doesn't change it
mode_2 < 7 -- animation when entering
mode_2 == 7 -- idle
Giant switch opcode -- FFEB
obj alive status -- FFEA
0 -- off
3 -- explode
5 -- normal
7 -- held by Link
8 -- thrown
6 -- on floor, returning to normal (Genie bottle style)
screen_warp_mode -- 0xC17F:
0 - off
1 - go to sleep
2 - begin ocarina warp
3 - end ocarina warp
FF - windfish appearing and disappearing
FE - windfish floating
FD - ?
6E -- butterfly
1C -- small zol
19 -- keese
5F -- big stalfos (alive status == 4 -> toggle boss talk)
07 -- shield-back, more powerful bracelet (get item in general)