diff clojure/com/aurellem/gb/rlm_assembly.clj @ 377:1f14c1b8af7e

working on main bootstrap program
author Robert McIntyre <rlm@mit.edu>
date Wed, 11 Apr 2012 10:47:27 -0500
parents
children 5c4a30521d09
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/clojure/com/aurellem/gb/rlm_assembly.clj	Wed Apr 11 10:47:27 2012 -0500
     1.3 @@ -0,0 +1,122 @@
     1.4 +(ns com.aurellem.gb.rlm-assembly
     1.5 +  "Version of main bootstrap program that is valid output for the
     1.6 +   item-writer program."
     1.7 +  (:use (com.aurellem.gb gb-driver assembly util vbm constants))
     1.8 +  (:use (com.aurellem.run bootstrap-1))
     1.9 +  (:import [com.aurellem.gb.gb_driver SaveState]))
    1.10 +
    1.11 +;; Specs for Main Bootstrap Program
    1.12 +
    1.13 +;; Number-Input
    1.14 +;; Number input works using all eight buttons to
    1.15 +;;   spell out an 8 bit number.  The order of buttons is
    1.16 +;;   [:d :u :l :r :start :select :b :a]  -->  11111111
    1.17 +;;   [      :l    :start            :a]  -->  00101001
    1.18 +
    1.19 +;;; MODE-SELECT
    1.20 +;;   The bootstrap program starts in MODE-SELECT mode.
    1.21 +;;   MODE-SELECT transitions to one of three modes depending
    1.22 +;;   on which buttons are pressed:
    1.23 +;;       0   (no-buttons)  :  MODE-SELECT
    1.24 +;;       8   [:start]      :  WRITE-BYTES
    1.25 +;;    0xFF   (all-buttons) :  JUMP
    1.26 +
    1.27 +;;; WRITE-BYTES
    1.28 +
    1.29 +;;   WRITE-BYTES mode writes sequences of arbitray values to
    1.30 +;;   arbitray memory locations. It expects you to enter a
    1.31 +;;   header of three bytes describing what to write:
    1.32 +
    1.33 +;;    Byte 0  : Number of Bytes to Write
    1.34 +;;    Byte 1  : Start Address High Byte
    1.35 +;;    Byte 1  : Start Address Low  Byte
    1.36 +
    1.37 +;;   Then, you enter the number of bytes specified in Byte 0
    1.38 +;;   they are written to the start address in
    1.39 +;;   sequence. After the last byte is written control
    1.40 +;;   returns to MODE-SELECT mode.
    1.41 +
    1.42 +;;   Example: to write the sequence [1 2 3 4] starting at
    1.43 +;;   address 0xC01F enter
    1.44 +;;    Byte 0  : 4 (will write four bytes)
    1.45 +;;    Byte 1  : 0xC0  (high byte of 0xC01F)
    1.46 +;;    Byte 2  : 0x1F  (low  byte of 0xC01F)
    1.47 +;;    Byte 3  : 1 (write 1 to 0xC01F)
    1.48 +;;    Byte 4  : 2 (write 2 to 0xC020)
    1.49 +;;    Byte 5  : 3 (write 3 to 0xC021)
    1.50 +;;    Byte 6  : 4 (write 4 to 0xC022)
    1.51 +
    1.52 +;;; JUMP 
    1.53 +;;   JUMP mode jumps program control to any arbitray
    1.54 +;;   location. It expects you to enter two bytes which
    1.55 +;;   correspond to the high and low bytes of the memory
    1.56 +;;   address to which you want to jump.
    1.57 +;;    Byte 0  : Jump Address High Byte
    1.58 +;;    Byte 1  : Jump Address Low  Byte
    1.59 +
    1.60 +;;   Example: to jump to address 0x1234 enter
    1.61 +;;    Byte 0  : 0x12 (high byte of 0x1234)
    1.62 +;;    Byte 1  : 0x34 (low  byte of 0x1234)
    1.63 +
    1.64 +
    1.65 +
    1.66 +(defn main-bootstrap-program [start-address]
    1.67 +  (let [[start-high start-low] (disect-bytes-2 start-address)]
    1.68 +    [0xF3 0x18 0xFE]))
    1.69 +
    1.70 +;;;;;; TESTS ;;;;;;
    1.71 +
    1.72 +(defn bootstrap-base []
    1.73 +  (let [program (main-bootstrap-program pokemon-list-start)]
    1.74 +    ;; make sure program is valid output for item-writer
    1.75 +    (bootstrap-pattern program)
    1.76 +    (-> (tick (mid-game))
    1.77 +        (set-memory-range pokemon-list-start program)
    1.78 +        (PC! pokemon-list-start))))
    1.79 +
    1.80 +(defn test-write-bytes-mode []
    1.81 +  (let [target-address 0xC00F
    1.82 +        [target-high target-low] (disect-bytes-2 target-address)
    1.83 +        assembly [0xF3 0x18 0xFE 0x12]
    1.84 +        get-mem-region  #(subvec (vec (memory %))
    1.85 +                                 target-address (+ target-address 20))
    1.86 +        before (bootstrap-base)
    1.87 +        after
    1.88 +        (-> before
    1.89 +            (step [])                       ; make sure it can handle blanks
    1.90 +            (step [])                       ; at the beginning.
    1.91 +            (step [])                      
    1.92 +            (step [:start])                 ; select WRITE-BYTES mode
    1.93 +            (step (buttons 4))              ; write 4 bytes
    1.94 +            (step (buttons target-high))
    1.95 +            (step (buttons target-low))
    1.96 +            (step (buttons (nth assembly 0)))
    1.97 +            (step (buttons (nth assembly 1)))
    1.98 +            (step (buttons (nth assembly 2)))
    1.99 +            (step (buttons (nth assembly 3)))
   1.100 +            (step [])
   1.101 +            (step [])
   1.102 +            (step []))]
   1.103 +            (println "before :" (get-mem-region before))
   1.104 +            (println "after  :" (get-mem-region after))
   1.105 +            (assert (= assembly (take 4 (get-mem-region after))))
   1.106 +    after))
   1.107 +
   1.108 +(defn test-jump-mode []
   1.109 +  (let [target-address 0xC00F
   1.110 +        [target-high target-low] (disect-bytes-2 target-address)
   1.111 +        post-jump
   1.112 +        (-> (test-write-bytes-mode)
   1.113 +            (step [])
   1.114 +            (step [])
   1.115 +            (step [])
   1.116 +            (step (buttons 0xFF))           ; Select JUMP mode.
   1.117 +            (step (buttons target-high))
   1.118 +            (step (buttons target-low)))
   1.119 +        program-counters
   1.120 +        (capture-program-counter 
   1.121 +         post-jump
   1.122 +         10000)]
   1.123 +    (println program-counters)
   1.124 +    (assert (contains? (set program-counters) target-address))
   1.125 +    post-jump))