# HG changeset patch # User Robert McIntyre # Date 1331934749 18000 # Node ID 39fb0cbab25e89e5f8523bac2bb04c281aff3467 # Parent a454730d92ddd7cac4f138885392c96dcb194e67 working on preliminary bootstrap code diff -r a454730d92dd -r 39fb0cbab25e clojure/com/aurellem/assembly.clj --- a/clojure/com/aurellem/assembly.clj Fri Mar 16 13:51:17 2012 -0500 +++ b/clojure/com/aurellem/assembly.clj Fri Mar 16 16:52:29 2012 -0500 @@ -125,32 +125,12 @@ [])))) -;; specs for main bootstrap program -;; starts in "mode-select" mode -;; Each button press takes place in a single frame. -;; mode-select-mode takes one of the main buttons -;; which selects one of up to eight modes -;; mode 1 activated by the "A" button -;; the next two button presses indicates the start -;; memory location which to which the bootstrap -;; program will write. -;; This is done by using each of the eight buttons to -;; spell out an 8 bit number. The order of buttons is -;; ["A" "B" "start" "select" "up" "right" "down" "left"], -;; [:a :start :l] --> 10100001 - -;; the next button press determines how many bytes are to be -;; written, starting at the start position. - -;; then, the actual bytes are entered and are written to the -;; start address in sequence. (defn count-frames [] (-> (tick (mid-game)) (IE! 0) ; disable interrupts (inject-item-assembly - ;; write 00010000 to 0xFF00 to select joypad [0x18 ;D31D ; jump over 0x02 ;D31E ; the next 2 bytes 0x00 ;D31F ; frame-count @@ -159,8 +139,6 @@ 0xFA ;D321 0x41 ;D322 ; load (FF41) into A 0xFF ;D323 ; this contains mode flags - - ;; if we're in v-blank, the bit-1 is 0 ;; and bit-2 is 1 Otherwise, it is not v-blank. @@ -168,14 +146,14 @@ 0x4F ;D325 0xC2 ;D326 ; if bit-1 is not 0 - 0x43 ;D327 ; GOTO not-v-blank + 0x44 ;D327 ; GOTO not-v-blank 0xD3 ;D328 0xCB ;D329 ; test bit-0 of A 0x47 ;D32A 0xCA ;D32B ; if bit-0 is not 1 - 0x43 ;D32C ; GOTO not-v-blank + 0x44 ;D32C ; GOTO not-v-blank 0xD3 ;D32D ;;; in v-blank mode @@ -212,22 +190,23 @@ 0x20 ;D33F 0xD3 ;D340 - 0x18 ;D341 ; skip not-in-v-blank section - 0x05 ;D342 + 0xC3 ;D341 ; return to beginning + 0x1D ;D342 + 0xD3 ;D343 ;;; not in v-blank mode ;; set v-blank-prev to 0 - 0x3E ;D343 ; load 0 into A - 0x00 ;D344 + 0x3E ;D344 ; load 0 into A + 0x00 ;D345 - 0xEA ;D345 ; load A into v-blank-prev - 0x20 ;D346 - 0xD3 ;D347 + 0xEA ;D346 ; load A into v-blank-prev + 0x20 ;D347 + 0xD3 ;D348 + + 0xC3 ;D349 ; return to beginning + 0x1D ;D34A + 0xD3 ;D34B - - 0xC3 ;D348 ; return to beginning - 0x1D ;D349 - 0xD3 ;D34A ]))) (defn step-count-frames [] @@ -256,10 +235,16 @@ (tick) (print-inventory))) -(defn test-read-down [] - (= (view-memory (step (step (read-buttons) [:d])) 0xD328) - (view-memory (step (step (read-buttons))) 0xD328))) - +;;(defn test-read-down [] +;; (= (view-memory (step (step (read-buttons) [:d])) 0xD328) +;; (view-memory (step (step (read-buttons))) 0xD328))) + +(defn test-count-frames [] + (= 255 (aget (memory ((apply comp (repeat 255 step)) + (count-frames))) + 0xD31F))) + + (defn trace [state] (loop [program-counters [] opcodes []] @@ -281,11 +266,192 @@ (PC! item-list-start)(print-interrupt) (info) (tick) (info) (tick) (info))) +;; specs for main bootstrap program +;; starts in "mode-select" mode +;; Each button press takes place in a single frame. +;; mode-select-mode takes one of the main buttons +;; which selects one of up to eight modes +;; mode 1 activated by the "A" button +;; the next two button presses indicates the start +;; memory location which to which the bootstrap +;; program will write. +;; This is done by using each of the eight buttons to +;; spell out an 8 bit number. The order of buttons is +;; ["A" "B" "start" "select" "up" "right" "down" "left"], +;; [:a :start :l] --> 10100001 +;; the next button press determines how many bytes are to be +;; written, starting at the start position. +;; then, the actual bytes are entered and are written to the +;; start address in sequence. +(defn input-number [] + (-> (tick (mid-game)) + (IE! 0) ; disable interrupts + (inject-item-assembly + [0x18 ;D31D ; jump over + 0x02 ;D31E ; the next 2 bytes + 0x00 ;D31F ; frame-count + 0x00 ;D320 ; v-blank-prev + + 0xFA ;D321 + 0x41 ;D322 ; load (FF41) into A + 0xFF ;D323 ; this contains mode flags + + ;; if we're in v-blank, the bit-1 is 0 + ;; and bit-2 is 1 Otherwise, it is not v-blank. + 0xCB ;D324 ; test bit-1 of A + 0x4F ;D325 + 0xC2 ;D326 ; if bit-1 is not 0 + 0x44 ;D327 ; GOTO not-v-blank + 0xD3 ;D328 + + 0xCB ;D329 ; test bit-0 of A + 0x47 ;D32A + 0xCA ;D32B ; if bit-0 is not 1 + 0x44 ;D32C ; GOTO not-v-blank + 0xD3 ;D32D + + ;;; in v-blank mode + ;; if v-blank-prev was 0, + ;; increment frame-count + + 0xFA ;D32E ; load v-blank-prev to A + 0x20 ;D32F + 0xD3 ;D330 + + 0xCB ;D331 + 0x47 ;D332 ; test bit-0 of A + + 0x20 ;D333 ; skip next section + 0x07 ;D334 ; if v-blank-prev was not zero + + ;; v-blank was 0, increment frame-count + 0xFA ;D335 ; load frame-count into A + 0x1F ;D336 + 0xD3 ;D337 + + 0x3C ;D338 ; inc A + + 0xEA ;D339 ; load A into frame-count + 0x1F ;D33A + 0xD3 ;D33B + + ;; set v-blank-prev to 1 + 0x3E ;D33C ; load 1 into A + 0x01 ;D33D + + 0xEA ;D33E ; load A into v-blank-prev + 0x20 ;D33F + 0xD3 ;D340 + + 0xC3 ;D341 ; GOTO input handling code + 0x4E ;D342 + 0xD3 ;D343 + + ;;; not in v-blank mode + ;; set v-blank-prev to 0 + 0x3E ;D344 ; load 0 into A + 0x00 ;D345 + + 0xEA ;D346 ; load A into v-blank-prev + 0x20 ;D347 + 0xD3 ;D348 + + 0xC3 ;D349 ; return to beginning + 0x1D ;D34A + 0xD3 ;D34B + + 0x00 ;D34C ; these are here + 0x00 ;D34D ; for glue + + + ;;; calculate input number based on button presses + 0x18 ;D34E ; skip next 3 bytes + 0x03 ;D34F + ;D350 + (Integer/parseInt "00100000" 2) ; select directional pad + ;D351 + (Integer/parseInt "00010000" 2) ; select buttons + 0x00 ;D352 ; input-number + + ;; select directional pad, store low bits in B + + 0xFA ;D353 ; load (D350) into A + 0x50 ;D354 --> + 0xD3 ;D355 --> D31F + + 0xEA ;D356 ; load (A), which is + 0x00 ;D357 --> ; 00010000, into FF00 + 0xFF ;D358 --> FF00 + + 0x06 ;D359 + ;D35A + (Integer/parseInt "11110000") ; "11110000" -> B + 0xFA ;D35B ; (FF00) -> A + 0x00 ;D35C + 0xFF ;D35D + + 0xCB ;D35E ; swap nybbles on A + 0x37 ;D35F + 0xA0 ;D360 ; (AND A B) -> A + 0x47 ;D361 ; A -> B + + ;; select buttons store bottom bits in C + + 0xFA ; ; load (D351) into A + 0x51 ; --> + 0xD3 ; --> D31F + + 0xEA ; ; load (A), which is + 0x00 ; --> ; 00001000, into FF00 + 0xFF ; --> FF00 + + 0x0E ; + (Integer/parseInt "00001111") ; "00001111" -> C + + 0xFA ; ; (FF00) -> A + 0x00 ; + 0xFF ; + + 0xA1 ; ; (AND A C) -> A + 0x4F ; ; A -> C + + + ;; combine the B and C registers into the input number + 0x79 ; ; C -> A + 0xB0 ; ; (OR A B) -> A + 0x2F ; ; negate A + + 0xEA ; ; store A into input-number + 0x52 ; + 0xD3 ; + + 0xC3 ; ; return to beginning + 0x1D ; + 0xD3 ; + ]))) + + + + +(defn print-listing [state begin end] + (dorun (map + (fn [opcode line] + (println (format "0x%04X: 0x%02X" line opcode))) + (subvec (vec (memory state)) begin end) + (range begin end)))) + + + + + + + +