Mercurial > vba-clojure
diff clojure/com/aurellem/gb/rlm_assembly.clj @ 403:ea37e98e188e
removed one opcode
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 13 Apr 2012 09:59:32 -0500 |
parents | eee219d1a259 |
children | 41647cb85901 |
line wrap: on
line diff
1.1 --- a/clojure/com/aurellem/gb/rlm_assembly.clj Fri Apr 13 09:47:34 2012 -0500 1.2 +++ b/clojure/com/aurellem/gb/rlm_assembly.clj Fri Apr 13 09:59:32 2012 -0500 1.3 @@ -70,26 +70,30 @@ 1.4 (if (< n 0) 1.5 (+ 256 n) n)) 1.6 1.7 -(defn frame-metronome [] 1.8 - (let [init [0xC5] ;; save value of BC 1.9 - timing-loop 1.10 - [0x01 ; \ 1.11 - 0x43 ; | 1.12 - 0xFE ; | load 0xFF44 into BC without repeats 1.13 - 0x0C ; | 1.14 - 0x04 ; / 1.15 - 0x0A] ;; (BC) -> A, now A = LY (vertical line coord) 1.16 - continue-if-144 1.17 - [0xFE 1.18 - 144 ;; compare LY (in A) with 144 1.19 - 0x20 ;; jump back to beginning if LY != 144 (not-v-blank) 1.20 - (->signed-8-bit 1.21 - (+ -4 (- (count timing-loop))))] 1.22 - spin-loop 1.23 - [0x05 ;; dec B, which is 0xFF 1.24 - 0x20 ;; spin until B==0 1.25 - 0xFD]] 1.26 - (concat init timing-loop continue-if-144 spin-loop))) 1.27 +(defn frame-metronome 1.28 + ([] (frame-metronome true)) 1.29 + ([spin-loop?] 1.30 + (let [init [0xC5] ;; save value of BC 1.31 + timing-loop 1.32 + [0x01 ; \ 1.33 + 0x43 ; | 1.34 + 0xFE ; | load 0xFF44 into BC without repeats 1.35 + 0x0C ; | 1.36 + 0x04 ; / 1.37 + 0x0A] ;; (BC) -> A, now A = LY (vertical line coord) 1.38 + continue-if-144 1.39 + [0xFE 1.40 + 144 ;; compare LY (in A) with 144 1.41 + 0x20 ;; jump back to beginning if LY != 144 (not-v-blank) 1.42 + (->signed-8-bit 1.43 + (+ -4 (- (count timing-loop))))] 1.44 + spin-loop 1.45 + [0x05 ;; dec B, which is 0xFF 1.46 + 0x20 ;; spin until B==0 1.47 + 0xFD]] 1.48 + (concat init timing-loop continue-if-144 1.49 + (if spin-loop? 1.50 + spin-loop []))))) 1.51 1.52 (defn test-frame-metronome 1.53 "Ensure that frame-metronome ticks exactly once every frame." 1.54 @@ -182,118 +186,119 @@ 1.55 (partial not= symbol) 1.56 sequence)))) 1.57 1.58 +(defn main-bootstrap-program 1.59 + ([] (main-bootstrap-program pokemon-list-start)) 1.60 + ([start-address] 1.61 + ;; Register Use: 1.62 + 1.63 + ;; ED non-volitale scratch 1.64 + 1.65 + ;; A user-input 1.66 + ;; HL target-address 1.67 + ;; B bytes-to-write 1.68 + ;; C non-volatile scratch 1.69 1.70 -(defn main-bootstrap-program [start-address] 1.71 - ;; Register Use: 1.72 - 1.73 - ;; ED non-volitale scratch 1.74 - 1.75 - ;; A user-input 1.76 - ;; HL target-address 1.77 - ;; B bytes-to-write 1.78 - ;; C non-volatile scratch 1.79 + ;; Modes (with codes) are: 1.80 1.81 - ;; Modes (with codes) are: 1.82 + ;; single-action-modes: 1.83 + ;; SET-TARGET-HIGH 0x67 ;; A->H 1.84 + ;; SET-TARGET-LOW 0x6F ;; A->L 1.85 + ;; JUMP 0xE9 ;; jump to (HL) 1.86 1.87 - ;; single-action-modes: 1.88 - ;; SET-TARGET-HIGH 0x67 ;; A->H 1.89 - ;; SET-TARGET-LOW 0x6F ;; A->L 1.90 - ;; JUMP 0xE9 ;; jump to (HL) 1.91 + ;; multi-action-modes 1.92 + ;; WRITE 0x47 ;; A->B 1.93 1.94 - ;; multi-action-modes 1.95 - ;; WRITE 0x47 ;; A->B 1.96 + (let [[start-high start-low] (disect-bytes-2 start-address) 1.97 + jump-distance (+ (count (frame-metronome)) 1.98 + (count (read-user-input))) 1.99 1.100 - (let [[start-high start-low] (disect-bytes-2 start-address) 1.101 - jump-distance (+ (count (frame-metronome)) 1.102 - (count (read-user-input))) 1.103 + init 1.104 + [0xAF 0x4F 0x47] ;; 0->A; 0->C; 0->B 1.105 1.106 - init 1.107 - [0xAF 0x4F 0x57 0x47] ;; 0->A; 0->C; 0->D; 0->B 1.108 + input 1.109 + [0xC1 ;; pop BC so it's not volatile 1.110 1.111 - input 1.112 - [0xC1 ;; pop BC so it's not volatile 1.113 + 0x5F ;; A->E 1.114 + 0xAF ;; test for output-mode (bytes-to-write > 0) 1.115 + 0xB8 ;; (cp A B) 1.116 + 0x7B ;; E->A 1.117 + 0x20 ;; skip to output section if 1.118 + :to-output ;; we're not in input mode 1.119 + 1.120 + :to-be-executed 1.121 1.122 - 0x5F ;; A->E 1.123 - 0xAF ;; test for output-mode (bytes-to-write > 0) 1.124 - 0xB8 ;; (cp A B) 1.125 - 0x7B ;; E->A 1.126 - 0x20 ;; skip to output section if 1.127 - :to-output ;; we're not in input mode 1.128 - 1.129 - :to-be-executed 1.130 + ;; write mode to instruction-to-be-executed (pun) 1.131 + 0xEA 1.132 + :to-be-executed-address 1.133 1.134 - ;; write mode to instruction-to-be-executed (pun) 1.135 - 0xEA 1.136 - :to-be-executed-address 1.137 + ;; protection region -- do not queue this op for 1.138 + ;; execution if the last one was non-zero 1.139 + 0x79 ;; C->A 1.140 + 0xA7 ;; test A==0 1.141 + 0x28 1.142 + 0x04 1.143 + 0xAF ;; put a no op (0x00) in to-be-executed 1.144 + 0xEA ;; 1.145 + :to-be-executed-address 1.146 + 1.147 + 0x7B ;; E->A 1.148 + 0x4F ;; A->C now C stores previous instruction 1.149 + 0x18 ;; return 1.150 + :to-beginning-1] 1.151 + 1.152 + output 1.153 + [:output-start ;; just a label 1.154 + 0x54 ;; 1.155 + 0x5D ;; HL->DE \ 1.156 + ;; | This mess is here to do 1.157 + 0x12 ;; A->(DE) | 0x22 (LDI (HL), A) without 1.158 + ;; | any repeating nybbles 1.159 + 0x23 ;; inc HL / 1.160 1.161 - ;; protection region -- do not queue this op for 1.162 - ;; execution if the last one was non-zero 1.163 - 0x79 ;; C->A 1.164 - 0xA7 ;; test A==0 1.165 - 0x28 1.166 - 0x04 1.167 - 0xAF ;; put a no op (0x00) in to-be-executed 1.168 - 0xEA ;; 1.169 - :to-be-executed-address 1.170 - 1.171 - 0x7B ;; E->A 1.172 - 0x4F ;; A->C now C stores previous instruction 1.173 - 0x18 ;; return 1.174 - :to-beginning-1] 1.175 - 1.176 - output 1.177 - [:output-start ;; just a label 1.178 - 0x54 ;; 1.179 - 0x5D ;; HL->DE \ 1.180 - ;; | This mess is here to do 1.181 - 0x12 ;; A->(DE) | 0x22 (LDI (HL), A) without 1.182 - ;; | any repeating nybbles 1.183 - 0x23 ;; inc HL / 1.184 + 0x05 ;; DEC bytes-to-write (B) 1.185 1.186 - 0x05 ;; DEC bytes-to-write (B) 1.187 + 0x18 1.188 + :to-beginning-2] 1.189 + 1.190 + symbols 1.191 + {:to-be-executed-address 1.192 + (reverse 1.193 + (disect-bytes-2 1.194 + (+ start-address jump-distance 1.195 + (count init) 1.196 + (symbol-index :to-be-executed input)))) 1.197 + :to-be-executed 0x00} ;; clear carry flag no-op 1.198 1.199 - 0x18 1.200 - :to-beginning-2] 1.201 - 1.202 - symbols 1.203 - {:to-be-executed-address 1.204 - (reverse 1.205 - (disect-bytes-2 1.206 - (+ start-address jump-distance 1.207 - (count init) 1.208 - (symbol-index :to-be-executed input)))) 1.209 - :to-be-executed 0x00} ;; clear carry flag no-op 1.210 + program** (flatten 1.211 + (replace 1.212 + symbols 1.213 + (concat init (frame-metronome) 1.214 + (read-user-input) 1.215 + input output))) 1.216 + resolve-internal-jumps 1.217 + {:output-start [] 1.218 + :to-output 1.219 + (->signed-8-bit 1.220 + (dec 1.221 + (- (symbol-index :output-start program**) 1.222 + (symbol-index :to-output program**))))} 1.223 1.224 - program** (flatten 1.225 - (replace 1.226 - symbols 1.227 - (concat init (frame-metronome) 1.228 - (read-user-input) 1.229 - input output))) 1.230 - resolve-internal-jumps 1.231 - {:output-start [] 1.232 - :to-output 1.233 - (->signed-8-bit 1.234 - (dec 1.235 - (- (symbol-index :output-start program**) 1.236 - (symbol-index :to-output program**))))} 1.237 + program* 1.238 + (flatten (replace resolve-internal-jumps program**)) 1.239 + 1.240 + resolve-external-jumps 1.241 + {:to-beginning-1 1.242 + (->signed-8-bit 1.243 + (+ (count init) 1.244 + -2 (- (dec (symbol-index :to-beginning-1 program*))))) 1.245 + :to-beginning-2 1.246 + (->signed-8-bit 1.247 + (+ (count init) 1.248 + -2 (- (dec (symbol-index :to-beginning-2 program*)))))} 1.249 1.250 - program* 1.251 - (flatten (replace resolve-internal-jumps program**)) 1.252 - 1.253 - resolve-external-jumps 1.254 - {:to-beginning-1 1.255 - (->signed-8-bit 1.256 - (+ (count init) 1.257 - -2 (- (dec (symbol-index :to-beginning-1 program*))))) 1.258 - :to-beginning-2 1.259 - (->signed-8-bit 1.260 - (+ (count init) 1.261 - -2 (- (dec (symbol-index :to-beginning-2 program*)))))} 1.262 - 1.263 - program 1.264 - (replace resolve-external-jumps program*)] 1.265 - program)) 1.266 + program 1.267 + (replace resolve-external-jumps program*)] 1.268 + program))) 1.269 1.270 1.271 ;;;;;; TESTS ;;;;;; 1.272 @@ -324,8 +329,9 @@ 1.273 ;;(println "desired H =" n "actual =" (H after)) 1.274 (assert (= n (H after))) 1.275 after))] 1.276 - (println "tested all H values") 1.277 - (reduce test-H (bootstrap-base) (range 0x100)))) 1.278 + (let [result (reduce test-H (bootstrap-base) (range 0x100))] 1.279 + (println "tested all H values") 1.280 + result))) 1.281 1.282 (defn test-write-bytes [] 1.283 (let [target-address 0xC00F