annotate clojure/com/aurellem/gb/assembly.clj @ 181:4ea8ff49af87

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