comparison clojure/com/aurellem/gb/rlm_assembly.clj @ 388:a0d0e1a46b1d

had to change programs to prevent repeats.
author Robert McIntyre <rlm@mit.edu>
date Thu, 12 Apr 2012 10:20:38 -0500
parents 47d44bb54d32
children bb8978d370d8
comparison
equal deleted inserted replaced
387:47d44bb54d32 388:a0d0e1a46b1d
63 (if (< n 0) 63 (if (< n 0)
64 (+ 256 n) n)) 64 (+ 256 n) n))
65 65
66 (defn frame-metronome [] 66 (defn frame-metronome []
67 (let [timing-loop 67 (let [timing-loop
68 [;;0x01 ; \ 68 [0x01 ; \
69 ;;0x43 ; | 69 0x43 ; |
70 ;;0xFE ; | load 0xFF44 into BC without repeats 70 0xFE ; | load 0xFF44 into BC without repeats
71 ;;0x0C ; | 71 0x0C ; |
72 ;;0x04 ; / 72 0x04 ; /
73 ;;0x0A ;; (BC) -> A, now A = LY (vertical line coord) 73 0x0A] ;; (BC) -> A, now A = LY (vertical line coord)
74
75 0x11 ; \
76 0x43 ; |
77 0xFE ; | load 0xFF44 into DE without repeats
78 0x1C ; |
79 0x14 ; /
80 0x1A ;; (DE) -> A, now A = LY (vertical line coord)
81 ]
82 continue-if-144 74 continue-if-144
83 [0xFE 75 [0xFE
84 144 ;; compare LY (in A) with 144 76 144 ;; compare LY (in A) with 144
85 0x20 ;; jump back to beginning if LY != 144 (not-v-blank) 77 0x20 ;; jump back to beginning if LY != 144 (not-v-blank)
86 (->signed-8-bit 78 (->signed-8-bit
87 (+ -4 (- (count timing-loop))))] 79 (+ -4 (- (count timing-loop))))]
88 spin-loop 80 spin-loop
89 [;;0x05 ;; dec B, which is 0xFF 81 [0x05 ;; dec B, which is 0xFF
90 0x15 ;; dec D, which is 0xFF
91 0x20 ;; spin until B==0 82 0x20 ;; spin until B==0
92 0xFD]] 83 0xFD]]
93 (concat timing-loop continue-if-144 spin-loop))) 84 (concat timing-loop continue-if-144 spin-loop)))
94 85
95 (defn test-frame-metronome 86 (defn test-frame-metronome
96 "Ensure that frame-metronome ticks exactly once every frame." 87 "Ensure that frame-metronome ticks exactly once every frame."
97 ([] (test-frame-metronome 151)) 88 ([] (test-frame-metronome 151))
98 ([steps] 89 ([steps]
99 (let [inc-B [0x04 0x18 90 (let [inc-E [0x1C 0x18
100 (->signed-8-bit 91 (->signed-8-bit
101 (+ -3 (- (count (frame-metronome)))))] 92 (+ -3 (- (count (frame-metronome)))))]
102 program (concat (frame-metronome) inc-B) 93 program (concat (frame-metronome) inc-E)
103 count-frames 94 count-frames
104 (-> (tick (mid-game)) 95 (-> (tick (mid-game))
105 (IE! 0) 96 (IE! 0)
106 (BC! 0) 97 (DE! 0)
107 (set-memory-range pokemon-list-start program) 98 (set-memory-range pokemon-list-start program)
108 (PC! pokemon-list-start)) 99 (PC! pokemon-list-start))
109 B-after-moves (B (run-moves count-frames (repeat steps [])))] 100 E-after-moves (E (run-moves count-frames (repeat steps [])))]
110 (println "B:" B-after-moves) 101 (println "E:" E-after-moves)
111 (assert (= steps B-after-moves)) 102 (assert (= steps E-after-moves))
112 103
113 (println "B =" B-after-moves "after" steps "steps") 104 (println "E =" E-after-moves "after" steps "steps")
114 count-frames))) 105 count-frames)))
115 106
116 (defn read-user-input [] 107 (defn read-user-input []
117 [;;0x01 ;\ 108 [0x3E
118 ;;0x01 ; | 109 0x20 ; prepare to measure d-pad
119 ;;0xFE ; | load 0xFF00 into BC without repeats 110
120 ;;0x04 ; | 111 0x01 ;\
121 ;;0x0D ;/ 112 0x01 ; |
122 113 0xFE ; | load 0xFF00 into BC without repeats
123 0x11 ; \ 114 0x04 ; |
124 0x01 ; | 115 0x0D ;/
125 0xFE ; | load 0xFF44 into DE without repeats
126 0x14 ; |
127 0x1D ; /
128 116
129 0x3E 117 0x02
130 (Integer/parseInt "00100000" 2) ; prepare to measure d-pad 118 0x0A ;; get D-pad info
131
132 0x12
133 0x1A ;; get D-pad info
134 119
135 0xF5 ;; push AF 120 0xF5 ;; push AF
136 121
137 0x3E 122 0x3E
138 (Integer/parseInt "00010000" 2) ; prepare to measure buttons 123 0x10 ; prepare to measure buttons
124
125 0x3F ;; clear carry flag no-op to prevent repeated nybbbles
139 126
140 0x12 127 0x02
141 0x1A ;; get button info 128 0x0A ;; get button info
142
143 129
144 0xE6 ;; select bottom bits of A 130 0xE6 ;; select bottom bits of A
145 0x0F 131 0x0F
146 132
147 0x57 ;; A->D 133 0x47 ;; A->B
148 134
149 0xF1 ;; pop AF 135 0xF1 ;; pop AF
150 136
151 0xE6 137 0xE6
152 0x0F ;; select bottom bits of A 138 0x0F ;; select bottom bits of A
153 139
154 0xCB 140 0xCB
155 0x37 ;; swap A nybbles 141 0x37 ;; swap A nybbles
156 142
157 0x5A ;; D->E \ necessary to 143 0xB0 ;; (or A B) -> A
158 0xB3 ;; (or A D) -> A / prevent repeats.
159 144
160 0x2F ;; (NOT A) -> A 145 0x2F ;; (NOT A) -> A
161 ]) 146 ])
162 147
163 (defn test-read-user-input [] 148 (defn test-read-user-input []
164 (let [program 149 (let [program
165 (concat 150 (concat
166 (frame-metronome) (read-user-input) 151 (frame-metronome) (read-user-input)
167 [0x47 ;; A->B 152 [0x5F ;; A-> E
168 0x18 153 0x18
169 (->signed-8-bit 154 (->signed-8-bit
170 (+ (- (count (frame-metronome))) 155 (+ (- (count (frame-metronome)))
171 (- (count (read-user-input))) 156 (- (count (read-user-input)))
172 (- 3)))]) 157 (- 3)))])
175 (IE! 0) 160 (IE! 0)
176 (set-memory-range pokemon-list-start program) 161 (set-memory-range pokemon-list-start program)
177 (PC! pokemon-list-start))] 162 (PC! pokemon-list-start))]
178 (dorun 163 (dorun
179 (for [i (range 0x100)] 164 (for [i (range 0x100)]
180 (assert (= (B (step read-input (buttons i))) i)))) 165 (assert (= (E (step read-input (buttons i))) i))))
181 (println "Tested all inputs.") 166 (println "Tested all inputs.")
182 read-input)) 167 read-input))
183 168
184 (def mode-select-mode (Integer/parseInt "00000000" 2)) 169 (def mode-select-mode (Integer/parseInt "00000000" 2))
185 (def write-mode (Integer/parseInt "00000001" 2)) 170 (def write-mode (Integer/parseInt "00000001" 2))
191 (def input-low-addr-write (Integer/parseInt "00000100" 2)) 176 (def input-low-addr-write (Integer/parseInt "00000100" 2))
192 177
193 (def input-write-num-mode (Integer/parseInt "00001000" 2)) 178 (def input-write-num-mode (Integer/parseInt "00001000" 2))
194 (def do-write-mode (Integer/parseInt "00010000" 2)) 179 (def do-write-mode (Integer/parseInt "00010000" 2))
195 180
196
197
198
199
200
201
202 (defn main-bootstrap-program [start-address] 181 (defn main-bootstrap-program [start-address]
203 (let [[start-high start-low] (disect-bytes-2 start-address) 182 (let [[start-high start-low] (disect-bytes-2 start-address)
204 jump-distance (+ (count (frame-metronome) 183 jump-distance (+ (count (frame-metronome)
205 (read-user-input))) 184 (read-user-input)))
206 185
207 init 186 init
208 [0xAF 0x4F] ;; 0->A; 0->C; 187 [0xAF 0x4F] ;; 0->A; 0->C;
188
189
209 190
210 ;; HL = here 191 ;; HL = here
211 ;; add C to HL 192 ;; add C to HL
212 ;; jp HL 193 ;; jp HL
213 194
214 prepare-HL 195 prepare-HL
215 [0x21] ;; load HL from literal nn 196 [0xD1 ;; pop DE causes D and E to be non-volitale
216 ;; nn == here defined below 197
198 0x21 ;; load HL from literal nn
199 :dispatch-high
200 :dispatch-low]
217 201
218 mode-dispatch 202 mode-dispatch
219 [0x06 ;\ 203 [0xC5 ;; push BC
204 0x06 ;\
220 0x01 ; | 0->B without repeats 205 0x01 ; | 0->B without repeats
221 0x05 ;/ 206 0x05 ;/
222 0x09 ;; add BC to HL 207 0x09 ;; add BC to HL
208 0xC1 ;; pop BC
223 0xE9] ;; jp 209 0xE9] ;; jp
224 210
225 here 211 mode-select
226 (disect-bytes-2 (+ 2 start-address (count init) 212 [0x4F ;; A->C (this is the address of dispatch above)
227 jump-distance prepare-HL 213 0x18 ;; return
228 (count mode-dispatch))) 214 :jump-to-end]
229 215
230 216 input-bytes-to-write
231 217 [0x47 ;; A->B
232 ;;(here) jr end 218 0x18 ;; return
233 219 :jump-to-end]
234 ;;stuff 220
235 ;;modify E 221
236 ;;jr metronome 222
237 223
238 ;;stuff 224
239 ;;jr metronome 225 cleanup
240 226 [0xD5 ;; push DE
241 input-number
242
243 [0x47 ;; A->B
244 0x1E ;;
245 input-high-write-jump
246 0x18 227 0x18
247 (jump-distance ??)] 228 0x??];; jump all the way back to frame-metronome
248 229
249 230
250 231 ;; (concat init (frame-metronome) (read-user-input)
251 input-high-write 232 ;; prepare-HL here mode-dispatch)
252 [0x
253
254
255
256
257
258
259
260 (concat init (frame-metronome) (read-user-input)
261 prepare-HL here mode-dispatch)
262 233
263 234
264 235
265 236
266 237
267 238
268 239
269 240
270 )) 241 ;; ))
271 242
272 243
273 244
274 245
275 246
276 247
277 248
278 249
279 250 (comment
280 251
281 ;;;;;; TESTS ;;;;;; 252 ;;;;;; TESTS ;;;;;;
282 253
283 (defn bootstrap-base [] 254 (defn bootstrap-base []
284 (let [program (main-bootstrap-program pokemon-list-start)] 255 (let [program (main-bootstrap-program pokemon-list-start)]
332 post-jump 303 post-jump
333 10000)] 304 10000)]
334 (println program-counters) 305 (println program-counters)
335 (assert (contains? (set program-counters) target-address)) 306 (assert (contains? (set program-counters) target-address))
336 post-jump)) 307 post-jump))
308 )