Mercurial > vba-clojure
comparison clojure/com/aurellem/gb/rlm_assembly.clj @ 388:a0d0e1a46b1d
had to change programs to prevent repeats.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Thu, 12 Apr 2012 10:20:38 -0500 |
parents | 47d44bb54d32 |
children | bb8978d370d8 |
comparison
equal
deleted
inserted
replaced
387:47d44bb54d32 | 388:a0d0e1a46b1d |
---|---|
63 (if (< n 0) | 63 (if (< n 0) |
64 (+ 256 n) n)) | 64 (+ 256 n) n)) |
65 | 65 |
66 (defn frame-metronome [] | 66 (defn frame-metronome [] |
67 (let [timing-loop | 67 (let [timing-loop |
68 [;;0x01 ; \ | 68 [0x01 ; \ |
69 ;;0x43 ; | | 69 0x43 ; | |
70 ;;0xFE ; | load 0xFF44 into BC without repeats | 70 0xFE ; | load 0xFF44 into BC without repeats |
71 ;;0x0C ; | | 71 0x0C ; | |
72 ;;0x04 ; / | 72 0x04 ; / |
73 ;;0x0A ;; (BC) -> A, now A = LY (vertical line coord) | 73 0x0A] ;; (BC) -> A, now A = LY (vertical line coord) |
74 | |
75 0x11 ; \ | |
76 0x43 ; | | |
77 0xFE ; | load 0xFF44 into DE without repeats | |
78 0x1C ; | | |
79 0x14 ; / | |
80 0x1A ;; (DE) -> A, now A = LY (vertical line coord) | |
81 ] | |
82 continue-if-144 | 74 continue-if-144 |
83 [0xFE | 75 [0xFE |
84 144 ;; compare LY (in A) with 144 | 76 144 ;; compare LY (in A) with 144 |
85 0x20 ;; jump back to beginning if LY != 144 (not-v-blank) | 77 0x20 ;; jump back to beginning if LY != 144 (not-v-blank) |
86 (->signed-8-bit | 78 (->signed-8-bit |
87 (+ -4 (- (count timing-loop))))] | 79 (+ -4 (- (count timing-loop))))] |
88 spin-loop | 80 spin-loop |
89 [;;0x05 ;; dec B, which is 0xFF | 81 [0x05 ;; dec B, which is 0xFF |
90 0x15 ;; dec D, which is 0xFF | |
91 0x20 ;; spin until B==0 | 82 0x20 ;; spin until B==0 |
92 0xFD]] | 83 0xFD]] |
93 (concat timing-loop continue-if-144 spin-loop))) | 84 (concat timing-loop continue-if-144 spin-loop))) |
94 | 85 |
95 (defn test-frame-metronome | 86 (defn test-frame-metronome |
96 "Ensure that frame-metronome ticks exactly once every frame." | 87 "Ensure that frame-metronome ticks exactly once every frame." |
97 ([] (test-frame-metronome 151)) | 88 ([] (test-frame-metronome 151)) |
98 ([steps] | 89 ([steps] |
99 (let [inc-B [0x04 0x18 | 90 (let [inc-E [0x1C 0x18 |
100 (->signed-8-bit | 91 (->signed-8-bit |
101 (+ -3 (- (count (frame-metronome)))))] | 92 (+ -3 (- (count (frame-metronome)))))] |
102 program (concat (frame-metronome) inc-B) | 93 program (concat (frame-metronome) inc-E) |
103 count-frames | 94 count-frames |
104 (-> (tick (mid-game)) | 95 (-> (tick (mid-game)) |
105 (IE! 0) | 96 (IE! 0) |
106 (BC! 0) | 97 (DE! 0) |
107 (set-memory-range pokemon-list-start program) | 98 (set-memory-range pokemon-list-start program) |
108 (PC! pokemon-list-start)) | 99 (PC! pokemon-list-start)) |
109 B-after-moves (B (run-moves count-frames (repeat steps [])))] | 100 E-after-moves (E (run-moves count-frames (repeat steps [])))] |
110 (println "B:" B-after-moves) | 101 (println "E:" E-after-moves) |
111 (assert (= steps B-after-moves)) | 102 (assert (= steps E-after-moves)) |
112 | 103 |
113 (println "B =" B-after-moves "after" steps "steps") | 104 (println "E =" E-after-moves "after" steps "steps") |
114 count-frames))) | 105 count-frames))) |
115 | 106 |
116 (defn read-user-input [] | 107 (defn read-user-input [] |
117 [;;0x01 ;\ | 108 [0x3E |
118 ;;0x01 ; | | 109 0x20 ; prepare to measure d-pad |
119 ;;0xFE ; | load 0xFF00 into BC without repeats | 110 |
120 ;;0x04 ; | | 111 0x01 ;\ |
121 ;;0x0D ;/ | 112 0x01 ; | |
122 | 113 0xFE ; | load 0xFF00 into BC without repeats |
123 0x11 ; \ | 114 0x04 ; | |
124 0x01 ; | | 115 0x0D ;/ |
125 0xFE ; | load 0xFF44 into DE without repeats | |
126 0x14 ; | | |
127 0x1D ; / | |
128 | 116 |
129 0x3E | 117 0x02 |
130 (Integer/parseInt "00100000" 2) ; prepare to measure d-pad | 118 0x0A ;; get D-pad info |
131 | |
132 0x12 | |
133 0x1A ;; get D-pad info | |
134 | 119 |
135 0xF5 ;; push AF | 120 0xF5 ;; push AF |
136 | 121 |
137 0x3E | 122 0x3E |
138 (Integer/parseInt "00010000" 2) ; prepare to measure buttons | 123 0x10 ; prepare to measure buttons |
124 | |
125 0x3F ;; clear carry flag no-op to prevent repeated nybbbles | |
139 | 126 |
140 0x12 | 127 0x02 |
141 0x1A ;; get button info | 128 0x0A ;; get button info |
142 | |
143 | 129 |
144 0xE6 ;; select bottom bits of A | 130 0xE6 ;; select bottom bits of A |
145 0x0F | 131 0x0F |
146 | 132 |
147 0x57 ;; A->D | 133 0x47 ;; A->B |
148 | 134 |
149 0xF1 ;; pop AF | 135 0xF1 ;; pop AF |
150 | 136 |
151 0xE6 | 137 0xE6 |
152 0x0F ;; select bottom bits of A | 138 0x0F ;; select bottom bits of A |
153 | 139 |
154 0xCB | 140 0xCB |
155 0x37 ;; swap A nybbles | 141 0x37 ;; swap A nybbles |
156 | 142 |
157 0x5A ;; D->E \ necessary to | 143 0xB0 ;; (or A B) -> A |
158 0xB3 ;; (or A D) -> A / prevent repeats. | |
159 | 144 |
160 0x2F ;; (NOT A) -> A | 145 0x2F ;; (NOT A) -> A |
161 ]) | 146 ]) |
162 | 147 |
163 (defn test-read-user-input [] | 148 (defn test-read-user-input [] |
164 (let [program | 149 (let [program |
165 (concat | 150 (concat |
166 (frame-metronome) (read-user-input) | 151 (frame-metronome) (read-user-input) |
167 [0x47 ;; A->B | 152 [0x5F ;; A-> E |
168 0x18 | 153 0x18 |
169 (->signed-8-bit | 154 (->signed-8-bit |
170 (+ (- (count (frame-metronome))) | 155 (+ (- (count (frame-metronome))) |
171 (- (count (read-user-input))) | 156 (- (count (read-user-input))) |
172 (- 3)))]) | 157 (- 3)))]) |
175 (IE! 0) | 160 (IE! 0) |
176 (set-memory-range pokemon-list-start program) | 161 (set-memory-range pokemon-list-start program) |
177 (PC! pokemon-list-start))] | 162 (PC! pokemon-list-start))] |
178 (dorun | 163 (dorun |
179 (for [i (range 0x100)] | 164 (for [i (range 0x100)] |
180 (assert (= (B (step read-input (buttons i))) i)))) | 165 (assert (= (E (step read-input (buttons i))) i)))) |
181 (println "Tested all inputs.") | 166 (println "Tested all inputs.") |
182 read-input)) | 167 read-input)) |
183 | 168 |
184 (def mode-select-mode (Integer/parseInt "00000000" 2)) | 169 (def mode-select-mode (Integer/parseInt "00000000" 2)) |
185 (def write-mode (Integer/parseInt "00000001" 2)) | 170 (def write-mode (Integer/parseInt "00000001" 2)) |
191 (def input-low-addr-write (Integer/parseInt "00000100" 2)) | 176 (def input-low-addr-write (Integer/parseInt "00000100" 2)) |
192 | 177 |
193 (def input-write-num-mode (Integer/parseInt "00001000" 2)) | 178 (def input-write-num-mode (Integer/parseInt "00001000" 2)) |
194 (def do-write-mode (Integer/parseInt "00010000" 2)) | 179 (def do-write-mode (Integer/parseInt "00010000" 2)) |
195 | 180 |
196 | |
197 | |
198 | |
199 | |
200 | |
201 | |
202 (defn main-bootstrap-program [start-address] | 181 (defn main-bootstrap-program [start-address] |
203 (let [[start-high start-low] (disect-bytes-2 start-address) | 182 (let [[start-high start-low] (disect-bytes-2 start-address) |
204 jump-distance (+ (count (frame-metronome) | 183 jump-distance (+ (count (frame-metronome) |
205 (read-user-input))) | 184 (read-user-input))) |
206 | 185 |
207 init | 186 init |
208 [0xAF 0x4F] ;; 0->A; 0->C; | 187 [0xAF 0x4F] ;; 0->A; 0->C; |
188 | |
189 | |
209 | 190 |
210 ;; HL = here | 191 ;; HL = here |
211 ;; add C to HL | 192 ;; add C to HL |
212 ;; jp HL | 193 ;; jp HL |
213 | 194 |
214 prepare-HL | 195 prepare-HL |
215 [0x21] ;; load HL from literal nn | 196 [0xD1 ;; pop DE causes D and E to be non-volitale |
216 ;; nn == here defined below | 197 |
198 0x21 ;; load HL from literal nn | |
199 :dispatch-high | |
200 :dispatch-low] | |
217 | 201 |
218 mode-dispatch | 202 mode-dispatch |
219 [0x06 ;\ | 203 [0xC5 ;; push BC |
204 0x06 ;\ | |
220 0x01 ; | 0->B without repeats | 205 0x01 ; | 0->B without repeats |
221 0x05 ;/ | 206 0x05 ;/ |
222 0x09 ;; add BC to HL | 207 0x09 ;; add BC to HL |
208 0xC1 ;; pop BC | |
223 0xE9] ;; jp | 209 0xE9] ;; jp |
224 | 210 |
225 here | 211 mode-select |
226 (disect-bytes-2 (+ 2 start-address (count init) | 212 [0x4F ;; A->C (this is the address of dispatch above) |
227 jump-distance prepare-HL | 213 0x18 ;; return |
228 (count mode-dispatch))) | 214 :jump-to-end] |
229 | 215 |
230 | 216 input-bytes-to-write |
231 | 217 [0x47 ;; A->B |
232 ;;(here) jr end | 218 0x18 ;; return |
233 | 219 :jump-to-end] |
234 ;;stuff | 220 |
235 ;;modify E | 221 |
236 ;;jr metronome | 222 |
237 | 223 |
238 ;;stuff | 224 |
239 ;;jr metronome | 225 cleanup |
240 | 226 [0xD5 ;; push DE |
241 input-number | |
242 | |
243 [0x47 ;; A->B | |
244 0x1E ;; | |
245 input-high-write-jump | |
246 0x18 | 227 0x18 |
247 (jump-distance ??)] | 228 0x??];; jump all the way back to frame-metronome |
248 | 229 |
249 | 230 |
250 | 231 ;; (concat init (frame-metronome) (read-user-input) |
251 input-high-write | 232 ;; prepare-HL here mode-dispatch) |
252 [0x | |
253 | |
254 | |
255 | |
256 | |
257 | |
258 | |
259 | |
260 (concat init (frame-metronome) (read-user-input) | |
261 prepare-HL here mode-dispatch) | |
262 | 233 |
263 | 234 |
264 | 235 |
265 | 236 |
266 | 237 |
267 | 238 |
268 | 239 |
269 | 240 |
270 )) | 241 ;; )) |
271 | 242 |
272 | 243 |
273 | 244 |
274 | 245 |
275 | 246 |
276 | 247 |
277 | 248 |
278 | 249 |
279 | 250 (comment |
280 | 251 |
281 ;;;;;; TESTS ;;;;;; | 252 ;;;;;; TESTS ;;;;;; |
282 | 253 |
283 (defn bootstrap-base [] | 254 (defn bootstrap-base [] |
284 (let [program (main-bootstrap-program pokemon-list-start)] | 255 (let [program (main-bootstrap-program pokemon-list-start)] |
332 post-jump | 303 post-jump |
333 10000)] | 304 10000)] |
334 (println program-counters) | 305 (println program-counters) |
335 (assert (contains? (set program-counters) target-address)) | 306 (assert (contains? (set program-counters) target-address)) |
336 post-jump)) | 307 post-jump)) |
308 ) |