annotate clojure/com/aurellem/gb/assembly.clj @ 183:5e34473ac774

merged assembly
author Dylan Holmes <ocsenave@gmail.com>
date Wed, 21 Mar 2012 23:19:01 -0500
parents 95b2758dd517
children d585b91de06c
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
ocsenave@183 409
ocsenave@183 410
ocsenave@183 411
ocsenave@183 412
ocsenave@183 413
rlm@145 414 (defn write-memory-assembly*
ocsenave@175 415 "A program for altering in-game memory by pressing buttons."
rlm@145 416 []
rlm@145 417 [
ocsenave@175 418 0xF3 ; stop interrupts
ocsenave@175 419 ;; --------- CLEANUP
ocsenave@175 420 0xAF ; zero A [D31E]
ocsenave@175 421 0x57 ; A->D; makes D=0.
ocsenave@175 422
rlm@145 423 ;; --------- FRAME METRONOME
ocsenave@175 424 0xF1 ;; pop AF (vblank prev) [D320]
rlm@145 425
ocsenave@175 426 0x2F ;; invert A
ocsenave@183 427 0x4F ;; A -> C
ocsenave@175 428
ocsenave@175 429 0xF0 ;; copy STAT into A
rlm@145 430 0x41
rlm@145 431
ocsenave@183 432 0x47 ;; A->B
ocsenave@183 433 0x1F ;; rotate A right
ocsenave@183 434 0x2F ;; complement A
ocsenave@183 435 0xA0 ;; A & B --> A
ocsenave@183 436
ocsenave@175 437 0xF5 ;; push AF (vbprev)
rlm@145 438
ocsenave@183 439 0xA1 ;; A & C --> A. Now A_0 contains "increment?"
ocsenave@175 440
ocsenave@175 441 0xCB ;; test A_0. this result will be used twice.
ocsenave@175 442 0x47
ocsenave@183 443
ocsenave@175 444 0x28 ;; end frame (JUMP) if A_0 = 0.
ocsenave@183 445 0xF3 ;; TODO: set jump length
rlm@145 446
rlm@145 447 ;; -------- GET BUTTON INPUT
ocsenave@175 448
ocsenave@175 449 ;; btw, Z bit is now 1
rlm@145 450 ;; prepare to select bits
rlm@145 451
rlm@145 452 0x3E ;; load 0x20 into A, to measure dpad
rlm@145 453 0x20
ocsenave@175 454
ocsenave@175 455 0x06 ;; load 0x00 into B
ocsenave@175 456 0x00 ;; to initialize for "OR" loop
rlm@145 457
rlm@145 458 0xE0 ;; load A into [FF00] ;; start of OR loop [D33C]
rlm@145 459 0x00
rlm@145 460
rlm@145 461 0xF0 ;; load A from [FF00]
rlm@145 462 0x00
rlm@145 463
rlm@145 464 0xE6 ;; bitmask 00001111
rlm@145 465 0x0F
rlm@145 466
rlm@145 467 0xB0 ;; A or B --> A
ocsenave@175 468
ocsenave@175 469 0x28 ;; JUMP forward if Z=0
rlm@145 470 0x08
rlm@145 471
rlm@145 472 0x47 ;; A -> B
rlm@145 473 0xCB ;; swap B nybbles
rlm@145 474 0x30
ocsenave@175 475
rlm@145 476 0x3E ;; load 0x10 into A, to measure btns
rlm@145 477 0x10
ocsenave@175 478
ocsenave@175 479 0xBF ;; compare(A,A) sets Z=0
ocsenave@175 480
ocsenave@183 481 0x18 ;; JUMP back to "load A into [FF00]"
ocsenave@183 482 0xEF
rlm@145 483
rlm@145 484
rlm@145 485 ;; ------ TAKE ACTION BASED ON USER INPUT
rlm@145 486
rlm@145 487 ;; "input mode"
rlm@145 488 ;; mode 0x00 : select mode
rlm@145 489 ;; mode 0x08 : select bytes-to-write
rlm@145 490 ;; mode 0x10 : select hi-bit
rlm@145 491 ;; mode 0x18 : select lo-bit
rlm@145 492
rlm@145 493 ;; "output mode"
rlm@145 494 ;; mode 0x20 : write bytes
rlm@145 495 ;; mode 0xFF : jump PC
rlm@145 496
rlm@145 497
rlm@145 498 ;; registers
rlm@145 499 ;; D : mode select
rlm@145 500 ;; E : count of bytes to write
rlm@145 501 ;; H : address-high
rlm@145 502 ;; L : address-low
rlm@145 503
rlm@145 504 ;; now A contains the pressed keys
rlm@145 505 0x2F ; complement A, by request. [D34F]
rlm@145 506
rlm@145 507 0x47 ; A->B ;; now B contains the pressed keys
rlm@145 508
rlm@145 509 0xCB ; test bit 5 of D (are we in o/p mode?)
rlm@145 510 0x6A
rlm@145 511 0x28 ; if test == 0, skip this o/p section
rlm@145 512 0x13 ; JUMP
rlm@145 513
rlm@145 514 0xCB ; else, test bit 0 of D (fragile; are we in pc mode?)
rlm@145 515 0x42
rlm@145 516 0x28 ; if test == 0, skip the following command
rlm@145 517 0x01
rlm@145 518
rlm@145 519 ;; output mode I: moving the program counter
rlm@145 520 0xE9 ; ** move PC to (HL)
rlm@145 521
rlm@145 522 ;; output mode II: writing bytes
ocsenave@175 523 0xAF ; zero A
ocsenave@175 524 0xBB ; compare count to zero. finished writing?
ocsenave@175 525 0x28 ; if we are finished, jump back to cleanup
ocsenave@175 526 0x00 ; TODO: set jump length backwards.
rlm@145 527
rlm@145 528 ;; continue writing bytes
ocsenave@175 529 0x78 ;; B->A
ocsenave@175 530 0x22 ;; copy A to (HL) and increment HL.
rlm@145 531 0x18 ;; end frame. [goto D31F]
ocsenave@175 532 0xB6 ;; JUMP
rlm@145 533
rlm@145 534
rlm@145 535 ;; ---- end of o/p section
rlm@145 536
rlm@145 537 ;; i/p mode
rlm@145 538 ;; adhere to the mode discipline:
rlm@145 539 ;; D must be one of 0x00 0x08 0x10 0x18.
rlm@145 540
rlm@145 541 0x3E ;; load the constant 57 into A. [D369]
rlm@145 542 0x57
rlm@145 543 0x82 ;; add the mode to A
rlm@145 544 0xEA ;; store A into "thing to execute"
rlm@145 545 0x74
rlm@145 546 0xD3
rlm@145 547
rlm@145 548 0x3E ;; load the constant 8 into A
rlm@145 549 0x08
rlm@145 550 0x82 ;; add the mode to A
rlm@145 551
rlm@145 552 0x57 ;; store the incremented mode into D
rlm@145 553 0x78 ;; B->A; now A contains the pressed keys
rlm@145 554
rlm@145 555 0x00 ;; var: thing to execute [D374]
rlm@145 556
rlm@145 557 0x18 ;; end frame
ocsenave@175 558 0xA8 ;; JUMP
rlm@145 559 ]
rlm@145 560 )
rlm@145 561
rlm@145 562 (defn write-mem-dyl []
rlm@145 563 (-> (tick (mid-game))
rlm@145 564 (IE! 0)
rlm@145 565 (inject-item-assembly (write-memory-assembly*))))
rlm@145 566
ocsenave@183 567 (defn ntick [s n]
ocsenave@183 568 (if (zero? n) s
ocsenave@183 569 (do
ocsenave@183 570 (set-state! s)
ocsenave@183 571 (dorun (dotimes [_ n]
ocsenave@183 572 (com.aurellem.gb.Gb/tick)))
ocsenave@183 573 (update-state))))
ocsenave@183 574
ocsenave@183 575
ocsenave@183 576 (defn find-frame-shift [state]
ocsenave@183 577 ;;(restart!)
ocsenave@183 578 (set-state! state)
ocsenave@183 579 (loop [n 0]
ocsenave@183 580 (if (>= (first (registers)) 0xD32D)
ocsenave@183 581 (do (println n)
ocsenave@183 582 (update-state))
ocsenave@183 583 (do
ocsenave@183 584 (com.aurellem.gb.Gb/tick)
ocsenave@183 585 (recur (inc n) )))))
ocsenave@183 586
ocsenave@183 587 (defn demo-assembly [n]
ocsenave@183 588 (repeat n 0x00))
ocsenave@183 589
ocsenave@183 590
ocsenave@183 591 (defn find-frame-shift* [state]
ocsenave@183 592 (set-state! state)
ocsenave@183 593 (loop []
ocsenave@183 594 (com.aurellem.gb.Gb/tick)
ocsenave@183 595 ;;(println (first (registers)))
ocsenave@183 596 (if (>= (first (registers)) 0xD32D)
ocsenave@183 597 (update-state)
ocsenave@183 598 (recur))))
ocsenave@183 599
ocsenave@183 600
ocsenave@183 601 (defn dylan**
ocsenave@183 602 ([k]
ocsenave@183 603 (->
ocsenave@183 604 (tick (mid-game))
ocsenave@183 605 (inject-item-assembly(write-memory-assembly*))
ocsenave@183 606 ;;(find-frame-shift)
ocsenave@183 607 (ntick k)
ocsenave@183 608 (d-tick)
ocsenave@183 609 (view-register "A" A)
ocsenave@183 610 (view-register "B" B)
ocsenave@183 611 (view-register "D" D)
ocsenave@183 612 (view-register "E" E)
ocsenave@183 613 (view-register "F" F)
ocsenave@183 614 (#(do (println) %))
ocsenave@183 615 ))
ocsenave@183 616 ([] (dylan** 0)))
ocsenave@183 617
ocsenave@183 618
ocsenave@183 619
rlm@145 620
rlm@145 621 (defn dylan* []
rlm@145 622 (->
rlm@145 623 (write-mem-dyl)
rlm@145 624
rlm@145 625 (tick)
rlm@145 626 (tick)
rlm@145 627 (tick)
rlm@145 628 (tick)
rlm@145 629 (tick)
rlm@145 630 (tick)
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)
rlm@145 646 (tick)
rlm@145 647 (tick)
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)
rlm@145 661
rlm@145 662 ;;(view-memory 0xD374)
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 (tick)
rlm@145 671 (tick)
rlm@145 672 (tick)
rlm@145 673 (tick)
rlm@145 674 (tick)
rlm@145 675 (tick)
rlm@145 676 (tick)
rlm@145 677 (tick)
rlm@145 678 ;;(view-memory 0xD374)
rlm@145 679 (d-tick)
rlm@145 680
rlm@145 681 (view-register "A" A)
rlm@145 682 (view-register "B" B)
rlm@145 683 (view-register "C" C))
rlm@145 684
rlm@145 685 )
rlm@145 686
rlm@145 687
rlm@145 688 (defn dylan []
rlm@145 689 (->
rlm@145 690 (write-mem-dyl)
rlm@145 691 (tick)
rlm@145 692 (tick)
rlm@145 693 (tick)
rlm@145 694 (tick)
rlm@145 695 (tick)
rlm@145 696 (tick)
rlm@145 697 (tick)
rlm@145 698 (tick)
rlm@145 699 (tick)
rlm@145 700 (tick)
rlm@145 701 (tick)
rlm@145 702 (tick)
rlm@145 703 (tick)
rlm@145 704 (tick)
rlm@145 705 (tick) ;; first loop
rlm@145 706
rlm@145 707
rlm@145 708 (tick)
rlm@145 709 (tick)
rlm@145 710 (tick)
rlm@145 711 (tick)
rlm@145 712 (tick)
rlm@145 713 (tick)
rlm@145 714 (tick)
rlm@145 715 (tick)
rlm@145 716 (tick)
rlm@145 717 (tick)
rlm@145 718 (tick)
rlm@145 719 (tick)
rlm@145 720 (tick) ;; dpad bits
rlm@145 721
rlm@145 722 (tick)
rlm@145 723 (tick)
rlm@145 724 (tick)
rlm@145 725 (tick)
rlm@145 726 (tick)
rlm@145 727 (tick)
rlm@145 728 (tick)
rlm@145 729 (tick)
rlm@145 730 (d-tick)
rlm@145 731
rlm@145 732
rlm@145 733
rlm@145 734 (view-register "A" A)
rlm@145 735 (view-register "B" B)
rlm@145 736 (view-register "C" C)
rlm@145 737
rlm@145 738 ))
rlm@145 739
rlm@145 740
rlm@145 741
rlm@145 742
rlm@145 743 (defn d2 []
rlm@145 744 (->
rlm@145 745 (write-mem-dyl)
rlm@145 746 (view-memory 0xD31F)
rlm@145 747 step step step step step
rlm@145 748 (view-memory 0xD31F)))
rlm@145 749
rlm@145 750
rlm@145 751
rlm@145 752
rlm@145 753
rlm@145 754
rlm@145 755
rlm@145 756
rlm@145 757
rlm@145 758
rlm@145 759
rlm@145 760
rlm@145 761
rlm@145 762
rlm@145 763
rlm@145 764
rlm@145 765
rlm@145 766
rlm@145 767
rlm@145 768
rlm@145 769 (defn write-memory-assembly []
rlm@145 770 [
rlm@145 771 ;; Main Timing Loop
rlm@145 772 ;; Constantly check for v-blank and Trigger main state machine on
rlm@145 773 ;; every transtion from v-blank to non-v-blank.
rlm@145 774
rlm@145 775 0x18 ; D31D ; Variable declaration
rlm@145 776 0x02 ; D31E
rlm@145 777 0x00 ; D31F ; frame-count
rlm@145 778 0x00 ; D320 ; v-blank-prev
rlm@145 779
rlm@145 780 0xF0 ; D321 ; load v-blank mode flags into A
rlm@145 781 0x41
rlm@145 782 0x00
rlm@145 783
rlm@145 784
rlm@145 785 ;; Branch dependent on v-blank. v-blank happens when the last two
rlm@145 786 ;; bits in A are "01"
rlm@145 787 0xCB ; D324
rlm@145 788 0x4F ; D325
rlm@145 789
rlm@145 790 0xC2 ; D326 ; if bit-1 is not 0, then
rlm@145 791 0x3E ; D327 ; GOTO non-v-blank.
rlm@145 792 0xD3 ; D328
rlm@145 793
rlm@145 794 0xCB ; D329
rlm@145 795 0x47 ; D32A
rlm@145 796
rlm@145 797 0xCA ; D32B ; if bit-0 is not 1, then
rlm@145 798 0x3E ; D32C ; GOTO non-v-blank.
rlm@145 799 0xD3 ; D32D
rlm@145 800
rlm@145 801 ;; V-Blank
rlm@145 802 ;; Activate state-machine if this is a transition event.
rlm@145 803
rlm@145 804 0xFA ; D32E ; load v-bank-prev into A
rlm@145 805 0x20 ; D32F
rlm@145 806 0xD3 ; D330
rlm@145 807
rlm@145 808 0xFE ; D331 ; compare A to 0. >--------\
rlm@145 809 0x00 ; D332 \
rlm@145 810 ; |
rlm@145 811 ;; set v-blank-prev to 1. |
rlm@145 812 0x3E ; D333 ; load 1 into A. |
rlm@145 813 0x01 ; D334 |
rlm@145 814 ; |
rlm@145 815 0xEA ; D335 ; load A into v-blank-prev |
rlm@145 816 0x20 ; D336 |
rlm@145 817 0xD3 ; D337 |
rlm@145 818 ; /
rlm@145 819 ;; if v-blank-prev was 0, activate state-machine <------/
rlm@145 820 0xCA ; D338 ; if v-blank-prev
rlm@145 821 0x46 ; D339 ; was 0,
rlm@145 822 0xD3 ; D33A ; GOTO state-machine
rlm@145 823
rlm@145 824 0xC3 ; D33B
rlm@145 825 0x1D ; D33C
rlm@145 826 0xD3 ; D33D ; GOTO beginning
rlm@145 827 ;; END V-blank
rlm@145 828
rlm@145 829 ;; Non-V-Blank
rlm@145 830 ;; Set v-blank-prev to 0
rlm@145 831 0x3E ; D33E ; load 0 into A
rlm@145 832 0x00 ; D33F
rlm@145 833
rlm@145 834 0xEA ; D340 ; load A into v-blank-prev
rlm@145 835 0x20 ; D341
rlm@145 836 0xD3 ; D342
rlm@145 837
rlm@145 838 0xC3 ; D343
rlm@145 839 0x1D ; D344
rlm@145 840 0xD3 ; D345 ; GOTO beginning
rlm@145 841 ;; END Not-V-Blank
rlm@145 842
rlm@145 843
rlm@145 844 ;; Main State Machine -- Input Section
rlm@145 845 ;; This is called once every frame.
rlm@145 846 ;; It collects input and uses it to drive the
rlm@145 847 ;; state transitions.
rlm@145 848
rlm@145 849 ;; Increment frame-count
rlm@145 850 0xFA ; D346 ; load frame-count into A
rlm@145 851 0x1F ; D347
rlm@145 852 0xD3 ; D348
rlm@145 853
rlm@145 854 0x3C ; D349 ; inc A
rlm@145 855
rlm@145 856 0xEA ; D34A
rlm@145 857 0x1F ; D34B ; load A into frame-count
rlm@145 858 0xD3 ; D34C
rlm@145 859
rlm@145 860 0x00 ; D34D ; glue :)
rlm@145 861
rlm@145 862 0x18 ;D34E ; skip next 3 bytes
rlm@145 863 0x03 ;D34F
rlm@145 864 ;D350
rlm@145 865 (Integer/parseInt "00100000" 2) ; select directional pad
rlm@145 866 ;D351
rlm@145 867 (Integer/parseInt "00010000" 2) ; select buttons
rlm@145 868 0x00 ;D352 ; input-number
rlm@145 869
rlm@145 870 ;; select directional pad; store low bits in B
rlm@145 871
rlm@145 872 0xFA ;D353 ; load (D350) into A
rlm@145 873 0x50 ;D354 -->
rlm@145 874 0xD3 ;D355 --> D350
rlm@145 875
rlm@145 876 0xE0 ;D356 ; load (A), which is
rlm@145 877 0x00 ;D357 --> ; 00010000, into FF00
rlm@145 878 0x00 ;D358 --> FF00 ;; NO-OP
rlm@145 879
rlm@145 880 0x06 ;D359
rlm@145 881 ;D35A
rlm@145 882 (Integer/parseInt "11110000" 2) ; "11110000" -> B
rlm@145 883 0xF0 ;D35B ; (FF00) -> A
rlm@145 884 0x00 ;D35C
rlm@145 885 0x00 ;D35D ;; NO-OP
rlm@145 886
rlm@145 887 0xCB ;D35E ; swap nybbles on A
rlm@145 888 0x37 ;D35F
rlm@145 889 0xA0 ;D360 ; (AND A B) -> A
rlm@145 890 0x47 ;D361 ; A -> B
rlm@145 891
rlm@145 892 ;; select buttons; store bottom bits in C
rlm@145 893
rlm@145 894 0xFA ;D362 ; load (D351) into A
rlm@145 895 0x51 ;D363 -->
rlm@145 896 0xD3 ;D364 --> D351
rlm@145 897
rlm@145 898 0xE0 ;D365 ; load (A), which is
rlm@145 899 0x00 ;D366 --> ; 00001000, into FF00
rlm@145 900 0x00 ;D367 --> FF00 ;; NO-OP
rlm@145 901
rlm@145 902 0x0E ;D368
rlm@145 903 ;D369
rlm@145 904 (Integer/parseInt "00001111" 2) ; "00001111" -> C
rlm@145 905
rlm@145 906 0xF0 ;D36A ; (FF00) -> A
rlm@145 907 0x00 ;D36B
rlm@145 908 0x00 ;D36C
rlm@145 909
rlm@145 910 0xA1 ;D36D ; (AND A C) -> A
rlm@145 911 0x4F ;D36E ; A -> C
rlm@145 912
rlm@145 913 ;; combine the B and C registers into the input number
rlm@145 914 0x79 ;D36F ; C -> A
rlm@145 915 0xB0 ;D370 ; (OR A B) -> A
rlm@145 916 0x2F ;D371 ; negate A
rlm@145 917
rlm@145 918 0xEA ;D372 ; store A into input-number
rlm@145 919 0x52 ;D373
rlm@145 920 0xD3 ;D374
rlm@145 921
rlm@145 922 0x00 ;D375
rlm@145 923 0x00 ;D376
rlm@145 924 0x00 ;D377
rlm@145 925 0x00 ;D378
rlm@145 926 0x00 ;D379
rlm@145 927 0x00 ;D37A
rlm@145 928 0x00 ;D37B ; these are here because
rlm@145 929 0x00 ;D37C ; I messed up :(
rlm@145 930 0x00 ;D37D
rlm@145 931 0x00 ;D37E
rlm@145 932 0x00 ;D37F
rlm@145 933
rlm@145 934 ;; beginning of main state machine
rlm@145 935 0x18 ;D380 ; Declaration of variables
rlm@145 936 0x05 ;D381 ; 5 variables:
rlm@145 937 0x00 ;D382 ; current-mode
rlm@145 938 0x00 ;D383 ; bytes-to-write
rlm@145 939 0x00 ;D384 ; bytes-written
rlm@145 940 0x00 ;D385 ; start-point-high
rlm@145 941 0x00 ;D386 ; start-point-low
rlm@145 942
rlm@145 943
rlm@145 944 ;; banch on current mode
rlm@145 945 0xFA ;D387 ; load current-mode (0xD382)
rlm@145 946 0x82 ;D388 ; into A
rlm@145 947 0xD3 ;D389
rlm@145 948 0x00 ;D38A
rlm@145 949
rlm@145 950
rlm@145 951 ;; GOTO Mode 0 (input-mode) if current-mode is 0
rlm@145 952 0xFE ;D38B
rlm@145 953 0x00 ;D38C ; compare A with 0x00
rlm@145 954
rlm@145 955 0xCA ;D38D ; goto Mode 0 if A == 0
rlm@145 956 0xA8 ;D38E
rlm@145 957 0xD3 ;D38F
rlm@145 958
rlm@145 959 ;; GOTO Mode 1 (set-length) if current-mode is 1
rlm@145 960 0xFE ;D390
rlm@145 961 0x01 ;D391 ; compare A with 0x01
rlm@145 962
rlm@145 963 0xCA ;D392
rlm@145 964 0xB1 ;D393
rlm@145 965 0xD3 ;D394 ; goto Mode 1 if A == 1
rlm@145 966
rlm@145 967 ;; GOTO Mode 2 (set-start-point-high) if current mode is 2
rlm@145 968 0xFE ;D395
rlm@145 969 0x02 ;D396 ; compare A with 0x02
rlm@145 970
rlm@145 971 0xCA ;D397
rlm@145 972 0xBF ;D398
rlm@145 973 0xD3 ;D399 ; goto Mode 2 if A == 2
rlm@145 974
rlm@145 975 ;; GOTO Mode 3 (set-start-point-low) if current mode is 3
rlm@145 976 0xFE ;D39A
rlm@145 977 0x03 ;D39B
rlm@145 978
rlm@145 979 0xCA ;D39C
rlm@145 980 0xCD ;D39D
rlm@145 981 0xD3 ;D39E ; goto Mode 3 if A == 3
rlm@145 982
rlm@145 983 ;; GOTO Mode 4 (write-memory) if current mode is 4
rlm@145 984 0xFE ;D39F
rlm@145 985 0x04 ;D3A0
rlm@145 986
rlm@145 987 0xCA ;D3A1
rlm@145 988 0xDB ;D3A2
rlm@145 989 0xD3 ;D3A3
rlm@145 990
rlm@145 991 0x00 ;D3A4
rlm@145 992 ;; End of Mode checking, goto beginning
rlm@145 993 0xC3 ;D3A5
rlm@145 994 0x1D ;D3A6
rlm@145 995 0xD3 ;D3A7
rlm@145 996
rlm@145 997
rlm@145 998 ;; Mode 0 -- input-mode mode
rlm@145 999 ;; means that we are waiting for a mode, so set the mode to
rlm@145 1000 ;; whatever is currently in input-number. If nothing is
rlm@145 1001 ;; entered, then the program stays in input-mode mode
rlm@145 1002
rlm@145 1003 ;; set current-mode to input-number
rlm@145 1004 0xFA ;D3A8 ; load input-number (0xD352)
rlm@145 1005 0x52 ;D3A9 ; into A
rlm@145 1006 0xD3 ;D3AA
rlm@145 1007
rlm@145 1008 0xEA ;D3AB ; load A into current-mode
rlm@145 1009 0x82 ;D3AC ; (0xD382)
rlm@145 1010 0xD3 ;D3AD
rlm@145 1011
rlm@145 1012 0xC3 ;D3AE ; go back to beginning
rlm@145 1013 0x1D ;D3AF
rlm@145 1014 0xD3 ;D3B0
rlm@145 1015 ;; End Mode 0
rlm@145 1016
rlm@145 1017
rlm@145 1018 ;; Mode 1 -- set-length mode
rlm@145 1019 ;; This is the header for writing things to memory.
rlm@145 1020 ;; User specifies the number of bytes to write.
rlm@145 1021 ;; Mode is auto advanced to Mode 2 after this mode
rlm@145 1022 ;; completes.
rlm@145 1023
rlm@145 1024 ;; Set bytes left to write to input-number;
rlm@145 1025 ;; set current-mode to 0x02.
rlm@145 1026 0xFA ;D3B1 ; load input-number (0xD352)
rlm@145 1027 0x52 ;D3B2 ; into A
rlm@145 1028 0xD3 ;D3B3
rlm@145 1029
rlm@145 1030 0xEA ;D3B4 ; load A into bytes-left-to-write
rlm@145 1031 0x83 ;D3B5 ; (0xD383)
rlm@145 1032 0xD3 ;D3B6
rlm@145 1033
rlm@145 1034 0x3E ;D3B7 ; load 0x02 into A.
rlm@145 1035 0x02 ;D3B8
rlm@145 1036
rlm@145 1037 0xEA ;D3B9 ; load A to current-mode
rlm@145 1038 0x82 ;D3BA ; advancing from Mode 1 to
rlm@145 1039 0xD3 ;D3BB ; Mode 2
rlm@145 1040
rlm@145 1041 0xC3 ;D3BC ; go back to beginning
rlm@145 1042 0x1D ;D3BD
rlm@145 1043 0xD3 ;D3BE
rlm@145 1044 ;; End Mode 1
rlm@145 1045
rlm@145 1046
rlm@145 1047 ;; Mode 2 -- set start-point-high mode
rlm@145 1048 ;; Middle part of the header for writing things to memory.
rlm@145 1049 ;; User specifies the start location in RAM to which
rlm@145 1050 ;; data will be written.
rlm@145 1051 ;; Mode is auto advanced to Mode 3 after this mode completes.
rlm@145 1052
rlm@145 1053 ;; Set start-point-high to input-number;
rlm@145 1054 ;; set current mode to 0x03.
rlm@145 1055 0xFA ;D3BF ; load input-number (0xD352)
rlm@145 1056 0x52 ;D3C0 ; into A
rlm@145 1057 0xD3 ;D3C1
rlm@145 1058
rlm@145 1059 0xEA ;D3C2 ; load A into start-point-high
rlm@145 1060 0x85 ;D3C3 ; (0xD385)
rlm@145 1061 0xD3 ;D3C4
rlm@145 1062
rlm@145 1063 0x3E ;D3C5 ; load 0x03 into A.
rlm@145 1064 0x03 ;D3C6
rlm@145 1065
rlm@145 1066 0xEA ;D3C7 ; load A to current-mode,
rlm@145 1067 0x82 ;D3C8 ; advancing from Mode 2 to
rlm@145 1068 0xD3 ;D3C9 ; Mode 3.
rlm@145 1069
rlm@145 1070 0xC3 ;D3CA ; go back to beginning
rlm@145 1071 0x1D ;D3CB
rlm@145 1072 0xD3 ;D3CC
rlm@145 1073 ;;End Mode 2
rlm@145 1074
rlm@145 1075
rlm@145 1076 ;; Mode 3 -- set-start-point-low mode
rlm@145 1077 ;; Final part of header for writing things to memory.
rlm@145 1078 ;; User specifies the low bytes of 16 bit start-point.
rlm@145 1079
rlm@145 1080 ;; Set start-point-low to input-number;
rlm@145 1081 ;; set current mode to 0x04
rlm@145 1082 0xFA ;D3CD ; load input-number into A
rlm@145 1083 0x52 ;D3CE
rlm@145 1084 0xD3 ;D3CF
rlm@145 1085
rlm@145 1086 0xEA ;D3D0 ; load A into start-point-low
rlm@145 1087 0x86 ;D3D1
rlm@145 1088 0xD3 ;D3D2
rlm@145 1089
rlm@145 1090 0x3E ;D3D3 ; load 0x04 into A.
rlm@145 1091 0x04 ;D3D4
rlm@145 1092
rlm@145 1093 0xEA ;D3D5 ; load A to current-mode,
rlm@145 1094 0x82 ;D3D6 ; advancing from Mode 3 to
rlm@145 1095 0xD3 ;D3D7 ; Mode 4.
rlm@145 1096
rlm@145 1097 0xC3 ;D3D8 ; go back to beginning
rlm@145 1098 0x1D ;D3D9
rlm@145 1099 0xD3 ;D3DA
rlm@145 1100
rlm@145 1101 ;; Mode 4 -- write bytes mode
rlm@145 1102
rlm@145 1103 ;; This is where RAM manipulation happens. User supplies
rlm@145 1104 ;; bytes every frame, which are written sequentially to
rlm@145 1105 ;; start-point until bytes-to-write have been written. Once
rlm@145 1106 ;; bytes-to-write have been written, the mode is reset to 0.
rlm@145 1107
rlm@145 1108 ;; compare bytes-written with bytes-to-write.
rlm@145 1109 ;; if they are the same, then reset mode to 0
rlm@145 1110
rlm@145 1111 0xFA ;D3DB ; load bytes-to-write into A
rlm@145 1112 0x83 ;D3DC
rlm@145 1113 0xD3 ;D3DD
rlm@145 1114
rlm@145 1115 0x47 ;D3DE ; load A into B
rlm@145 1116
rlm@145 1117 0xFA ;D3DF ; load bytes-written into A
rlm@145 1118 0x84 ;D3E0
rlm@145 1119 0xD3 ;D3E1
rlm@145 1120
rlm@145 1121 0xB8 ;D3E2 ; compare A with B
rlm@145 1122
rlm@145 1123 0xCA ;D3E3 ; if they are equal, go to cleanup
rlm@145 1124 0x07 ;D3E4
rlm@145 1125 0xD4 ;D3E5
rlm@145 1126
rlm@145 1127 ;; Write Memory Section
rlm@145 1128 ;; Write the input-number, interpreted as an 8-bit number,
rlm@145 1129 ;; into the current target register, determined by
rlm@145 1130 ;; (+ start-point bytes-written).
rlm@145 1131 ;; Then, increment bytes-written by 1.
rlm@145 1132
rlm@145 1133 0xFA ;D3E6 ; load start-point-high into A
rlm@145 1134 0x85 ;D3E7
rlm@145 1135 0xD3 ;D3E8
rlm@145 1136
rlm@145 1137 0x67 ;D3E9 ; load A into H
rlm@145 1138
rlm@145 1139 0xFA ;D3EA ; load start-point-low into A
rlm@145 1140 0x86 ;D3EB
rlm@145 1141 0xD3 ;D3EC
rlm@145 1142
rlm@145 1143 0x6F ;D3ED ; load A into L
rlm@145 1144
rlm@145 1145 0xFA ;D3EE ; load bytes-written into A
rlm@145 1146 0x84 ;D3EF
rlm@145 1147 0xD3 ;D3F0
rlm@145 1148
rlm@145 1149 0x00 ;D3F1 ; These are here because
rlm@145 1150 0x00 ;D3F2 ; I screwed up again.
rlm@145 1151 0x00 ;D3F3
rlm@145 1152
rlm@145 1153 0x85 ;D3F4 ; add L to A; store A in L.
rlm@145 1154 0x6F ;D3F5
rlm@145 1155
rlm@145 1156 0x30 ;D3F6 ; If the addition overflowed,
rlm@145 1157 0x01 ;D3F7
rlm@145 1158 0x24 ;D3F8 ; increment H.
rlm@145 1159
rlm@145 1160 ;; Now, HL points to the correct place in memory
rlm@145 1161
rlm@145 1162 0xFA ;D3F9 ; load input-number into A
rlm@145 1163 0x52 ;D3FA
rlm@145 1164 0xD3 ;D3FB
rlm@145 1165
rlm@145 1166 0x77 ;D3FC ; load A into (HL)
rlm@145 1167
rlm@145 1168 0xFA ;D3FD ; load bytes-written into A
rlm@145 1169 0x84 ;D3FE
rlm@145 1170 0xD3 ;D3FF
rlm@145 1171
rlm@145 1172 0x3C ;D400 ; increment A
rlm@145 1173
rlm@145 1174 0xEA ;D401 ; load A into bytes-written
rlm@145 1175 0x84 ;D402
rlm@145 1176 0xD3 ;D403
rlm@145 1177
rlm@145 1178 0xC3 ;D404 ; go back to beginning.
rlm@145 1179 0x1D ;D405
rlm@145 1180 0xD3 ;D406
rlm@145 1181 ;; End Write Memory Section
rlm@145 1182
rlm@145 1183 ;; Mode 4 Cleanup Section
rlm@145 1184 ;; reset bytes-written to 0
rlm@145 1185 ;; set mode to 0
rlm@145 1186 0x3E ;D407 ; load 0 into A
rlm@145 1187 0x00 ;D408
rlm@145 1188
rlm@145 1189 0xEA ;D409 ; load A into bytes-written
rlm@145 1190 0x84 ;D40A
rlm@145 1191 0xD3 ;D40B
rlm@145 1192
rlm@145 1193 0xEA ;D40C ; load A into current-mode
rlm@145 1194 0x82 ;D40D
rlm@145 1195 0xD3 ;D40E
rlm@145 1196
rlm@145 1197 0xC3 ;D40F ; go back to beginning
rlm@145 1198 0x1D ;D410
rlm@145 1199 0xD3 ;D411
rlm@145 1200
rlm@145 1201 ;; End Mode 4
rlm@145 1202
rlm@145 1203 ])
rlm@145 1204
rlm@145 1205
rlm@145 1206
rlm@145 1207 (def frame-count 0xD31F)
rlm@145 1208 (def input 0xD352)
rlm@145 1209 (def current-mode 0xD382)
rlm@145 1210 (def bytes-to-write 0xD383)
rlm@145 1211 (def bytes-written 0xD384)
rlm@145 1212 (def start-point-high 0xD385)
rlm@145 1213 (def start-point-low 0xD386)
rlm@145 1214
rlm@145 1215
rlm@145 1216
rlm@145 1217 (defn write-memory []
rlm@145 1218 (-> (tick (mid-game))
rlm@145 1219 (IE! 0) ; disable interrupts
rlm@145 1220 (inject-item-assembly (write-memory-assembly))))
rlm@145 1221
rlm@145 1222 (defn test-write-memory []
rlm@145 1223 (set-state! (write-memory))
rlm@145 1224 (dorun
rlm@145 1225 (dotimes [_ 5000]
rlm@145 1226 (view-memory (step @current-state) current-mode))))
rlm@145 1227
rlm@145 1228 (def bytes-to-write 0xD383)
rlm@145 1229 (def start-point 0xD384)
rlm@145 1230
rlm@145 1231 (defn print-blank-assembly
rlm@145 1232 [start end]
rlm@145 1233 (dorun
rlm@145 1234 (map
rlm@145 1235 #(println (format "0x00 ;%04X " %))
rlm@145 1236 (range start end))))
rlm@145 1237
rlm@145 1238 (defn test-mode-2 []
rlm@145 1239 (->
rlm@145 1240 (write-memory)
rlm@145 1241 (view-memory frame-count)
rlm@145 1242 (step)
rlm@145 1243 (step [:a])
rlm@145 1244 (step [:b])
rlm@145 1245 (step [:start])
rlm@145 1246 (step [])
rlm@145 1247 (view-memory frame-count)))
rlm@145 1248
rlm@145 1249
rlm@145 1250
rlm@145 1251 (defn dylan-test-mode
rlm@145 1252 ([] (dylan-test-mode (write-mem-dyl)))
rlm@145 1253 ([target-state]
rlm@145 1254 (let [
rlm@145 1255 v-blank-prev 54046
rlm@145 1256 btn-register 65280
rlm@145 1257 eggs 0xD374
rlm@145 1258 ]
rlm@145 1259
rlm@145 1260 (->
rlm@145 1261 target-state
rlm@145 1262
rlm@145 1263 (tick)
rlm@145 1264 (tick)
rlm@145 1265 (tick)
rlm@145 1266 (tick);; jumps back to beginning
rlm@145 1267
rlm@145 1268 (tick)
rlm@145 1269 (tick)
rlm@145 1270 (tick)
rlm@145 1271 (tick)
rlm@145 1272 (tick)
rlm@145 1273 (tick)
rlm@145 1274 (tick)
rlm@145 1275 (tick)
rlm@145 1276 (tick)
rlm@145 1277 (tick)
rlm@145 1278 (tick)
rlm@145 1279 (tick)
rlm@145 1280
rlm@145 1281
rlm@145 1282 (tick)
rlm@145 1283 (tick)
rlm@145 1284 (tick)
rlm@145 1285 (tick)
rlm@145 1286 (tick)
rlm@145 1287 (tick)
rlm@145 1288 (tick)
rlm@145 1289 (tick)
rlm@145 1290 (tick)
rlm@145 1291 (tick)
rlm@145 1292 (tick)
rlm@145 1293 (tick)
rlm@145 1294 (tick)
rlm@145 1295 (tick)
rlm@145 1296 (tick)
rlm@145 1297 (tick)
rlm@145 1298 (tick)
rlm@145 1299 (tick)
rlm@145 1300 (tick)
rlm@145 1301 (tick)
rlm@145 1302 (tick) ;; just complemented A
rlm@145 1303
rlm@145 1304 (tick)
rlm@145 1305 (DE! 0x1800)
rlm@145 1306 (AF! 0x7700) ;; change inputs @ A
rlm@145 1307 (tick)
rlm@145 1308 (tick)
rlm@145 1309 (tick)
rlm@145 1310 (tick)
rlm@145 1311 (tick)
rlm@145 1312
rlm@145 1313 ;;(view-memory eggs)
rlm@145 1314 (tick)
rlm@145 1315 (tick)
rlm@145 1316 ;;(view-memory eggs)
rlm@145 1317 (tick)
rlm@145 1318 (tick)
rlm@145 1319 (tick)
rlm@145 1320 (tick)
rlm@145 1321 (tick)
rlm@145 1322 (tick)
rlm@145 1323 (d-tick)
rlm@145 1324
rlm@145 1325
rlm@145 1326 ;;(view-memory btn-register)
rlm@145 1327 (view-register "A" A)
rlm@145 1328 (view-register "B" B)
rlm@145 1329
rlm@145 1330 ;;(view-register "C" C)
rlm@145 1331 (view-register "D" D)
rlm@145 1332 (view-register "E" E)
rlm@145 1333 (view-register "H" H)
rlm@145 1334 (view-register "L" L)
rlm@145 1335 ))))
rlm@145 1336
rlm@145 1337
rlm@145 1338
rlm@145 1339 (defn drive-dylan []
rlm@145 1340 (-> (write-mem-dyl)
rlm@145 1341 (#(do (println "memory from 0xC00F to 0xC01F:"
rlm@145 1342 (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
rlm@145 1343 (step [])
rlm@145 1344 (step [])
rlm@145 1345 (step [])
rlm@145 1346 (step [:start])
rlm@145 1347 (step [:select])
rlm@145 1348 (step [:u :d])
rlm@145 1349 (step [:a :b :start :select])
rlm@145 1350 (step [:a])
rlm@145 1351 (step [:b])
rlm@145 1352 (step [:a :b])
rlm@145 1353 (step [:select])
rlm@145 1354 (step [])
rlm@145 1355 (step [])
rlm@145 1356 (step [])
rlm@145 1357 (#(do (println "memory from 0xC00F to 0xC01F:"
rlm@145 1358 (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
rlm@145 1359 ))
rlm@145 1360
rlm@145 1361 (defn test-mode-4
rlm@145 1362 ([] (test-mode-4 (write-memory)))
rlm@145 1363 ([target-state]
rlm@145 1364 (->
rlm@145 1365 target-state
rlm@145 1366 (#(do (println "memory from 0xC00F to 0xC01F:"
rlm@145 1367 (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
rlm@145 1368 (view-memory current-mode)
rlm@145 1369 (step [])
rlm@145 1370 (step [])
rlm@145 1371 (step [])
rlm@145 1372 (#(do (println "after three steps") %))
rlm@145 1373 (view-memory current-mode)
rlm@145 1374
rlm@145 1375 ;; Activate memory writing mode
rlm@145 1376
rlm@145 1377 (#(do (println "step with [:a]") %))
rlm@145 1378 (step [:a])
rlm@145 1379 (view-memory current-mode)
rlm@145 1380 (view-memory bytes-to-write)
rlm@145 1381 (view-memory start-point-high)
rlm@145 1382 (view-memory start-point-low)
rlm@145 1383
rlm@145 1384 ;; Specify four bytes to be written
rlm@145 1385
rlm@145 1386 (#(do (println "step with [:select]")%))
rlm@145 1387 (step [:select])
rlm@145 1388 (view-memory current-mode)
rlm@145 1389 (view-memory bytes-to-write)
rlm@145 1390 (view-memory start-point-high)
rlm@145 1391 (view-memory start-point-low)
rlm@145 1392
rlm@145 1393 ;; Specify target memory address as 0xC00F
rlm@145 1394
rlm@145 1395 (#(do (println "step with [:u :d]")%))
rlm@145 1396 (step [:u :d])
rlm@145 1397 (view-memory current-mode)
rlm@145 1398 (view-memory bytes-to-write)
rlm@145 1399 (view-memory start-point-high)
rlm@145 1400 (view-memory start-point-low)
rlm@145 1401
rlm@145 1402 (#(do (println "step with [:a :b :start :select]")%))
rlm@145 1403 (step [:a :b :start :select])
rlm@145 1404 (view-memory current-mode)
rlm@145 1405 (view-memory bytes-to-write)
rlm@145 1406 (view-memory start-point-high)
rlm@145 1407 (view-memory start-point-low)
rlm@145 1408
rlm@145 1409 ;; Start reprogramming memory
rlm@145 1410
rlm@145 1411 (#(do (println "step with [:a]")%))
rlm@145 1412 (step [:a])
rlm@145 1413 (view-memory current-mode)
rlm@145 1414 (view-memory bytes-written)
rlm@145 1415
rlm@145 1416 (#(do (println "step with [:b]")%))
rlm@145 1417 (step [:b])
rlm@145 1418 (view-memory current-mode)
rlm@145 1419 (view-memory bytes-written)
rlm@145 1420
rlm@145 1421 (#(do (println "step with [:a :b]")%))
rlm@145 1422 (step [:a :b])
rlm@145 1423 (view-memory current-mode)
rlm@145 1424 (view-memory bytes-written)
rlm@145 1425
rlm@145 1426 (#(do (println "step with [:select]")%))
rlm@145 1427 (step [:select])
rlm@145 1428 (view-memory current-mode)
rlm@145 1429 (view-memory bytes-written)
rlm@145 1430
rlm@145 1431 ;; Reprogramming done, program ready for more commands.
rlm@145 1432
rlm@145 1433 (#(do (println "step with []")%))
rlm@145 1434 (step [])
rlm@145 1435 (view-memory current-mode)
rlm@145 1436 (view-memory bytes-written)
rlm@145 1437
rlm@145 1438 (#(do (println "memory from 0xC00F to 0xC01F:"
rlm@145 1439 (subvec (vec (memory %)) 0xC00F 0xC01F)) %)))))
rlm@145 1440