annotate clojure/com/aurellem/gb/assembly.clj @ 175:5d9a7a0ca09a

beginning test of latest assembly code. 240->70.
author Dylan Holmes <ocsenave@gmail.com>
date Wed, 21 Mar 2012 18:17:37 -0500
parents 412ca096a9ba
children 95b2758dd517
rev   line source
rlm@145 1 (ns com.aurellem.gb.assembly
rlm@145 2 (:use (com.aurellem.gb gb-driver vbm util items))
rlm@145 3 (:import [com.aurellem.gb.gb_driver SaveState]))
rlm@145 4
rlm@145 5 (defn inject-assembly
rlm@145 6 ([^SaveState state
rlm@145 7 program-counter registers
rlm@145 8 assembly-code]
rlm@145 9 (let [scratch-memory (memory state)]
rlm@145 10 ;; inject assembly code
rlm@145 11 (dorun (map (fn [index val]
rlm@145 12 (aset scratch-memory index val))
rlm@145 13 (range program-counter
rlm@145 14 (+ program-counter (count assembly-code)))
rlm@145 15 assembly-code))
rlm@145 16 (-> state
rlm@145 17 (write-memory! scratch-memory)
rlm@145 18 (write-registers! registers)
rlm@145 19 (PC! program-counter)))))
rlm@145 20
rlm@145 21 (defn inject-item-assembly
rlm@145 22 ([^SaveState state assembly-code]
rlm@145 23 (inject-assembly state (inc item-list-start)
rlm@145 24 (registers state)
rlm@145 25 assembly-code))
rlm@145 26 ([assembly-code]
rlm@145 27 (inject-item-assembly @current-state assembly-code)))
rlm@145 28
rlm@145 29 (defn run-assembly
rlm@145 30 ([info-fn assembly n]
rlm@145 31 (let [final-state
rlm@145 32 (reduce (fn [state _]
rlm@145 33 (tick (info-fn state)))
rlm@145 34 (inject-item-assembly
rlm@145 35 (mid-game) assembly)
rlm@145 36 (range n))]
rlm@145 37 final-state))
rlm@145 38 ([assembly n]
rlm@145 39 (run-assembly d-tick assembly n)))
rlm@145 40
rlm@145 41 (def buttons-port 0xFF00)
rlm@145 42
rlm@145 43 (defn trace [state]
rlm@145 44 (loop [program-counters [(first (registers @current-state)) ]
rlm@145 45 opcodes [(aget (memory @current-state) (PC @current-state))]]
rlm@145 46 (let [frame-boundary?
rlm@145 47 (com.aurellem.gb.Gb/tick)]
rlm@145 48 (if frame-boundary?
rlm@145 49 [program-counters opcodes]
rlm@145 50 (recur
rlm@145 51 (conj program-counters
rlm@145 52 (first (registers @current-state)))
rlm@145 53 (conj opcodes
rlm@145 54 (aget (memory @current-state)
rlm@145 55 (PC @current-state))))))))
rlm@145 56
rlm@145 57 (defn print-trace [state n]
rlm@145 58 (let [[program-counters opcodes] (trace state)]
rlm@145 59 (dorun (map (fn [pc op] (println (format "%04X: 0x%02X" pc op)))
rlm@145 60 (take n program-counters)
rlm@145 61 (take n opcodes)))))
rlm@145 62
rlm@145 63 (defn good-trace []
rlm@145 64 (-> (mid-game) (tick) (IE! 0)
rlm@145 65 (set-inv-mem [0x00 0x00 0X00 0x00])
rlm@145 66 (PC! item-list-start)(print-interrupt)
rlm@145 67 (d-tick) (tick) (d-tick) (tick) (d-tick)))
rlm@145 68
rlm@145 69 (defn read-down-button []
rlm@145 70 (-> (tick (mid-game))
rlm@145 71 (IE! 0) ; disable interrupts
rlm@145 72 (inject-item-assembly
rlm@145 73 ;; write 00010000 to 0xFF00 to select joypad
rlm@145 74 [0x18 ;D31D ; jump over
rlm@145 75 0x01 ;D31E ; the next 8 bits
rlm@145 76 ;D31F
rlm@145 77 (Integer/parseInt "00100000" 2) ; data section
rlm@145 78
rlm@145 79 0xFA ;D320 ; load (D31F) into A
rlm@145 80 0x1F ;D321 -->
rlm@145 81 0xD3 ;D322 --> D31F
rlm@145 82
rlm@145 83 0xEA ;D323 ; load (A), which is
rlm@145 84 0x00 ;D324 --> ; 00010000, into FF00
rlm@145 85 0xFF ;D325 --> FF00
rlm@145 86
rlm@145 87 0x18 ;D326 ; this is the place where
rlm@145 88 0x01 ;D327 ; we will store whether
rlm@145 89 0x00 ;D328 ; "down" is pressed.
rlm@145 90
rlm@145 91 0xFA ;D329 ; (FF00) -> A
rlm@145 92 0x00 ;D32A
rlm@145 93 0xFF ;D32B
rlm@145 94
rlm@145 95 0xCB ;D32C ; Test whether "down"
rlm@145 96 0x5F ;D32D ; is pressed.
rlm@145 97
rlm@145 98 0x28 ;D32E ; if down is pressed,
rlm@145 99 0x03 ;D32F ; skip the next section
rlm@145 100 ; of code.
rlm@145 101 ;; down-is-not-pressed
rlm@145 102 0xC3 ;D330
rlm@145 103 0x1D ;D331 ; return to beginning
rlm@145 104 0xD3 ;D332
rlm@145 105
rlm@145 106 ;; down-is-pressed
rlm@145 107 0xEA ;D334 ; write A to D328 if
rlm@145 108 0x28 ;D335 ; "down" was pressed
rlm@145 109 0xD3 ;D336
rlm@145 110
rlm@145 111 0xC3 ;D330
rlm@145 112 0x1D ;D331 ; return to beginning
rlm@145 113 0xD3 ;D332
rlm@145 114 ])))
rlm@145 115
rlm@145 116 (defn test-read-down []
rlm@145 117 (= (view-memory (step (step (read-down-button) [:d])) 0xD328)
rlm@145 118 (view-memory (step (step (read-down-button))) 0xD328)))
rlm@145 119
rlm@145 120 (defn count-frames []
rlm@145 121 (-> (tick (mid-game))
rlm@145 122 (IE! 0) ; disable interrupts
rlm@145 123 (inject-item-assembly
rlm@145 124 [0x18 ;D31D ; jump over
rlm@145 125 0x02 ;D31E ; the next 2 bytes
rlm@145 126 0x00 ;D31F ; frame-count
rlm@145 127 0x00 ;D320 ; v-blank-prev
rlm@145 128
rlm@145 129 0xFA ;D321
rlm@145 130 0x41 ;D322 ; load (FF41) into A
rlm@145 131 0xFF ;D323 ; this contains mode flags
rlm@145 132
rlm@145 133 ;; if we're in v-blank, the bit-1 is 0
rlm@145 134 ;; and bit-2 is 1 Otherwise, it is not v-blank.
rlm@145 135 0xCB ;D324 ; test bit-1 of A
rlm@145 136 0x4F ;D325
rlm@145 137
rlm@145 138 0xC2 ;D326 ; if bit-1 is not 0
rlm@145 139 0x44 ;D327 ; GOTO not-v-blank
rlm@145 140 0xD3 ;D328
rlm@145 141
rlm@145 142 0xCB ;D329 ; test bit-0 of A
rlm@145 143 0x47 ;D32A
rlm@145 144
rlm@145 145 0xCA ;D32B ; if bit-0 is not 1
rlm@145 146 0x44 ;D32C ; GOTO not-v-blank
rlm@145 147 0xD3 ;D32D
rlm@145 148 ;;; in v-blank mode
rlm@145 149 ;; if v-blank-prev was 0,
rlm@145 150 ;; increment frame-count
rlm@145 151
rlm@145 152 0xFA ;D32E ; load v-blank-prev to A
rlm@145 153 0x20 ;D32F
rlm@145 154 0xD3 ;D330
rlm@145 155
rlm@145 156 0xCB ;D331
rlm@145 157 0x47 ;D332 ; test bit-0 of A
rlm@145 158
rlm@145 159 0x20 ;D333 ; skip next section
rlm@145 160 0x07 ;D334 ; if v-blank-prev was not zero
rlm@145 161
rlm@145 162 ;; v-blank was 0, increment frame-count
rlm@145 163 0xFA ;D335 ; load frame-count into A
rlm@145 164 0x1F ;D336
rlm@145 165 0xD3 ;D337
rlm@145 166
rlm@145 167 0x3C ;D338 ; inc A
rlm@145 168
rlm@145 169 0xEA ;D339 ; load A into frame-count
rlm@145 170 0x1F ;D33A
rlm@145 171 0xD3 ;D33B
rlm@145 172
rlm@145 173 ;; set v-blank-prev to 1
rlm@145 174 0x3E ;D33C ; load 1 into A
rlm@145 175 0x01 ;D33D
rlm@145 176
rlm@145 177 0xEA ;D33E ; load A into v-blank-prev
rlm@145 178 0x20 ;D33F
rlm@145 179 0xD3 ;D340
rlm@145 180
rlm@145 181 0xC3 ;D341 ; return to beginning
rlm@145 182 0x1D ;D342
rlm@145 183 0xD3 ;D343
rlm@145 184
rlm@145 185 ;;; not in v-blank mode
rlm@145 186 ;; set v-blank-prev to 0
rlm@145 187 0x3E ;D344 ; load 0 into A
rlm@145 188 0x00 ;D345
rlm@145 189
rlm@145 190 0xEA ;D346 ; load A into v-blank-prev
rlm@145 191 0x20 ;D347
rlm@145 192 0xD3 ;D348
rlm@145 193
rlm@145 194 0xC3 ;D349 ; return to beginning
rlm@145 195 0x1D ;D34A
rlm@145 196 0xD3 ;D34B
rlm@145 197 ])))
rlm@145 198
rlm@145 199 (defn step-count-frames []
rlm@145 200 (-> (read-down-button)
rlm@145 201 (d-tick)
rlm@145 202 (tick) ;; skip over data section
rlm@145 203 (d-tick)
rlm@145 204 (view-register "Register A" A)
rlm@145 205 (tick) ;; load-data into A
rlm@145 206 (view-register "Register A" A)
rlm@145 207 (d-tick)
rlm@145 208 (view-memory 0xFF00)
rlm@145 209 (tick) ;; load A into 0xFF00
rlm@145 210 (view-memory 0xFF00)
rlm@145 211 (d-tick)
rlm@145 212 (tick)
rlm@145 213 (d-tick)
rlm@145 214 (tick)
rlm@145 215 (d-tick)
rlm@145 216 (tick)
rlm@145 217 (d-tick)
rlm@145 218 (tick)
rlm@145 219 (d-tick)
rlm@145 220 (tick)
rlm@145 221 (d-tick)
rlm@145 222 (tick)
rlm@145 223 (print-inventory)))
rlm@145 224
rlm@145 225 (defn test-count-frames []
rlm@145 226 (= 255 (aget (memory ((apply comp (repeat 255 step))
rlm@145 227 (count-frames)))
rlm@145 228 0xD31F)))
rlm@145 229
rlm@145 230 ;; specs for main bootstrap program
rlm@145 231 ;; starts in "mode-select" mode
rlm@145 232 ;; Each button press takes place in a single frame.
rlm@145 233 ;; mode-select-mode takes one of the main buttons
rlm@145 234 ;; which selects one of up to eight modes
rlm@145 235 ;; mode 1 activated by the "A" button
rlm@145 236 ;; the next two button presses indicates the start
rlm@145 237 ;; memory location which to which the bootstrap
rlm@145 238 ;; program will write.
rlm@145 239 ;; This is done by using each of the eight buttons to
rlm@145 240 ;; spell out an 8 bit number. The order of buttons is
rlm@145 241 ;; [:d :u :l :r :start :select :b :a]
rlm@145 242 ;; [:a :start :l] --> 00101001
rlm@145 243
rlm@145 244 ;; the next button press determines how many bytes are to be
rlm@145 245 ;; written, starting at the start position.
rlm@145 246
rlm@145 247 ;; then, the actual bytes are entered and are written to the
rlm@145 248 ;; start address in sequence.
rlm@145 249
rlm@145 250 (defn input-number-assembly []
rlm@145 251 [0x18 ;D31D ; jump over
rlm@145 252 0x02 ;D31E ; the next 2 bytes
rlm@145 253 0x00 ;D31F ; frame-count
rlm@145 254 0x00 ;D320 ; v-blank-prev
rlm@145 255
rlm@145 256 0xFA ;D321
rlm@145 257 0x41 ;D322 ; load (FF41) into A
rlm@145 258 0xFF ;D323 ; this contains mode flags
rlm@145 259
rlm@145 260 ;; if we're in v-blank, the bit-1 is 0
rlm@145 261 ;; and bit-2 is 1 Otherwise, it is not v-blank.
rlm@145 262 0xCB ;D324 ; test bit-1 of A
rlm@145 263 0x4F ;D325
rlm@145 264
rlm@145 265 0xC2 ;D326 ; if bit-1 is not 0
rlm@145 266 0x44 ;D327 ; GOTO not-v-blank
rlm@145 267 0xD3 ;D328
rlm@145 268
rlm@145 269 0xCB ;D329 ; test bit-0 of A
rlm@145 270 0x47 ;D32A
rlm@145 271
rlm@145 272 0xCA ;D32B ; if bit-0 is not 1
rlm@145 273 0x44 ;D32C ; GOTO not-v-blank
rlm@145 274 0xD3 ;D32D
rlm@145 275
rlm@145 276 ;;; in v-blank mode
rlm@145 277
rlm@145 278 ;; if v-blank-prev was 0,
rlm@145 279 ;; increment frame-count
rlm@145 280
rlm@145 281 0xFA ;D32E ; load v-blank-prev to A
rlm@145 282 0x20 ;D32F
rlm@145 283 0xD3 ;D330
rlm@145 284
rlm@145 285 0xCB ;D331
rlm@145 286 0x47 ;D332 ; test bit-0 of A
rlm@145 287
rlm@145 288 0x20 ;D333 ; skip next section
rlm@145 289 0x07 ;D334 ; if v-blank-prev was not zero
rlm@145 290
rlm@145 291 ;; v-blank was 0, increment frame-count
rlm@145 292 0xFA ;D335 ; load frame-count into A
rlm@145 293 0x1F ;D336
rlm@145 294 0xD3 ;D337
rlm@145 295
rlm@145 296 0x3C ;D338 ; inc A
rlm@145 297
rlm@145 298 0xEA ;D339 ; load A into frame-count
rlm@145 299 0x1F ;D33A
rlm@145 300 0xD3 ;D33B
rlm@145 301
rlm@145 302 ;; set v-blank-prev to 1
rlm@145 303 0x3E ;D33C ; load 1 into A
rlm@145 304 0x01 ;D33D
rlm@145 305
rlm@145 306 0xEA ;D33E ; load A into v-blank-prev
rlm@145 307 0x20 ;D33F
rlm@145 308 0xD3 ;D340
rlm@145 309
rlm@145 310 0xC3 ;D341 ; GOTO input handling code
rlm@145 311 0x4E ;D342
rlm@145 312 0xD3 ;D343
rlm@145 313
rlm@145 314 ;;; not in v-blank mode
rlm@145 315 ;; set v-blank-prev to 0
rlm@145 316 0x3E ;D344 ; load 0 into A
rlm@145 317 0x00 ;D345
rlm@145 318
rlm@145 319 0xEA ;D346 ; load A into v-blank-prev
rlm@145 320 0x20 ;D347
rlm@145 321 0xD3 ;D348
rlm@145 322
rlm@145 323 0xC3 ;D349 ; return to beginning
rlm@145 324 0x1D ;D34A
rlm@145 325 0xD3 ;D34B
rlm@145 326
rlm@145 327 0x00 ;D34C ; these are here
rlm@145 328 0x00 ;D34D ; for glue
rlm@145 329
rlm@145 330
rlm@145 331 ;;; calculate input number based on button presses
rlm@145 332 0x18 ;D34E ; skip next 3 bytes
rlm@145 333 0x03 ;D34F
rlm@145 334 ;D350
rlm@145 335 (Integer/parseInt "00100000" 2) ; select directional pad
rlm@145 336 ;D351
rlm@145 337 (Integer/parseInt "00010000" 2) ; select buttons
rlm@145 338 0x00 ;D352 ; input-number
rlm@145 339
rlm@145 340 ;; select directional pad, store low bits in B
rlm@145 341
rlm@145 342 0xFA ;D353 ; load (D350) into A
rlm@145 343 0x50 ;D354 -->
rlm@145 344 0xD3 ;D355 --> D31F
rlm@145 345
rlm@145 346 0xEA ;D356 ; load A, which is
rlm@145 347 0x00 ;D357 --> ; 00010000, into FF00
rlm@145 348 0xFF ;D358 --> FF00
rlm@145 349
rlm@145 350 0x06 ;D359
rlm@145 351 ;D35A
rlm@145 352 (Integer/parseInt "11110000" 2) ; "11110000" -> B
rlm@145 353 0xFA ;D35B ; (FF00) -> A
rlm@145 354 0x00 ;D35C
rlm@145 355 0xFF ;D35D
rlm@145 356
rlm@145 357 0xCB ;D35E ; swap nybbles on A
rlm@145 358 0x37 ;D35F
rlm@145 359 0xA0 ;D360 ; (AND A B) -> A
rlm@145 360 0x47 ;D361 ; A -> B
rlm@145 361
rlm@145 362 ;; select buttons store bottom bits in C
rlm@145 363
rlm@145 364 0xFA ; ; load (D351) into A
rlm@145 365 0x51 ; -->
rlm@145 366 0xD3 ; --> D31F
rlm@145 367
rlm@145 368 0xEA ; ; load (A), which is
rlm@145 369 0x00 ; --> ; 00001000, into FF00
rlm@145 370 0xFF ; --> FF00
rlm@145 371
rlm@145 372 0x0E ;
rlm@145 373 (Integer/parseInt "00001111" 2) ; "00001111" -> C
rlm@145 374
rlm@145 375 0xFA ; ; (FF00) -> A
rlm@145 376 0x00 ;
rlm@145 377 0xFF ;
rlm@145 378
rlm@145 379 0xA1 ; ; (AND A C) -> A
rlm@145 380 0x4F ; ; A -> C
rlm@145 381
rlm@145 382 ;; combine the B and C registers into the input number
rlm@145 383 0x79 ; ; C -> A
rlm@145 384 0xB0 ; ; (OR A B) -> A
rlm@145 385 0x2F ; ; negate A
rlm@145 386
rlm@145 387 0xEA ; ; store A into input-number
rlm@145 388 0x52 ;
rlm@145 389 0xD3 ;
rlm@145 390
rlm@145 391 0xC3 ; ; return to beginning
rlm@145 392 0x1D ;
rlm@145 393 0xD3 ;
rlm@145 394 ])
rlm@145 395
rlm@145 396
rlm@145 397
rlm@145 398 (defn input-number []
rlm@145 399 (-> (tick (mid-game))
rlm@145 400 (IE! 0) ; disable interrupts
rlm@145 401 (inject-item-assembly (input-number-assembly))))
rlm@145 402
rlm@145 403 (defn test-input-number
rlm@145 404 "Input freestyle buttons and observe the effects at the repl."
rlm@145 405 []
rlm@145 406 (set-state! (input-number))
rlm@145 407 (dotimes [_ 90000] (step (view-memory @current-state 0xD352))))
rlm@145 408
rlm@145 409
rlm@145 410 (defn write-memory-assembly*
ocsenave@175 411 "A program for altering in-game memory by pressing buttons."
rlm@145 412 []
rlm@145 413 [
ocsenave@175 414 0xF3 ; stop interrupts
ocsenave@175 415 ;; --------- CLEANUP
ocsenave@175 416 0xAF ; zero A [D31E]
ocsenave@175 417 0x57 ; A->D; makes D=0.
ocsenave@175 418
rlm@145 419 ;; --------- FRAME METRONOME
ocsenave@175 420 0xF1 ;; pop AF (vblank prev) [D320]
rlm@145 421
ocsenave@175 422 0x2F ;; invert A
ocsenave@175 423 0x47 ;; A -> B
ocsenave@175 424
ocsenave@175 425 0xF0 ;; copy STAT into A
rlm@145 426 0x41
rlm@145 427
ocsenave@175 428 0xCB ;; swap A nybbles; now A_0 is (VB==1).
ocsenave@175 429 0x37
rlm@145 430
ocsenave@175 431 0xF5 ;; push AF (vbprev)
rlm@145 432
ocsenave@175 433 0xA0 ;; A & B --> A. Now A_0 contains "increment?"
ocsenave@175 434
ocsenave@175 435 0xCB ;; test A_0. this result will be used twice.
ocsenave@175 436 0x47
ocsenave@175 437 0x28 ;; end frame (JUMP) if A_0 = 0.
ocsenave@175 438 0x00 ;; TODO: set jump length
rlm@145 439
rlm@145 440 ;; -------- GET BUTTON INPUT
ocsenave@175 441
ocsenave@175 442 ;; btw, Z bit is now 1
rlm@145 443 ;; prepare to select bits
rlm@145 444
rlm@145 445 0x3E ;; load 0x20 into A, to measure dpad
rlm@145 446 0x20
ocsenave@175 447
ocsenave@175 448 0x06 ;; load 0x00 into B
ocsenave@175 449 0x00 ;; to initialize for "OR" loop
rlm@145 450
rlm@145 451 0xE0 ;; load A into [FF00] ;; start of OR loop [D33C]
rlm@145 452 0x00
rlm@145 453
rlm@145 454 0xF0 ;; load A from [FF00]
rlm@145 455 0x00
rlm@145 456
rlm@145 457 0xE6 ;; bitmask 00001111
rlm@145 458 0x0F
rlm@145 459
rlm@145 460 0xB0 ;; A or B --> A
ocsenave@175 461
ocsenave@175 462 0x28 ;; JUMP forward if Z=0
rlm@145 463 0x08
rlm@145 464
rlm@145 465 0x47 ;; A -> B
rlm@145 466 0xCB ;; swap B nybbles
rlm@145 467 0x30
ocsenave@175 468
rlm@145 469 0x3E ;; load 0x10 into A, to measure btns
rlm@145 470 0x10
ocsenave@175 471
ocsenave@175 472 0xBF ;; compare(A,A) sets Z=0
ocsenave@175 473
rlm@145 474 0x18 ;; JUMP back to "load A into [FF00]" [20 steps?]
rlm@145 475 0xED
rlm@145 476
rlm@145 477
rlm@145 478 ;; ------ TAKE ACTION BASED ON USER INPUT
rlm@145 479
rlm@145 480 ;; "input mode"
rlm@145 481 ;; mode 0x00 : select mode
rlm@145 482 ;; mode 0x08 : select bytes-to-write
rlm@145 483 ;; mode 0x10 : select hi-bit
rlm@145 484 ;; mode 0x18 : select lo-bit
rlm@145 485
rlm@145 486 ;; "output mode"
rlm@145 487 ;; mode 0x20 : write bytes
rlm@145 488 ;; mode 0xFF : jump PC
rlm@145 489
rlm@145 490
rlm@145 491 ;; registers
rlm@145 492 ;; D : mode select
rlm@145 493 ;; E : count of bytes to write
rlm@145 494 ;; H : address-high
rlm@145 495 ;; L : address-low
rlm@145 496
rlm@145 497 ;; now A contains the pressed keys
rlm@145 498 0x2F ; complement A, by request. [D34F]
rlm@145 499
rlm@145 500 0x47 ; A->B ;; now B contains the pressed keys
rlm@145 501
rlm@145 502 0xCB ; test bit 5 of D (are we in o/p mode?)
rlm@145 503 0x6A
rlm@145 504 0x28 ; if test == 0, skip this o/p section
rlm@145 505 0x13 ; JUMP
rlm@145 506
rlm@145 507 0xCB ; else, test bit 0 of D (fragile; are we in pc mode?)
rlm@145 508 0x42
rlm@145 509 0x28 ; if test == 0, skip the following command
rlm@145 510 0x01
rlm@145 511
rlm@145 512 ;; output mode I: moving the program counter
rlm@145 513 0xE9 ; ** move PC to (HL)
rlm@145 514
rlm@145 515 ;; output mode II: writing bytes
ocsenave@175 516 0xAF ; zero A
ocsenave@175 517 0xBB ; compare count to zero. finished writing?
ocsenave@175 518 0x28 ; if we are finished, jump back to cleanup
ocsenave@175 519 0x00 ; TODO: set jump length backwards.
rlm@145 520
rlm@145 521 ;; continue writing bytes
ocsenave@175 522 0x78 ;; B->A
ocsenave@175 523 0x22 ;; copy A to (HL) and increment HL.
rlm@145 524 0x18 ;; end frame. [goto D31F]
ocsenave@175 525 0xB6 ;; JUMP
rlm@145 526
rlm@145 527
rlm@145 528 ;; ---- end of o/p section
rlm@145 529
rlm@145 530 ;; i/p mode
rlm@145 531 ;; adhere to the mode discipline:
rlm@145 532 ;; D must be one of 0x00 0x08 0x10 0x18.
rlm@145 533
rlm@145 534 0x3E ;; load the constant 57 into A. [D369]
rlm@145 535 0x57
rlm@145 536 0x82 ;; add the mode to A
rlm@145 537 0xEA ;; store A into "thing to execute"
rlm@145 538 0x74
rlm@145 539 0xD3
rlm@145 540
rlm@145 541 0x3E ;; load the constant 8 into A
rlm@145 542 0x08
rlm@145 543 0x82 ;; add the mode to A
rlm@145 544
rlm@145 545 0x57 ;; store the incremented mode into D
rlm@145 546 0x78 ;; B->A; now A contains the pressed keys
rlm@145 547
rlm@145 548 0x00 ;; var: thing to execute [D374]
rlm@145 549
rlm@145 550 0x18 ;; end frame
ocsenave@175 551 0xA8 ;; JUMP
rlm@145 552 ]
rlm@145 553 )
rlm@145 554
rlm@145 555 (defn write-mem-dyl []
rlm@145 556 (-> (tick (mid-game))
rlm@145 557 (IE! 0)
rlm@145 558 (inject-item-assembly (write-memory-assembly*))))
rlm@145 559
rlm@145 560
rlm@145 561 (defn dylan* []
rlm@145 562 (->
rlm@145 563 (write-mem-dyl)
rlm@145 564
rlm@145 565 (tick)
rlm@145 566 (tick)
rlm@145 567 (tick)
rlm@145 568 (tick)
rlm@145 569 (tick)
rlm@145 570 (tick)
rlm@145 571 (tick)
rlm@145 572 (tick)
rlm@145 573 (tick)
rlm@145 574 (tick)
rlm@145 575 (tick)
rlm@145 576 (tick)
rlm@145 577 (tick)
rlm@145 578 (tick)
rlm@145 579 (tick)
rlm@145 580 (tick)
rlm@145 581 (tick)
rlm@145 582 (tick)
rlm@145 583 (tick)
rlm@145 584 (tick)
rlm@145 585 (tick)
rlm@145 586 (tick)
rlm@145 587 (tick)
rlm@145 588 (tick)
rlm@145 589 (tick)
rlm@145 590 (tick)
rlm@145 591 (tick)
rlm@145 592 (tick)
rlm@145 593 (tick)
rlm@145 594 (tick)
rlm@145 595 (tick)
rlm@145 596 (tick)
rlm@145 597 (tick)
rlm@145 598 (tick)
rlm@145 599 (tick)
rlm@145 600 (tick)
rlm@145 601
rlm@145 602 ;;(view-memory 0xD374)
rlm@145 603 (tick)
rlm@145 604 (tick)
rlm@145 605 (tick)
rlm@145 606 (tick)
rlm@145 607 (tick)
rlm@145 608 (tick)
rlm@145 609 (tick)
rlm@145 610 (tick)
rlm@145 611 (tick)
rlm@145 612 (tick)
rlm@145 613 (tick)
rlm@145 614 (tick)
rlm@145 615 (tick)
rlm@145 616 (tick)
rlm@145 617 (tick)
rlm@145 618 ;;(view-memory 0xD374)
rlm@145 619 (d-tick)
rlm@145 620
rlm@145 621 (view-register "A" A)
rlm@145 622 (view-register "B" B)
rlm@145 623 (view-register "C" C))
rlm@145 624
rlm@145 625 )
rlm@145 626
rlm@145 627
rlm@145 628 (defn dylan []
rlm@145 629 (->
rlm@145 630 (write-mem-dyl)
rlm@145 631 (tick)
rlm@145 632 (tick)
rlm@145 633 (tick)
rlm@145 634 (tick)
rlm@145 635 (tick)
rlm@145 636 (tick)
rlm@145 637 (tick)
rlm@145 638 (tick)
rlm@145 639 (tick)
rlm@145 640 (tick)
rlm@145 641 (tick)
rlm@145 642 (tick)
rlm@145 643 (tick)
rlm@145 644 (tick)
rlm@145 645 (tick) ;; first loop
rlm@145 646
rlm@145 647
rlm@145 648 (tick)
rlm@145 649 (tick)
rlm@145 650 (tick)
rlm@145 651 (tick)
rlm@145 652 (tick)
rlm@145 653 (tick)
rlm@145 654 (tick)
rlm@145 655 (tick)
rlm@145 656 (tick)
rlm@145 657 (tick)
rlm@145 658 (tick)
rlm@145 659 (tick)
rlm@145 660 (tick) ;; dpad bits
rlm@145 661
rlm@145 662 (tick)
rlm@145 663 (tick)
rlm@145 664 (tick)
rlm@145 665 (tick)
rlm@145 666 (tick)
rlm@145 667 (tick)
rlm@145 668 (tick)
rlm@145 669 (tick)
rlm@145 670 (d-tick)
rlm@145 671
rlm@145 672
rlm@145 673
rlm@145 674 (view-register "A" A)
rlm@145 675 (view-register "B" B)
rlm@145 676 (view-register "C" C)
rlm@145 677
rlm@145 678 ))
rlm@145 679
rlm@145 680
rlm@145 681
rlm@145 682
rlm@145 683 (defn d2 []
rlm@145 684 (->
rlm@145 685 (write-mem-dyl)
rlm@145 686 (view-memory 0xD31F)
rlm@145 687 step step step step step
rlm@145 688 (view-memory 0xD31F)))
rlm@145 689
rlm@145 690
rlm@145 691
rlm@145 692
rlm@145 693
rlm@145 694
rlm@145 695
rlm@145 696
rlm@145 697
rlm@145 698
rlm@145 699
rlm@145 700
rlm@145 701
rlm@145 702
rlm@145 703
rlm@145 704
rlm@145 705
rlm@145 706
rlm@145 707
rlm@145 708
rlm@145 709 (defn write-memory-assembly []
rlm@145 710 [
rlm@145 711 ;; Main Timing Loop
rlm@145 712 ;; Constantly check for v-blank and Trigger main state machine on
rlm@145 713 ;; every transtion from v-blank to non-v-blank.
rlm@145 714
rlm@145 715 0x18 ; D31D ; Variable declaration
rlm@145 716 0x02 ; D31E
rlm@145 717 0x00 ; D31F ; frame-count
rlm@145 718 0x00 ; D320 ; v-blank-prev
rlm@145 719
rlm@145 720 0xF0 ; D321 ; load v-blank mode flags into A
rlm@145 721 0x41
rlm@145 722 0x00
rlm@145 723
rlm@145 724
rlm@145 725 ;; Branch dependent on v-blank. v-blank happens when the last two
rlm@145 726 ;; bits in A are "01"
rlm@145 727 0xCB ; D324
rlm@145 728 0x4F ; D325
rlm@145 729
rlm@145 730 0xC2 ; D326 ; if bit-1 is not 0, then
rlm@145 731 0x3E ; D327 ; GOTO non-v-blank.
rlm@145 732 0xD3 ; D328
rlm@145 733
rlm@145 734 0xCB ; D329
rlm@145 735 0x47 ; D32A
rlm@145 736
rlm@145 737 0xCA ; D32B ; if bit-0 is not 1, then
rlm@145 738 0x3E ; D32C ; GOTO non-v-blank.
rlm@145 739 0xD3 ; D32D
rlm@145 740
rlm@145 741 ;; V-Blank
rlm@145 742 ;; Activate state-machine if this is a transition event.
rlm@145 743
rlm@145 744 0xFA ; D32E ; load v-bank-prev into A
rlm@145 745 0x20 ; D32F
rlm@145 746 0xD3 ; D330
rlm@145 747
rlm@145 748 0xFE ; D331 ; compare A to 0. >--------\
rlm@145 749 0x00 ; D332 \
rlm@145 750 ; |
rlm@145 751 ;; set v-blank-prev to 1. |
rlm@145 752 0x3E ; D333 ; load 1 into A. |
rlm@145 753 0x01 ; D334 |
rlm@145 754 ; |
rlm@145 755 0xEA ; D335 ; load A into v-blank-prev |
rlm@145 756 0x20 ; D336 |
rlm@145 757 0xD3 ; D337 |
rlm@145 758 ; /
rlm@145 759 ;; if v-blank-prev was 0, activate state-machine <------/
rlm@145 760 0xCA ; D338 ; if v-blank-prev
rlm@145 761 0x46 ; D339 ; was 0,
rlm@145 762 0xD3 ; D33A ; GOTO state-machine
rlm@145 763
rlm@145 764 0xC3 ; D33B
rlm@145 765 0x1D ; D33C
rlm@145 766 0xD3 ; D33D ; GOTO beginning
rlm@145 767 ;; END V-blank
rlm@145 768
rlm@145 769 ;; Non-V-Blank
rlm@145 770 ;; Set v-blank-prev to 0
rlm@145 771 0x3E ; D33E ; load 0 into A
rlm@145 772 0x00 ; D33F
rlm@145 773
rlm@145 774 0xEA ; D340 ; load A into v-blank-prev
rlm@145 775 0x20 ; D341
rlm@145 776 0xD3 ; D342
rlm@145 777
rlm@145 778 0xC3 ; D343
rlm@145 779 0x1D ; D344
rlm@145 780 0xD3 ; D345 ; GOTO beginning
rlm@145 781 ;; END Not-V-Blank
rlm@145 782
rlm@145 783
rlm@145 784 ;; Main State Machine -- Input Section
rlm@145 785 ;; This is called once every frame.
rlm@145 786 ;; It collects input and uses it to drive the
rlm@145 787 ;; state transitions.
rlm@145 788
rlm@145 789 ;; Increment frame-count
rlm@145 790 0xFA ; D346 ; load frame-count into A
rlm@145 791 0x1F ; D347
rlm@145 792 0xD3 ; D348
rlm@145 793
rlm@145 794 0x3C ; D349 ; inc A
rlm@145 795
rlm@145 796 0xEA ; D34A
rlm@145 797 0x1F ; D34B ; load A into frame-count
rlm@145 798 0xD3 ; D34C
rlm@145 799
rlm@145 800 0x00 ; D34D ; glue :)
rlm@145 801
rlm@145 802 0x18 ;D34E ; skip next 3 bytes
rlm@145 803 0x03 ;D34F
rlm@145 804 ;D350
rlm@145 805 (Integer/parseInt "00100000" 2) ; select directional pad
rlm@145 806 ;D351
rlm@145 807 (Integer/parseInt "00010000" 2) ; select buttons
rlm@145 808 0x00 ;D352 ; input-number
rlm@145 809
rlm@145 810 ;; select directional pad; store low bits in B
rlm@145 811
rlm@145 812 0xFA ;D353 ; load (D350) into A
rlm@145 813 0x50 ;D354 -->
rlm@145 814 0xD3 ;D355 --> D350
rlm@145 815
rlm@145 816 0xE0 ;D356 ; load (A), which is
rlm@145 817 0x00 ;D357 --> ; 00010000, into FF00
rlm@145 818 0x00 ;D358 --> FF00 ;; NO-OP
rlm@145 819
rlm@145 820 0x06 ;D359
rlm@145 821 ;D35A
rlm@145 822 (Integer/parseInt "11110000" 2) ; "11110000" -> B
rlm@145 823 0xF0 ;D35B ; (FF00) -> A
rlm@145 824 0x00 ;D35C
rlm@145 825 0x00 ;D35D ;; NO-OP
rlm@145 826
rlm@145 827 0xCB ;D35E ; swap nybbles on A
rlm@145 828 0x37 ;D35F
rlm@145 829 0xA0 ;D360 ; (AND A B) -> A
rlm@145 830 0x47 ;D361 ; A -> B
rlm@145 831
rlm@145 832 ;; select buttons; store bottom bits in C
rlm@145 833
rlm@145 834 0xFA ;D362 ; load (D351) into A
rlm@145 835 0x51 ;D363 -->
rlm@145 836 0xD3 ;D364 --> D351
rlm@145 837
rlm@145 838 0xE0 ;D365 ; load (A), which is
rlm@145 839 0x00 ;D366 --> ; 00001000, into FF00
rlm@145 840 0x00 ;D367 --> FF00 ;; NO-OP
rlm@145 841
rlm@145 842 0x0E ;D368
rlm@145 843 ;D369
rlm@145 844 (Integer/parseInt "00001111" 2) ; "00001111" -> C
rlm@145 845
rlm@145 846 0xF0 ;D36A ; (FF00) -> A
rlm@145 847 0x00 ;D36B
rlm@145 848 0x00 ;D36C
rlm@145 849
rlm@145 850 0xA1 ;D36D ; (AND A C) -> A
rlm@145 851 0x4F ;D36E ; A -> C
rlm@145 852
rlm@145 853 ;; combine the B and C registers into the input number
rlm@145 854 0x79 ;D36F ; C -> A
rlm@145 855 0xB0 ;D370 ; (OR A B) -> A
rlm@145 856 0x2F ;D371 ; negate A
rlm@145 857
rlm@145 858 0xEA ;D372 ; store A into input-number
rlm@145 859 0x52 ;D373
rlm@145 860 0xD3 ;D374
rlm@145 861
rlm@145 862 0x00 ;D375
rlm@145 863 0x00 ;D376
rlm@145 864 0x00 ;D377
rlm@145 865 0x00 ;D378
rlm@145 866 0x00 ;D379
rlm@145 867 0x00 ;D37A
rlm@145 868 0x00 ;D37B ; these are here because
rlm@145 869 0x00 ;D37C ; I messed up :(
rlm@145 870 0x00 ;D37D
rlm@145 871 0x00 ;D37E
rlm@145 872 0x00 ;D37F
rlm@145 873
rlm@145 874 ;; beginning of main state machine
rlm@145 875 0x18 ;D380 ; Declaration of variables
rlm@145 876 0x05 ;D381 ; 5 variables:
rlm@145 877 0x00 ;D382 ; current-mode
rlm@145 878 0x00 ;D383 ; bytes-to-write
rlm@145 879 0x00 ;D384 ; bytes-written
rlm@145 880 0x00 ;D385 ; start-point-high
rlm@145 881 0x00 ;D386 ; start-point-low
rlm@145 882
rlm@145 883
rlm@145 884 ;; banch on current mode
rlm@145 885 0xFA ;D387 ; load current-mode (0xD382)
rlm@145 886 0x82 ;D388 ; into A
rlm@145 887 0xD3 ;D389
rlm@145 888 0x00 ;D38A
rlm@145 889
rlm@145 890
rlm@145 891 ;; GOTO Mode 0 (input-mode) if current-mode is 0
rlm@145 892 0xFE ;D38B
rlm@145 893 0x00 ;D38C ; compare A with 0x00
rlm@145 894
rlm@145 895 0xCA ;D38D ; goto Mode 0 if A == 0
rlm@145 896 0xA8 ;D38E
rlm@145 897 0xD3 ;D38F
rlm@145 898
rlm@145 899 ;; GOTO Mode 1 (set-length) if current-mode is 1
rlm@145 900 0xFE ;D390
rlm@145 901 0x01 ;D391 ; compare A with 0x01
rlm@145 902
rlm@145 903 0xCA ;D392
rlm@145 904 0xB1 ;D393
rlm@145 905 0xD3 ;D394 ; goto Mode 1 if A == 1
rlm@145 906
rlm@145 907 ;; GOTO Mode 2 (set-start-point-high) if current mode is 2
rlm@145 908 0xFE ;D395
rlm@145 909 0x02 ;D396 ; compare A with 0x02
rlm@145 910
rlm@145 911 0xCA ;D397
rlm@145 912 0xBF ;D398
rlm@145 913 0xD3 ;D399 ; goto Mode 2 if A == 2
rlm@145 914
rlm@145 915 ;; GOTO Mode 3 (set-start-point-low) if current mode is 3
rlm@145 916 0xFE ;D39A
rlm@145 917 0x03 ;D39B
rlm@145 918
rlm@145 919 0xCA ;D39C
rlm@145 920 0xCD ;D39D
rlm@145 921 0xD3 ;D39E ; goto Mode 3 if A == 3
rlm@145 922
rlm@145 923 ;; GOTO Mode 4 (write-memory) if current mode is 4
rlm@145 924 0xFE ;D39F
rlm@145 925 0x04 ;D3A0
rlm@145 926
rlm@145 927 0xCA ;D3A1
rlm@145 928 0xDB ;D3A2
rlm@145 929 0xD3 ;D3A3
rlm@145 930
rlm@145 931 0x00 ;D3A4
rlm@145 932 ;; End of Mode checking, goto beginning
rlm@145 933 0xC3 ;D3A5
rlm@145 934 0x1D ;D3A6
rlm@145 935 0xD3 ;D3A7
rlm@145 936
rlm@145 937
rlm@145 938 ;; Mode 0 -- input-mode mode
rlm@145 939 ;; means that we are waiting for a mode, so set the mode to
rlm@145 940 ;; whatever is currently in input-number. If nothing is
rlm@145 941 ;; entered, then the program stays in input-mode mode
rlm@145 942
rlm@145 943 ;; set current-mode to input-number
rlm@145 944 0xFA ;D3A8 ; load input-number (0xD352)
rlm@145 945 0x52 ;D3A9 ; into A
rlm@145 946 0xD3 ;D3AA
rlm@145 947
rlm@145 948 0xEA ;D3AB ; load A into current-mode
rlm@145 949 0x82 ;D3AC ; (0xD382)
rlm@145 950 0xD3 ;D3AD
rlm@145 951
rlm@145 952 0xC3 ;D3AE ; go back to beginning
rlm@145 953 0x1D ;D3AF
rlm@145 954 0xD3 ;D3B0
rlm@145 955 ;; End Mode 0
rlm@145 956
rlm@145 957
rlm@145 958 ;; Mode 1 -- set-length mode
rlm@145 959 ;; This is the header for writing things to memory.
rlm@145 960 ;; User specifies the number of bytes to write.
rlm@145 961 ;; Mode is auto advanced to Mode 2 after this mode
rlm@145 962 ;; completes.
rlm@145 963
rlm@145 964 ;; Set bytes left to write to input-number;
rlm@145 965 ;; set current-mode to 0x02.
rlm@145 966 0xFA ;D3B1 ; load input-number (0xD352)
rlm@145 967 0x52 ;D3B2 ; into A
rlm@145 968 0xD3 ;D3B3
rlm@145 969
rlm@145 970 0xEA ;D3B4 ; load A into bytes-left-to-write
rlm@145 971 0x83 ;D3B5 ; (0xD383)
rlm@145 972 0xD3 ;D3B6
rlm@145 973
rlm@145 974 0x3E ;D3B7 ; load 0x02 into A.
rlm@145 975 0x02 ;D3B8
rlm@145 976
rlm@145 977 0xEA ;D3B9 ; load A to current-mode
rlm@145 978 0x82 ;D3BA ; advancing from Mode 1 to
rlm@145 979 0xD3 ;D3BB ; Mode 2
rlm@145 980
rlm@145 981 0xC3 ;D3BC ; go back to beginning
rlm@145 982 0x1D ;D3BD
rlm@145 983 0xD3 ;D3BE
rlm@145 984 ;; End Mode 1
rlm@145 985
rlm@145 986
rlm@145 987 ;; Mode 2 -- set start-point-high mode
rlm@145 988 ;; Middle part of the header for writing things to memory.
rlm@145 989 ;; User specifies the start location in RAM to which
rlm@145 990 ;; data will be written.
rlm@145 991 ;; Mode is auto advanced to Mode 3 after this mode completes.
rlm@145 992
rlm@145 993 ;; Set start-point-high to input-number;
rlm@145 994 ;; set current mode to 0x03.
rlm@145 995 0xFA ;D3BF ; load input-number (0xD352)
rlm@145 996 0x52 ;D3C0 ; into A
rlm@145 997 0xD3 ;D3C1
rlm@145 998
rlm@145 999 0xEA ;D3C2 ; load A into start-point-high
rlm@145 1000 0x85 ;D3C3 ; (0xD385)
rlm@145 1001 0xD3 ;D3C4
rlm@145 1002
rlm@145 1003 0x3E ;D3C5 ; load 0x03 into A.
rlm@145 1004 0x03 ;D3C6
rlm@145 1005
rlm@145 1006 0xEA ;D3C7 ; load A to current-mode,
rlm@145 1007 0x82 ;D3C8 ; advancing from Mode 2 to
rlm@145 1008 0xD3 ;D3C9 ; Mode 3.
rlm@145 1009
rlm@145 1010 0xC3 ;D3CA ; go back to beginning
rlm@145 1011 0x1D ;D3CB
rlm@145 1012 0xD3 ;D3CC
rlm@145 1013 ;;End Mode 2
rlm@145 1014
rlm@145 1015
rlm@145 1016 ;; Mode 3 -- set-start-point-low mode
rlm@145 1017 ;; Final part of header for writing things to memory.
rlm@145 1018 ;; User specifies the low bytes of 16 bit start-point.
rlm@145 1019
rlm@145 1020 ;; Set start-point-low to input-number;
rlm@145 1021 ;; set current mode to 0x04
rlm@145 1022 0xFA ;D3CD ; load input-number into A
rlm@145 1023 0x52 ;D3CE
rlm@145 1024 0xD3 ;D3CF
rlm@145 1025
rlm@145 1026 0xEA ;D3D0 ; load A into start-point-low
rlm@145 1027 0x86 ;D3D1
rlm@145 1028 0xD3 ;D3D2
rlm@145 1029
rlm@145 1030 0x3E ;D3D3 ; load 0x04 into A.
rlm@145 1031 0x04 ;D3D4
rlm@145 1032
rlm@145 1033 0xEA ;D3D5 ; load A to current-mode,
rlm@145 1034 0x82 ;D3D6 ; advancing from Mode 3 to
rlm@145 1035 0xD3 ;D3D7 ; Mode 4.
rlm@145 1036
rlm@145 1037 0xC3 ;D3D8 ; go back to beginning
rlm@145 1038 0x1D ;D3D9
rlm@145 1039 0xD3 ;D3DA
rlm@145 1040
rlm@145 1041 ;; Mode 4 -- write bytes mode
rlm@145 1042
rlm@145 1043 ;; This is where RAM manipulation happens. User supplies
rlm@145 1044 ;; bytes every frame, which are written sequentially to
rlm@145 1045 ;; start-point until bytes-to-write have been written. Once
rlm@145 1046 ;; bytes-to-write have been written, the mode is reset to 0.
rlm@145 1047
rlm@145 1048 ;; compare bytes-written with bytes-to-write.
rlm@145 1049 ;; if they are the same, then reset mode to 0
rlm@145 1050
rlm@145 1051 0xFA ;D3DB ; load bytes-to-write into A
rlm@145 1052 0x83 ;D3DC
rlm@145 1053 0xD3 ;D3DD
rlm@145 1054
rlm@145 1055 0x47 ;D3DE ; load A into B
rlm@145 1056
rlm@145 1057 0xFA ;D3DF ; load bytes-written into A
rlm@145 1058 0x84 ;D3E0
rlm@145 1059 0xD3 ;D3E1
rlm@145 1060
rlm@145 1061 0xB8 ;D3E2 ; compare A with B
rlm@145 1062
rlm@145 1063 0xCA ;D3E3 ; if they are equal, go to cleanup
rlm@145 1064 0x07 ;D3E4
rlm@145 1065 0xD4 ;D3E5
rlm@145 1066
rlm@145 1067 ;; Write Memory Section
rlm@145 1068 ;; Write the input-number, interpreted as an 8-bit number,
rlm@145 1069 ;; into the current target register, determined by
rlm@145 1070 ;; (+ start-point bytes-written).
rlm@145 1071 ;; Then, increment bytes-written by 1.
rlm@145 1072
rlm@145 1073 0xFA ;D3E6 ; load start-point-high into A
rlm@145 1074 0x85 ;D3E7
rlm@145 1075 0xD3 ;D3E8
rlm@145 1076
rlm@145 1077 0x67 ;D3E9 ; load A into H
rlm@145 1078
rlm@145 1079 0xFA ;D3EA ; load start-point-low into A
rlm@145 1080 0x86 ;D3EB
rlm@145 1081 0xD3 ;D3EC
rlm@145 1082
rlm@145 1083 0x6F ;D3ED ; load A into L
rlm@145 1084
rlm@145 1085 0xFA ;D3EE ; load bytes-written into A
rlm@145 1086 0x84 ;D3EF
rlm@145 1087 0xD3 ;D3F0
rlm@145 1088
rlm@145 1089 0x00 ;D3F1 ; These are here because
rlm@145 1090 0x00 ;D3F2 ; I screwed up again.
rlm@145 1091 0x00 ;D3F3
rlm@145 1092
rlm@145 1093 0x85 ;D3F4 ; add L to A; store A in L.
rlm@145 1094 0x6F ;D3F5
rlm@145 1095
rlm@145 1096 0x30 ;D3F6 ; If the addition overflowed,
rlm@145 1097 0x01 ;D3F7
rlm@145 1098 0x24 ;D3F8 ; increment H.
rlm@145 1099
rlm@145 1100 ;; Now, HL points to the correct place in memory
rlm@145 1101
rlm@145 1102 0xFA ;D3F9 ; load input-number into A
rlm@145 1103 0x52 ;D3FA
rlm@145 1104 0xD3 ;D3FB
rlm@145 1105
rlm@145 1106 0x77 ;D3FC ; load A into (HL)
rlm@145 1107
rlm@145 1108 0xFA ;D3FD ; load bytes-written into A
rlm@145 1109 0x84 ;D3FE
rlm@145 1110 0xD3 ;D3FF
rlm@145 1111
rlm@145 1112 0x3C ;D400 ; increment A
rlm@145 1113
rlm@145 1114 0xEA ;D401 ; load A into bytes-written
rlm@145 1115 0x84 ;D402
rlm@145 1116 0xD3 ;D403
rlm@145 1117
rlm@145 1118 0xC3 ;D404 ; go back to beginning.
rlm@145 1119 0x1D ;D405
rlm@145 1120 0xD3 ;D406
rlm@145 1121 ;; End Write Memory Section
rlm@145 1122
rlm@145 1123 ;; Mode 4 Cleanup Section
rlm@145 1124 ;; reset bytes-written to 0
rlm@145 1125 ;; set mode to 0
rlm@145 1126 0x3E ;D407 ; load 0 into A
rlm@145 1127 0x00 ;D408
rlm@145 1128
rlm@145 1129 0xEA ;D409 ; load A into bytes-written
rlm@145 1130 0x84 ;D40A
rlm@145 1131 0xD3 ;D40B
rlm@145 1132
rlm@145 1133 0xEA ;D40C ; load A into current-mode
rlm@145 1134 0x82 ;D40D
rlm@145 1135 0xD3 ;D40E
rlm@145 1136
rlm@145 1137 0xC3 ;D40F ; go back to beginning
rlm@145 1138 0x1D ;D410
rlm@145 1139 0xD3 ;D411
rlm@145 1140
rlm@145 1141 ;; End Mode 4
rlm@145 1142
rlm@145 1143 ])
rlm@145 1144
rlm@145 1145
rlm@145 1146
rlm@145 1147 (def frame-count 0xD31F)
rlm@145 1148 (def input 0xD352)
rlm@145 1149 (def current-mode 0xD382)
rlm@145 1150 (def bytes-to-write 0xD383)
rlm@145 1151 (def bytes-written 0xD384)
rlm@145 1152 (def start-point-high 0xD385)
rlm@145 1153 (def start-point-low 0xD386)
rlm@145 1154
rlm@145 1155
rlm@145 1156
rlm@145 1157 (defn write-memory []
rlm@145 1158 (-> (tick (mid-game))
rlm@145 1159 (IE! 0) ; disable interrupts
rlm@145 1160 (inject-item-assembly (write-memory-assembly))))
rlm@145 1161
rlm@145 1162 (defn test-write-memory []
rlm@145 1163 (set-state! (write-memory))
rlm@145 1164 (dorun
rlm@145 1165 (dotimes [_ 5000]
rlm@145 1166 (view-memory (step @current-state) current-mode))))
rlm@145 1167
rlm@145 1168 (def bytes-to-write 0xD383)
rlm@145 1169 (def start-point 0xD384)
rlm@145 1170
rlm@145 1171 (defn print-blank-assembly
rlm@145 1172 [start end]
rlm@145 1173 (dorun
rlm@145 1174 (map
rlm@145 1175 #(println (format "0x00 ;%04X " %))
rlm@145 1176 (range start end))))
rlm@145 1177
rlm@145 1178 (defn test-mode-2 []
rlm@145 1179 (->
rlm@145 1180 (write-memory)
rlm@145 1181 (view-memory frame-count)
rlm@145 1182 (step)
rlm@145 1183 (step [:a])
rlm@145 1184 (step [:b])
rlm@145 1185 (step [:start])
rlm@145 1186 (step [])
rlm@145 1187 (view-memory frame-count)))
rlm@145 1188
rlm@145 1189
rlm@145 1190
rlm@145 1191 (defn dylan-test-mode
rlm@145 1192 ([] (dylan-test-mode (write-mem-dyl)))
rlm@145 1193 ([target-state]
rlm@145 1194 (let [
rlm@145 1195 v-blank-prev 54046
rlm@145 1196 btn-register 65280
rlm@145 1197 eggs 0xD374
rlm@145 1198 ]
rlm@145 1199
rlm@145 1200 (->
rlm@145 1201 target-state
rlm@145 1202
rlm@145 1203 (tick)
rlm@145 1204 (tick)
rlm@145 1205 (tick)
rlm@145 1206 (tick);; jumps back to beginning
rlm@145 1207
rlm@145 1208 (tick)
rlm@145 1209 (tick)
rlm@145 1210 (tick)
rlm@145 1211 (tick)
rlm@145 1212 (tick)
rlm@145 1213 (tick)
rlm@145 1214 (tick)
rlm@145 1215 (tick)
rlm@145 1216 (tick)
rlm@145 1217 (tick)
rlm@145 1218 (tick)
rlm@145 1219 (tick)
rlm@145 1220
rlm@145 1221
rlm@145 1222 (tick)
rlm@145 1223 (tick)
rlm@145 1224 (tick)
rlm@145 1225 (tick)
rlm@145 1226 (tick)
rlm@145 1227 (tick)
rlm@145 1228 (tick)
rlm@145 1229 (tick)
rlm@145 1230 (tick)
rlm@145 1231 (tick)
rlm@145 1232 (tick)
rlm@145 1233 (tick)
rlm@145 1234 (tick)
rlm@145 1235 (tick)
rlm@145 1236 (tick)
rlm@145 1237 (tick)
rlm@145 1238 (tick)
rlm@145 1239 (tick)
rlm@145 1240 (tick)
rlm@145 1241 (tick)
rlm@145 1242 (tick) ;; just complemented A
rlm@145 1243
rlm@145 1244 (tick)
rlm@145 1245 (DE! 0x1800)
rlm@145 1246 (AF! 0x7700) ;; change inputs @ A
rlm@145 1247 (tick)
rlm@145 1248 (tick)
rlm@145 1249 (tick)
rlm@145 1250 (tick)
rlm@145 1251 (tick)
rlm@145 1252
rlm@145 1253 ;;(view-memory eggs)
rlm@145 1254 (tick)
rlm@145 1255 (tick)
rlm@145 1256 ;;(view-memory eggs)
rlm@145 1257 (tick)
rlm@145 1258 (tick)
rlm@145 1259 (tick)
rlm@145 1260 (tick)
rlm@145 1261 (tick)
rlm@145 1262 (tick)
rlm@145 1263 (d-tick)
rlm@145 1264
rlm@145 1265
rlm@145 1266 ;;(view-memory btn-register)
rlm@145 1267 (view-register "A" A)
rlm@145 1268 (view-register "B" B)
rlm@145 1269
rlm@145 1270 ;;(view-register "C" C)
rlm@145 1271 (view-register "D" D)
rlm@145 1272 (view-register "E" E)
rlm@145 1273 (view-register "H" H)
rlm@145 1274 (view-register "L" L)
rlm@145 1275 ))))
rlm@145 1276
rlm@145 1277
rlm@145 1278
rlm@145 1279 (defn drive-dylan []
rlm@145 1280 (-> (write-mem-dyl)
rlm@145 1281 (#(do (println "memory from 0xC00F to 0xC01F:"
rlm@145 1282 (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
rlm@145 1283 (step [])
rlm@145 1284 (step [])
rlm@145 1285 (step [])
rlm@145 1286 (step [:start])
rlm@145 1287 (step [:select])
rlm@145 1288 (step [:u :d])
rlm@145 1289 (step [:a :b :start :select])
rlm@145 1290 (step [:a])
rlm@145 1291 (step [:b])
rlm@145 1292 (step [:a :b])
rlm@145 1293 (step [:select])
rlm@145 1294 (step [])
rlm@145 1295 (step [])
rlm@145 1296 (step [])
rlm@145 1297 (#(do (println "memory from 0xC00F to 0xC01F:"
rlm@145 1298 (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
rlm@145 1299 ))
rlm@145 1300
rlm@145 1301 (defn test-mode-4
rlm@145 1302 ([] (test-mode-4 (write-memory)))
rlm@145 1303 ([target-state]
rlm@145 1304 (->
rlm@145 1305 target-state
rlm@145 1306 (#(do (println "memory from 0xC00F to 0xC01F:"
rlm@145 1307 (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
rlm@145 1308 (view-memory current-mode)
rlm@145 1309 (step [])
rlm@145 1310 (step [])
rlm@145 1311 (step [])
rlm@145 1312 (#(do (println "after three steps") %))
rlm@145 1313 (view-memory current-mode)
rlm@145 1314
rlm@145 1315 ;; Activate memory writing mode
rlm@145 1316
rlm@145 1317 (#(do (println "step with [:a]") %))
rlm@145 1318 (step [:a])
rlm@145 1319 (view-memory current-mode)
rlm@145 1320 (view-memory bytes-to-write)
rlm@145 1321 (view-memory start-point-high)
rlm@145 1322 (view-memory start-point-low)
rlm@145 1323
rlm@145 1324 ;; Specify four bytes to be written
rlm@145 1325
rlm@145 1326 (#(do (println "step with [:select]")%))
rlm@145 1327 (step [:select])
rlm@145 1328 (view-memory current-mode)
rlm@145 1329 (view-memory bytes-to-write)
rlm@145 1330 (view-memory start-point-high)
rlm@145 1331 (view-memory start-point-low)
rlm@145 1332
rlm@145 1333 ;; Specify target memory address as 0xC00F
rlm@145 1334
rlm@145 1335 (#(do (println "step with [:u :d]")%))
rlm@145 1336 (step [:u :d])
rlm@145 1337 (view-memory current-mode)
rlm@145 1338 (view-memory bytes-to-write)
rlm@145 1339 (view-memory start-point-high)
rlm@145 1340 (view-memory start-point-low)
rlm@145 1341
rlm@145 1342 (#(do (println "step with [:a :b :start :select]")%))
rlm@145 1343 (step [:a :b :start :select])
rlm@145 1344 (view-memory current-mode)
rlm@145 1345 (view-memory bytes-to-write)
rlm@145 1346 (view-memory start-point-high)
rlm@145 1347 (view-memory start-point-low)
rlm@145 1348
rlm@145 1349 ;; Start reprogramming memory
rlm@145 1350
rlm@145 1351 (#(do (println "step with [:a]")%))
rlm@145 1352 (step [:a])
rlm@145 1353 (view-memory current-mode)
rlm@145 1354 (view-memory bytes-written)
rlm@145 1355
rlm@145 1356 (#(do (println "step with [:b]")%))
rlm@145 1357 (step [:b])
rlm@145 1358 (view-memory current-mode)
rlm@145 1359 (view-memory bytes-written)
rlm@145 1360
rlm@145 1361 (#(do (println "step with [:a :b]")%))
rlm@145 1362 (step [:a :b])
rlm@145 1363 (view-memory current-mode)
rlm@145 1364 (view-memory bytes-written)
rlm@145 1365
rlm@145 1366 (#(do (println "step with [:select]")%))
rlm@145 1367 (step [:select])
rlm@145 1368 (view-memory current-mode)
rlm@145 1369 (view-memory bytes-written)
rlm@145 1370
rlm@145 1371 ;; Reprogramming done, program ready for more commands.
rlm@145 1372
rlm@145 1373 (#(do (println "step with []")%))
rlm@145 1374 (step [])
rlm@145 1375 (view-memory current-mode)
rlm@145 1376 (view-memory bytes-written)
rlm@145 1377
rlm@145 1378 (#(do (println "memory from 0xC00F to 0xC01F:"
rlm@145 1379 (subvec (vec (memory %)) 0xC00F 0xC01F)) %)))))
rlm@145 1380