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