comparison clojure/com/aurellem/gb/rlm_assembly.clj @ 390:dbf7b5a2e9e7

saving progress.
author Robert McIntyre <rlm@mit.edu>
date Wed, 11 Apr 2012 23:40:01 -0500
parents bb8978d370d8
children 2e9b2d27f32f
comparison
equal deleted inserted replaced
389:bb8978d370d8 390:dbf7b5a2e9e7
2 "Version of main bootstrap program that is valid output for the 2 "Version of main bootstrap program that is valid output for the
3 item-writer program." 3 item-writer program."
4 (:use (com.aurellem.gb gb-driver assembly util vbm constants)) 4 (:use (com.aurellem.gb gb-driver assembly util vbm constants))
5 (:use (com.aurellem.run bootstrap-1)) 5 (:use (com.aurellem.run bootstrap-1))
6 (:import [com.aurellem.gb.gb_driver SaveState])) 6 (:import [com.aurellem.gb.gb_driver SaveState]))
7
8
9 ;; MODE-SELECT
10 ;; SET-LENGTH
11 ;; SET-TARGET
12 ;; WRITE
13 ;; JUMP
7 14
8 ;; Specs for Main Bootstrap Program 15 ;; Specs for Main Bootstrap Program
9 16
10 ;; Number-Input 17 ;; Number-Input
11 ;; Number input works using all eight buttons to 18 ;; Number input works using all eight buttons to
62 (defn ->signed-8-bit [n] 69 (defn ->signed-8-bit [n]
63 (if (< n 0) 70 (if (< n 0)
64 (+ 256 n) n)) 71 (+ 256 n) n))
65 72
66 (defn frame-metronome [] 73 (defn frame-metronome []
67 (let [timing-loop 74 (let [init [0xC5] ;; save value of BC
75 timing-loop
68 [0x01 ; \ 76 [0x01 ; \
69 0x43 ; | 77 0x43 ; |
70 0xFE ; | load 0xFF44 into BC without repeats 78 0xFE ; | load 0xFF44 into BC without repeats
71 0x0C ; | 79 0x0C ; |
72 0x04 ; / 80 0x04 ; /
79 (+ -4 (- (count timing-loop))))] 87 (+ -4 (- (count timing-loop))))]
80 spin-loop 88 spin-loop
81 [0x05 ;; dec B, which is 0xFF 89 [0x05 ;; dec B, which is 0xFF
82 0x20 ;; spin until B==0 90 0x20 ;; spin until B==0
83 0xFD]] 91 0xFD]]
84 (concat timing-loop continue-if-144 spin-loop))) 92 (concat init timing-loop continue-if-144 spin-loop)))
85 93
86 (defn test-frame-metronome 94 (defn test-frame-metronome
87 "Ensure that frame-metronome ticks exactly once every frame." 95 "Ensure that frame-metronome ticks exactly once every frame."
88 ([] (test-frame-metronome 151)) 96 ([] (test-frame-metronome 151))
89 ([steps] 97 ([steps]
95 (-> (tick (mid-game)) 103 (-> (tick (mid-game))
96 (IE! 0) 104 (IE! 0)
97 (DE! 0) 105 (DE! 0)
98 (set-memory-range pokemon-list-start program) 106 (set-memory-range pokemon-list-start program)
99 (PC! pokemon-list-start)) 107 (PC! pokemon-list-start))
100 E-after-moves (E (run-moves count-frames (repeat steps [])))] 108 E-after-moves
109 (E (run-moves count-frames (repeat steps [])))]
101 (println "E:" E-after-moves) 110 (println "E:" E-after-moves)
102 (assert (= steps E-after-moves)) 111 (assert (= steps E-after-moves))
103 112
104 (println "E =" E-after-moves "after" steps "steps") 113 (println "E =" E-after-moves "after" steps "steps")
105 count-frames))) 114 count-frames)))
141 0x37 ;; swap A nybbles 150 0x37 ;; swap A nybbles
142 151
143 0xB0 ;; (or A B) -> A 152 0xB0 ;; (or A B) -> A
144 153
145 0x2F ;; (NOT A) -> A 154 0x2F ;; (NOT A) -> A
155
146 ]) 156 ])
147 157
148 (defn test-read-user-input [] 158 (defn test-read-user-input []
149 (let [program 159 (let [program
150 (concat 160 (concat
177 187
178 (def input-write-num-mode (Integer/parseInt "00001000" 2)) 188 (def input-write-num-mode (Integer/parseInt "00001000" 2))
179 (def do-write-mode (Integer/parseInt "00010000" 2)) 189 (def do-write-mode (Integer/parseInt "00010000" 2))
180 190
181 (defn main-bootstrap-program [start-address] 191 (defn main-bootstrap-program [start-address]
192 ;; Register Use:
193
194 ;; BC persistent scratch
195 ;;
196 ;; A user-input
197 ;; HL target-address
198 ;; D current-mode
199 ;; E bytes-to-write
200
201
202 ;; Modes are:
203
204 ;; single-action-modes:
205 ;; SET-MODE
206 ;; SET-TARGET-HIGH
207 ;; SET-TARGET-LOW
208 ;; SET-WRITE-LENGTH
209 ;; JUMP
210
211 ;; multi-action-modes
212 ;; WRITE
213
214
215
182 (let [[start-high start-low] (disect-bytes-2 start-address) 216 (let [[start-high start-low] (disect-bytes-2 start-address)
183 jump-distance (+ (count (frame-metronome) 217 jump-distance (+ (count (frame-metronome))
184 (read-user-input))) 218 (read-user-input))
185 219
186 init 220 init
187 [0xAF 0x5F] ;; 0->A; 0->E; 221 [0xAF 0x5F 0x57 0x47] ;; 0->A; 0->E; 0->D; 0->B
188 222
189 223
190 header 224
191 [0x47] ;; A->B 225
192 226 input
193 mode-select 227 [0xC1 ;; pop BC so it's not volatile
194 [0xCB 0x43 ;; last-bit is zero 228 ;; some condition
195 0x28 :to-beginning 229 ;; to skip if not in input
196 0x5F];; A->E 230 ;; mode
197 231
198 input-section 232
199 [0xCB 0x4B ;; test bit 0 of E 233
200 0x28 0x03 234
201 235 0xE9 ;; jump to (HL)
202 236
237 0x22 ;; A->(HL) ; inc HL
238
239
203 0x57 ;; A->D 240 0x57 ;; A->D
204 241
205 0x67 ;; A->H 242 0x67 ;; A->H
206 0x6F ;; A->L 243 0x6F ;; A->L
207 244
217 254
218 ;; HL = here 255 ;; HL = here
219 ;; add C to HL 256 ;; add C to HL
220 ;; jp HL 257 ;; jp HL
221 258
222 prepare-HL 259 ]]))
223 [0xD1 ;; pop DE causes D and E to be non-volitale
224
225 0x21 ;; load HL from literal nn
226 :dispatch-high
227 :dispatch-low]
228
229 mode-dispatch
230 [0xC5 ;; push BC
231 0x06 ;\
232 0x01 ; | 0->B without repeats
233 0x05 ;/
234 0x09 ;; add BC to HL
235 0xC1 ;; pop BC
236 0xE9] ;; jp
237
238 mode-select
239 [0x4F ;; A->C (this is the address of dispatch above)
240 0x18 ;; return
241 :jump-to-end]
242
243 input-bytes-to-write
244 [0x47 ;; A->B
245 0x18 ;; return
246 :jump-to-end]
247
248
249
250
251
252 cleanup
253 [0xD5 ;; push DE
254 0x18
255 0x??];; jump all the way back to frame-metronome
256
257
258 ;; (concat init (frame-metronome) (read-user-input)
259 ;; prepare-HL here mode-dispatch)
260
261
262
263
264
265
266
267
268 ;; ))
269
270 260
271 261
272 262
273 263
274 264