Mercurial > vba-clojure
comparison clojure/com/aurellem/assembly.clj @ 115:39fb0cbab25e
working on preliminary bootstrap code
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 16 Mar 2012 16:52:29 -0500 |
parents | a454730d92dd |
children | e45031af5327 |
comparison
equal
deleted
inserted
replaced
114:a454730d92dd | 115:39fb0cbab25e |
---|---|
123 ] | 123 ] |
124 | 124 |
125 [])))) | 125 [])))) |
126 | 126 |
127 | 127 |
128 ;; specs for main bootstrap program | |
129 ;; starts in "mode-select" mode | |
130 ;; Each button press takes place in a single frame. | |
131 ;; mode-select-mode takes one of the main buttons | |
132 ;; which selects one of up to eight modes | |
133 ;; mode 1 activated by the "A" button | |
134 ;; the next two button presses indicates the start | |
135 ;; memory location which to which the bootstrap | |
136 ;; program will write. | |
137 ;; This is done by using each of the eight buttons to | |
138 ;; spell out an 8 bit number. The order of buttons is | |
139 ;; ["A" "B" "start" "select" "up" "right" "down" "left"], | |
140 ;; [:a :start :l] --> 10100001 | |
141 | |
142 ;; the next button press determines how many bytes are to be | |
143 ;; written, starting at the start position. | |
144 | |
145 ;; then, the actual bytes are entered and are written to the | |
146 ;; start address in sequence. | |
147 | 128 |
148 | 129 |
149 (defn count-frames [] | 130 (defn count-frames [] |
150 (-> (tick (mid-game)) | 131 (-> (tick (mid-game)) |
151 (IE! 0) ; disable interrupts | 132 (IE! 0) ; disable interrupts |
152 (inject-item-assembly | 133 (inject-item-assembly |
153 ;; write 00010000 to 0xFF00 to select joypad | |
154 [0x18 ;D31D ; jump over | 134 [0x18 ;D31D ; jump over |
155 0x02 ;D31E ; the next 2 bytes | 135 0x02 ;D31E ; the next 2 bytes |
156 0x00 ;D31F ; frame-count | 136 0x00 ;D31F ; frame-count |
157 0x00 ;D320 ; v-blank-prev | 137 0x00 ;D320 ; v-blank-prev |
158 | 138 |
159 0xFA ;D321 | 139 0xFA ;D321 |
160 0x41 ;D322 ; load (FF41) into A | 140 0x41 ;D322 ; load (FF41) into A |
161 0xFF ;D323 ; this contains mode flags | 141 0xFF ;D323 ; this contains mode flags |
162 | |
163 | |
164 | 142 |
165 ;; if we're in v-blank, the bit-1 is 0 | 143 ;; if we're in v-blank, the bit-1 is 0 |
166 ;; and bit-2 is 1 Otherwise, it is not v-blank. | 144 ;; and bit-2 is 1 Otherwise, it is not v-blank. |
167 0xCB ;D324 ; test bit-1 of A | 145 0xCB ;D324 ; test bit-1 of A |
168 0x4F ;D325 | 146 0x4F ;D325 |
169 | 147 |
170 0xC2 ;D326 ; if bit-1 is not 0 | 148 0xC2 ;D326 ; if bit-1 is not 0 |
171 0x43 ;D327 ; GOTO not-v-blank | 149 0x44 ;D327 ; GOTO not-v-blank |
172 0xD3 ;D328 | 150 0xD3 ;D328 |
173 | 151 |
174 0xCB ;D329 ; test bit-0 of A | 152 0xCB ;D329 ; test bit-0 of A |
175 0x47 ;D32A | 153 0x47 ;D32A |
176 | 154 |
177 0xCA ;D32B ; if bit-0 is not 1 | 155 0xCA ;D32B ; if bit-0 is not 1 |
178 0x43 ;D32C ; GOTO not-v-blank | 156 0x44 ;D32C ; GOTO not-v-blank |
179 0xD3 ;D32D | 157 0xD3 ;D32D |
180 | 158 |
181 ;;; in v-blank mode | 159 ;;; in v-blank mode |
182 | 160 |
183 ;; if v-blank-prev was 0, | 161 ;; if v-blank-prev was 0, |
210 | 188 |
211 0xEA ;D33E ; load A into v-blank-prev | 189 0xEA ;D33E ; load A into v-blank-prev |
212 0x20 ;D33F | 190 0x20 ;D33F |
213 0xD3 ;D340 | 191 0xD3 ;D340 |
214 | 192 |
215 0x18 ;D341 ; skip not-in-v-blank section | 193 0xC3 ;D341 ; return to beginning |
216 0x05 ;D342 | 194 0x1D ;D342 |
195 0xD3 ;D343 | |
217 | 196 |
218 ;;; not in v-blank mode | 197 ;;; not in v-blank mode |
219 ;; set v-blank-prev to 0 | 198 ;; set v-blank-prev to 0 |
220 0x3E ;D343 ; load 0 into A | 199 0x3E ;D344 ; load 0 into A |
221 0x00 ;D344 | 200 0x00 ;D345 |
222 | 201 |
223 0xEA ;D345 ; load A into v-blank-prev | 202 0xEA ;D346 ; load A into v-blank-prev |
224 0x20 ;D346 | 203 0x20 ;D347 |
225 0xD3 ;D347 | 204 0xD3 ;D348 |
226 | 205 |
227 | 206 0xC3 ;D349 ; return to beginning |
228 0xC3 ;D348 ; return to beginning | 207 0x1D ;D34A |
229 0x1D ;D349 | 208 0xD3 ;D34B |
230 0xD3 ;D34A | 209 |
231 ]))) | 210 ]))) |
232 | 211 |
233 (defn step-count-frames [] | 212 (defn step-count-frames [] |
234 (-> (read-down-button) | 213 (-> (read-down-button) |
235 (info) | 214 (info) |
254 (tick) | 233 (tick) |
255 (info) | 234 (info) |
256 (tick) | 235 (tick) |
257 (print-inventory))) | 236 (print-inventory))) |
258 | 237 |
259 (defn test-read-down [] | 238 ;;(defn test-read-down [] |
260 (= (view-memory (step (step (read-buttons) [:d])) 0xD328) | 239 ;; (= (view-memory (step (step (read-buttons) [:d])) 0xD328) |
261 (view-memory (step (step (read-buttons))) 0xD328))) | 240 ;; (view-memory (step (step (read-buttons))) 0xD328))) |
262 | 241 |
242 (defn test-count-frames [] | |
243 (= 255 (aget (memory ((apply comp (repeat 255 step)) | |
244 (count-frames))) | |
245 0xD31F))) | |
246 | |
247 | |
263 (defn trace [state] | 248 (defn trace [state] |
264 (loop [program-counters [] | 249 (loop [program-counters [] |
265 opcodes []] | 250 opcodes []] |
266 (let [frame-boundary? | 251 (let [frame-boundary? |
267 (com.aurellem.gb.Gb/tick)] | 252 (com.aurellem.gb.Gb/tick)] |
279 (-> (mid-game) (tick) (IE! 0) | 264 (-> (mid-game) (tick) (IE! 0) |
280 (set-inv-mem [0x00 0x00 0X00 0x00]) | 265 (set-inv-mem [0x00 0x00 0X00 0x00]) |
281 (PC! item-list-start)(print-interrupt) | 266 (PC! item-list-start)(print-interrupt) |
282 (info) (tick) (info) (tick) (info))) | 267 (info) (tick) (info) (tick) (info))) |
283 | 268 |
284 | 269 ;; specs for main bootstrap program |
285 | 270 ;; starts in "mode-select" mode |
286 | 271 ;; Each button press takes place in a single frame. |
287 | 272 ;; mode-select-mode takes one of the main buttons |
288 | 273 ;; which selects one of up to eight modes |
289 | 274 ;; mode 1 activated by the "A" button |
290 | 275 ;; the next two button presses indicates the start |
291 | 276 ;; memory location which to which the bootstrap |
277 ;; program will write. | |
278 ;; This is done by using each of the eight buttons to | |
279 ;; spell out an 8 bit number. The order of buttons is | |
280 ;; ["A" "B" "start" "select" "up" "right" "down" "left"], | |
281 ;; [:a :start :l] --> 10100001 | |
282 | |
283 ;; the next button press determines how many bytes are to be | |
284 ;; written, starting at the start position. | |
285 | |
286 ;; then, the actual bytes are entered and are written to the | |
287 ;; start address in sequence. | |
288 | |
289 | |
290 | |
291 (defn input-number [] | |
292 (-> (tick (mid-game)) | |
293 (IE! 0) ; disable interrupts | |
294 (inject-item-assembly | |
295 [0x18 ;D31D ; jump over | |
296 0x02 ;D31E ; the next 2 bytes | |
297 0x00 ;D31F ; frame-count | |
298 0x00 ;D320 ; v-blank-prev | |
299 | |
300 0xFA ;D321 | |
301 0x41 ;D322 ; load (FF41) into A | |
302 0xFF ;D323 ; this contains mode flags | |
303 | |
304 ;; if we're in v-blank, the bit-1 is 0 | |
305 ;; and bit-2 is 1 Otherwise, it is not v-blank. | |
306 0xCB ;D324 ; test bit-1 of A | |
307 0x4F ;D325 | |
308 | |
309 0xC2 ;D326 ; if bit-1 is not 0 | |
310 0x44 ;D327 ; GOTO not-v-blank | |
311 0xD3 ;D328 | |
312 | |
313 0xCB ;D329 ; test bit-0 of A | |
314 0x47 ;D32A | |
315 | |
316 0xCA ;D32B ; if bit-0 is not 1 | |
317 0x44 ;D32C ; GOTO not-v-blank | |
318 0xD3 ;D32D | |
319 | |
320 ;;; in v-blank mode | |
321 | |
322 ;; if v-blank-prev was 0, | |
323 ;; increment frame-count | |
324 | |
325 0xFA ;D32E ; load v-blank-prev to A | |
326 0x20 ;D32F | |
327 0xD3 ;D330 | |
328 | |
329 0xCB ;D331 | |
330 0x47 ;D332 ; test bit-0 of A | |
331 | |
332 0x20 ;D333 ; skip next section | |
333 0x07 ;D334 ; if v-blank-prev was not zero | |
334 | |
335 ;; v-blank was 0, increment frame-count | |
336 0xFA ;D335 ; load frame-count into A | |
337 0x1F ;D336 | |
338 0xD3 ;D337 | |
339 | |
340 0x3C ;D338 ; inc A | |
341 | |
342 0xEA ;D339 ; load A into frame-count | |
343 0x1F ;D33A | |
344 0xD3 ;D33B | |
345 | |
346 ;; set v-blank-prev to 1 | |
347 0x3E ;D33C ; load 1 into A | |
348 0x01 ;D33D | |
349 | |
350 0xEA ;D33E ; load A into v-blank-prev | |
351 0x20 ;D33F | |
352 0xD3 ;D340 | |
353 | |
354 0xC3 ;D341 ; GOTO input handling code | |
355 0x4E ;D342 | |
356 0xD3 ;D343 | |
357 | |
358 ;;; not in v-blank mode | |
359 ;; set v-blank-prev to 0 | |
360 0x3E ;D344 ; load 0 into A | |
361 0x00 ;D345 | |
362 | |
363 0xEA ;D346 ; load A into v-blank-prev | |
364 0x20 ;D347 | |
365 0xD3 ;D348 | |
366 | |
367 0xC3 ;D349 ; return to beginning | |
368 0x1D ;D34A | |
369 0xD3 ;D34B | |
370 | |
371 0x00 ;D34C ; these are here | |
372 0x00 ;D34D ; for glue | |
373 | |
374 | |
375 ;;; calculate input number based on button presses | |
376 0x18 ;D34E ; skip next 3 bytes | |
377 0x03 ;D34F | |
378 ;D350 | |
379 (Integer/parseInt "00100000" 2) ; select directional pad | |
380 ;D351 | |
381 (Integer/parseInt "00010000" 2) ; select buttons | |
382 0x00 ;D352 ; input-number | |
383 | |
384 ;; select directional pad, store low bits in B | |
385 | |
386 0xFA ;D353 ; load (D350) into A | |
387 0x50 ;D354 --> | |
388 0xD3 ;D355 --> D31F | |
389 | |
390 0xEA ;D356 ; load (A), which is | |
391 0x00 ;D357 --> ; 00010000, into FF00 | |
392 0xFF ;D358 --> FF00 | |
393 | |
394 0x06 ;D359 | |
395 ;D35A | |
396 (Integer/parseInt "11110000") ; "11110000" -> B | |
397 0xFA ;D35B ; (FF00) -> A | |
398 0x00 ;D35C | |
399 0xFF ;D35D | |
400 | |
401 0xCB ;D35E ; swap nybbles on A | |
402 0x37 ;D35F | |
403 0xA0 ;D360 ; (AND A B) -> A | |
404 0x47 ;D361 ; A -> B | |
405 | |
406 ;; select buttons store bottom bits in C | |
407 | |
408 0xFA ; ; load (D351) into A | |
409 0x51 ; --> | |
410 0xD3 ; --> D31F | |
411 | |
412 0xEA ; ; load (A), which is | |
413 0x00 ; --> ; 00001000, into FF00 | |
414 0xFF ; --> FF00 | |
415 | |
416 0x0E ; | |
417 (Integer/parseInt "00001111") ; "00001111" -> C | |
418 | |
419 0xFA ; ; (FF00) -> A | |
420 0x00 ; | |
421 0xFF ; | |
422 | |
423 0xA1 ; ; (AND A C) -> A | |
424 0x4F ; ; A -> C | |
425 | |
426 | |
427 ;; combine the B and C registers into the input number | |
428 0x79 ; ; C -> A | |
429 0xB0 ; ; (OR A B) -> A | |
430 0x2F ; ; negate A | |
431 | |
432 0xEA ; ; store A into input-number | |
433 0x52 ; | |
434 0xD3 ; | |
435 | |
436 0xC3 ; ; return to beginning | |
437 0x1D ; | |
438 0xD3 ; | |
439 ]))) | |
440 | |
441 | |
442 | |
443 | |
444 (defn print-listing [state begin end] | |
445 (dorun (map | |
446 (fn [opcode line] | |
447 (println (format "0x%04X: 0x%02X" line opcode))) | |
448 (subvec (vec (memory state)) begin end) | |
449 (range begin end)))) | |
450 | |
451 | |
452 | |
453 | |
454 | |
455 | |
456 | |
457 |