annotate clojure/com/aurellem/gb/assembly.clj @ 293:4a0dbaed7078

preliminary idea for a better pre-bootstrapping program.
author Robert McIntyre <rlm@mit.edu>
date Fri, 30 Mar 2012 18:14:14 -0500
parents 2e751984b42d
children
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@242 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@242 440
ocsenave@242 441 0x4F
ocsenave@242 442 0xCB ;; test bit 0 of C. sadly, this result can't be reused below.
ocsenave@242 443 0x41
ocsenave@183 444
ocsenave@175 445 0x28 ;; end frame (JUMP) if A_0 = 0.
ocsenave@183 446 0xF3 ;; TODO: set jump length
rlm@145 447
rlm@145 448 ;; -------- GET BUTTON INPUT
ocsenave@175 449
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@242 469 0xCB ;; check bit 0 of C
ocsenave@242 470 0x41
ocsenave@242 471
ocsenave@175 472 0x28 ;; JUMP forward if Z=0
rlm@145 473 0x08
rlm@145 474
rlm@145 475 0x47 ;; A -> B
rlm@145 476 0xCB ;; swap B nybbles
rlm@145 477 0x30
ocsenave@175 478
rlm@145 479 0x3E ;; load 0x10 into A, to measure btns
rlm@145 480 0x10
ocsenave@175 481
ocsenave@183 482 0x18 ;; JUMP back to "load A into [FF00]"
ocsenave@242 483 0xF0
rlm@145 484
rlm@145 485
rlm@145 486 ;; ------ TAKE ACTION BASED ON USER INPUT
rlm@145 487
rlm@145 488 ;; "input mode"
rlm@145 489 ;; mode 0x00 : select mode
rlm@145 490 ;; mode 0x08 : select bytes-to-write
rlm@145 491 ;; mode 0x10 : select hi-bit
rlm@145 492 ;; mode 0x18 : select lo-bit
rlm@145 493
rlm@145 494 ;; "output mode"
rlm@145 495 ;; mode 0x20 : write bytes
rlm@145 496 ;; mode 0xFF : jump PC
rlm@145 497
rlm@145 498
rlm@145 499 ;; registers
rlm@145 500 ;; D : mode select
rlm@145 501 ;; E : count of bytes to write
rlm@145 502 ;; H : address-high
rlm@145 503 ;; L : address-low
rlm@145 504
rlm@145 505 ;; now A contains the pressed keys
rlm@145 506 0x2F ; complement A, by request. [D34F]
rlm@145 507
rlm@145 508 0x47 ; A->B ;; now B contains the pressed keys
rlm@145 509
rlm@145 510 0xCB ; test bit 5 of D (are we in o/p mode?)
rlm@145 511 0x6A
rlm@145 512 0x28 ; if test == 0, skip this o/p section
rlm@145 513 0x13 ; JUMP
rlm@145 514
rlm@145 515 0xCB ; else, test bit 0 of D (fragile; are we in pc mode?)
rlm@145 516 0x42
rlm@145 517 0x28 ; if test == 0, skip the following command
rlm@145 518 0x01
rlm@145 519
rlm@145 520 ;; output mode I: moving the program counter
rlm@145 521 0xE9 ; ** move PC to (HL)
rlm@145 522
rlm@145 523 ;; output mode II: writing bytes
ocsenave@175 524 0xAF ; zero A
ocsenave@175 525 0xBB ; compare count to zero. finished writing?
ocsenave@175 526 0x28 ; if we are finished, jump back to cleanup
ocsenave@175 527 0x00 ; TODO: set jump length backwards.
rlm@145 528
rlm@145 529 ;; continue writing bytes
ocsenave@175 530 0x78 ;; B->A
ocsenave@175 531 0x22 ;; copy A to (HL) and increment HL.
rlm@145 532 0x18 ;; end frame. [goto D31F]
ocsenave@175 533 0xB6 ;; JUMP
rlm@145 534
rlm@145 535
rlm@145 536 ;; ---- end of o/p section
rlm@145 537
rlm@145 538 ;; i/p mode
rlm@145 539 ;; adhere to the mode discipline:
rlm@145 540 ;; D must be one of 0x00 0x08 0x10 0x18.
rlm@145 541
rlm@145 542 0x3E ;; load the constant 57 into A. [D369]
rlm@145 543 0x57
rlm@145 544 0x82 ;; add the mode to A
rlm@145 545 0xEA ;; store A into "thing to execute"
ocsenave@242 546 0x74 ;; ABSOLUTE LOCATION
ocsenave@242 547 0xD3 ;; ABSOLUTE LOCATION
rlm@145 548
rlm@145 549 0x3E ;; load the constant 8 into A
rlm@145 550 0x08
rlm@145 551 0x82 ;; add the mode to A
rlm@145 552
rlm@145 553 0x57 ;; store the incremented mode into D
rlm@145 554 0x78 ;; B->A; now A contains the pressed keys
rlm@145 555
rlm@145 556 0x00 ;; var: thing to execute [D374]
rlm@145 557
rlm@145 558 0x18 ;; end frame
ocsenave@175 559 0xA8 ;; JUMP
rlm@145 560 ]
rlm@145 561 )
rlm@145 562
rlm@145 563 (defn write-mem-dyl []
rlm@145 564 (-> (tick (mid-game))
rlm@145 565 (IE! 0)
rlm@145 566 (inject-item-assembly (write-memory-assembly*))))
rlm@145 567
ocsenave@183 568 (defn ntick [s n]
ocsenave@183 569 (if (zero? n) s
ocsenave@183 570 (do
ocsenave@183 571 (set-state! s)
ocsenave@183 572 (dorun (dotimes [_ n]
ocsenave@183 573 (com.aurellem.gb.Gb/tick)))
ocsenave@183 574 (update-state))))
ocsenave@183 575
ocsenave@183 576
ocsenave@183 577 (defn find-frame-shift [state]
ocsenave@183 578 ;;(restart!)
ocsenave@183 579 (set-state! state)
ocsenave@183 580 (loop [n 0]
ocsenave@183 581 (if (>= (first (registers)) 0xD32D)
ocsenave@183 582 (do (println n)
ocsenave@183 583 (update-state))
ocsenave@183 584 (do
ocsenave@183 585 (com.aurellem.gb.Gb/tick)
ocsenave@183 586 (recur (inc n) )))))
ocsenave@183 587
ocsenave@183 588 (defn demo-assembly [n]
ocsenave@183 589 (repeat n 0x00))
ocsenave@183 590
ocsenave@183 591
ocsenave@183 592 (defn find-frame-shift* [state]
ocsenave@183 593 (set-state! state)
ocsenave@183 594 (loop []
ocsenave@183 595 (com.aurellem.gb.Gb/tick)
ocsenave@183 596 ;;(println (first (registers)))
ocsenave@183 597 (if (>= (first (registers)) 0xD32D)
ocsenave@183 598 (update-state)
ocsenave@183 599 (recur))))
ocsenave@183 600
ocsenave@183 601
ocsenave@183 602 (defn dylan**
ocsenave@183 603 ([k]
ocsenave@183 604 (->
ocsenave@183 605 (tick (mid-game))
ocsenave@183 606 (inject-item-assembly(write-memory-assembly*))
ocsenave@183 607 ;;(find-frame-shift)
ocsenave@183 608 (ntick k)
ocsenave@183 609 (d-tick)
ocsenave@183 610 (view-register "A" A)
ocsenave@183 611 (view-register "B" B)
ocsenave@183 612 (view-register "D" D)
ocsenave@183 613 (view-register "E" E)
ocsenave@183 614 (view-register "F" F)
ocsenave@183 615 (#(do (println) %))
ocsenave@183 616 ))
ocsenave@183 617 ([] (dylan** 0)))
ocsenave@183 618
ocsenave@183 619
ocsenave@183 620
rlm@145 621
rlm@145 622 (defn dylan* []
rlm@145 623 (->
rlm@145 624 (write-mem-dyl)
rlm@145 625
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 (tick)
rlm@145 662
rlm@145 663 ;;(view-memory 0xD374)
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 (tick)
rlm@145 679 ;;(view-memory 0xD374)
rlm@145 680 (d-tick)
rlm@145 681
rlm@145 682 (view-register "A" A)
rlm@145 683 (view-register "B" B)
rlm@145 684 (view-register "C" C))
rlm@145 685
rlm@145 686 )
rlm@145 687
rlm@145 688
rlm@145 689 (defn dylan []
rlm@145 690 (->
rlm@145 691 (write-mem-dyl)
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)
rlm@145 706 (tick) ;; first loop
rlm@145 707
rlm@145 708
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)
rlm@145 721 (tick) ;; dpad bits
rlm@145 722
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 (tick)
rlm@145 731 (d-tick)
rlm@145 732
rlm@145 733
rlm@145 734
rlm@145 735 (view-register "A" A)
rlm@145 736 (view-register "B" B)
rlm@145 737 (view-register "C" C)
rlm@145 738
rlm@145 739 ))
rlm@145 740
rlm@145 741
rlm@145 742
rlm@145 743
rlm@145 744 (defn d2 []
rlm@145 745 (->
rlm@145 746 (write-mem-dyl)
rlm@145 747 (view-memory 0xD31F)
rlm@145 748 step step step step step
rlm@145 749 (view-memory 0xD31F)))
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
rlm@145 770 (defn write-memory-assembly []
rlm@145 771 [
rlm@145 772 ;; Main Timing Loop
rlm@145 773 ;; Constantly check for v-blank and Trigger main state machine on
rlm@145 774 ;; every transtion from v-blank to non-v-blank.
rlm@145 775
rlm@145 776 0x18 ; D31D ; Variable declaration
rlm@145 777 0x02 ; D31E
rlm@145 778 0x00 ; D31F ; frame-count
rlm@145 779 0x00 ; D320 ; v-blank-prev
rlm@145 780
rlm@145 781 0xF0 ; D321 ; load v-blank mode flags into A
rlm@145 782 0x41
rlm@145 783 0x00
rlm@145 784
rlm@145 785
rlm@145 786 ;; Branch dependent on v-blank. v-blank happens when the last two
rlm@145 787 ;; bits in A are "01"
rlm@145 788 0xCB ; D324
rlm@145 789 0x4F ; D325
rlm@145 790
rlm@145 791 0xC2 ; D326 ; if bit-1 is not 0, then
rlm@145 792 0x3E ; D327 ; GOTO non-v-blank.
rlm@145 793 0xD3 ; D328
rlm@145 794
rlm@145 795 0xCB ; D329
rlm@145 796 0x47 ; D32A
rlm@145 797
rlm@145 798 0xCA ; D32B ; if bit-0 is not 1, then
rlm@145 799 0x3E ; D32C ; GOTO non-v-blank.
rlm@145 800 0xD3 ; D32D
rlm@145 801
rlm@145 802 ;; V-Blank
rlm@145 803 ;; Activate state-machine if this is a transition event.
rlm@145 804
rlm@145 805 0xFA ; D32E ; load v-bank-prev into A
rlm@145 806 0x20 ; D32F
rlm@145 807 0xD3 ; D330
rlm@145 808
rlm@145 809 0xFE ; D331 ; compare A to 0. >--------\
rlm@145 810 0x00 ; D332 \
rlm@145 811 ; |
rlm@145 812 ;; set v-blank-prev to 1. |
rlm@145 813 0x3E ; D333 ; load 1 into A. |
rlm@145 814 0x01 ; D334 |
rlm@145 815 ; |
rlm@145 816 0xEA ; D335 ; load A into v-blank-prev |
rlm@145 817 0x20 ; D336 |
rlm@145 818 0xD3 ; D337 |
rlm@145 819 ; /
rlm@145 820 ;; if v-blank-prev was 0, activate state-machine <------/
rlm@145 821 0xCA ; D338 ; if v-blank-prev
rlm@145 822 0x46 ; D339 ; was 0,
rlm@145 823 0xD3 ; D33A ; GOTO state-machine
rlm@145 824
rlm@145 825 0xC3 ; D33B
rlm@145 826 0x1D ; D33C
rlm@145 827 0xD3 ; D33D ; GOTO beginning
rlm@145 828 ;; END V-blank
rlm@145 829
rlm@145 830 ;; Non-V-Blank
rlm@145 831 ;; Set v-blank-prev to 0
rlm@145 832 0x3E ; D33E ; load 0 into A
rlm@145 833 0x00 ; D33F
rlm@145 834
rlm@145 835 0xEA ; D340 ; load A into v-blank-prev
rlm@145 836 0x20 ; D341
rlm@145 837 0xD3 ; D342
rlm@145 838
rlm@145 839 0xC3 ; D343
rlm@145 840 0x1D ; D344
rlm@145 841 0xD3 ; D345 ; GOTO beginning
rlm@145 842 ;; END Not-V-Blank
rlm@145 843
rlm@145 844
rlm@145 845 ;; Main State Machine -- Input Section
rlm@145 846 ;; This is called once every frame.
rlm@145 847 ;; It collects input and uses it to drive the
rlm@145 848 ;; state transitions.
rlm@145 849
rlm@145 850 ;; Increment frame-count
rlm@145 851 0xFA ; D346 ; load frame-count into A
rlm@145 852 0x1F ; D347
rlm@145 853 0xD3 ; D348
rlm@145 854
rlm@145 855 0x3C ; D349 ; inc A
rlm@145 856
rlm@145 857 0xEA ; D34A
rlm@145 858 0x1F ; D34B ; load A into frame-count
rlm@145 859 0xD3 ; D34C
rlm@145 860
rlm@145 861 0x00 ; D34D ; glue :)
rlm@145 862
rlm@145 863 0x18 ;D34E ; skip next 3 bytes
rlm@145 864 0x03 ;D34F
rlm@145 865 ;D350
rlm@145 866 (Integer/parseInt "00100000" 2) ; select directional pad
rlm@145 867 ;D351
rlm@145 868 (Integer/parseInt "00010000" 2) ; select buttons
rlm@145 869 0x00 ;D352 ; input-number
rlm@145 870
rlm@145 871 ;; select directional pad; store low bits in B
rlm@145 872
rlm@145 873 0xFA ;D353 ; load (D350) into A
rlm@145 874 0x50 ;D354 -->
rlm@145 875 0xD3 ;D355 --> D350
rlm@145 876
rlm@145 877 0xE0 ;D356 ; load (A), which is
rlm@145 878 0x00 ;D357 --> ; 00010000, into FF00
rlm@145 879 0x00 ;D358 --> FF00 ;; NO-OP
rlm@145 880
rlm@145 881 0x06 ;D359
rlm@145 882 ;D35A
rlm@145 883 (Integer/parseInt "11110000" 2) ; "11110000" -> B
rlm@145 884 0xF0 ;D35B ; (FF00) -> A
rlm@145 885 0x00 ;D35C
rlm@145 886 0x00 ;D35D ;; NO-OP
rlm@145 887
rlm@145 888 0xCB ;D35E ; swap nybbles on A
rlm@145 889 0x37 ;D35F
rlm@145 890 0xA0 ;D360 ; (AND A B) -> A
rlm@145 891 0x47 ;D361 ; A -> B
rlm@145 892
rlm@145 893 ;; select buttons; store bottom bits in C
rlm@145 894
rlm@145 895 0xFA ;D362 ; load (D351) into A
rlm@145 896 0x51 ;D363 -->
rlm@145 897 0xD3 ;D364 --> D351
rlm@145 898
rlm@145 899 0xE0 ;D365 ; load (A), which is
rlm@145 900 0x00 ;D366 --> ; 00001000, into FF00
rlm@145 901 0x00 ;D367 --> FF00 ;; NO-OP
rlm@145 902
rlm@145 903 0x0E ;D368
rlm@145 904 ;D369
rlm@145 905 (Integer/parseInt "00001111" 2) ; "00001111" -> C
rlm@145 906
rlm@145 907 0xF0 ;D36A ; (FF00) -> A
rlm@145 908 0x00 ;D36B
rlm@145 909 0x00 ;D36C
rlm@145 910
rlm@145 911 0xA1 ;D36D ; (AND A C) -> A
rlm@145 912 0x4F ;D36E ; A -> C
rlm@145 913
rlm@145 914 ;; combine the B and C registers into the input number
rlm@145 915 0x79 ;D36F ; C -> A
rlm@145 916 0xB0 ;D370 ; (OR A B) -> A
rlm@145 917 0x2F ;D371 ; negate A
rlm@145 918
rlm@145 919 0xEA ;D372 ; store A into input-number
rlm@145 920 0x52 ;D373
rlm@145 921 0xD3 ;D374
rlm@145 922
rlm@145 923 0x00 ;D375
rlm@145 924 0x00 ;D376
rlm@145 925 0x00 ;D377
rlm@145 926 0x00 ;D378
rlm@145 927 0x00 ;D379
rlm@145 928 0x00 ;D37A
rlm@145 929 0x00 ;D37B ; these are here because
rlm@145 930 0x00 ;D37C ; I messed up :(
rlm@145 931 0x00 ;D37D
rlm@145 932 0x00 ;D37E
rlm@145 933 0x00 ;D37F
rlm@145 934
rlm@145 935 ;; beginning of main state machine
rlm@145 936 0x18 ;D380 ; Declaration of variables
rlm@145 937 0x05 ;D381 ; 5 variables:
rlm@145 938 0x00 ;D382 ; current-mode
rlm@145 939 0x00 ;D383 ; bytes-to-write
rlm@145 940 0x00 ;D384 ; bytes-written
rlm@145 941 0x00 ;D385 ; start-point-high
rlm@145 942 0x00 ;D386 ; start-point-low
rlm@145 943
rlm@145 944
rlm@145 945 ;; banch on current mode
rlm@145 946 0xFA ;D387 ; load current-mode (0xD382)
rlm@145 947 0x82 ;D388 ; into A
rlm@145 948 0xD3 ;D389
rlm@145 949 0x00 ;D38A
rlm@145 950
rlm@145 951
rlm@145 952 ;; GOTO Mode 0 (input-mode) if current-mode is 0
rlm@145 953 0xFE ;D38B
rlm@145 954 0x00 ;D38C ; compare A with 0x00
rlm@145 955
rlm@145 956 0xCA ;D38D ; goto Mode 0 if A == 0
rlm@145 957 0xA8 ;D38E
rlm@145 958 0xD3 ;D38F
rlm@145 959
rlm@145 960 ;; GOTO Mode 1 (set-length) if current-mode is 1
rlm@145 961 0xFE ;D390
rlm@145 962 0x01 ;D391 ; compare A with 0x01
rlm@145 963
rlm@145 964 0xCA ;D392
rlm@145 965 0xB1 ;D393
rlm@145 966 0xD3 ;D394 ; goto Mode 1 if A == 1
rlm@145 967
rlm@145 968 ;; GOTO Mode 2 (set-start-point-high) if current mode is 2
rlm@145 969 0xFE ;D395
rlm@145 970 0x02 ;D396 ; compare A with 0x02
rlm@145 971
rlm@145 972 0xCA ;D397
rlm@145 973 0xBF ;D398
rlm@145 974 0xD3 ;D399 ; goto Mode 2 if A == 2
rlm@145 975
rlm@145 976 ;; GOTO Mode 3 (set-start-point-low) if current mode is 3
rlm@145 977 0xFE ;D39A
rlm@145 978 0x03 ;D39B
rlm@145 979
rlm@145 980 0xCA ;D39C
rlm@145 981 0xCD ;D39D
rlm@145 982 0xD3 ;D39E ; goto Mode 3 if A == 3
rlm@145 983
rlm@145 984 ;; GOTO Mode 4 (write-memory) if current mode is 4
rlm@145 985 0xFE ;D39F
rlm@145 986 0x04 ;D3A0
rlm@145 987
rlm@145 988 0xCA ;D3A1
rlm@145 989 0xDB ;D3A2
rlm@145 990 0xD3 ;D3A3
rlm@145 991
rlm@145 992 0x00 ;D3A4
rlm@145 993 ;; End of Mode checking, goto beginning
rlm@145 994 0xC3 ;D3A5
rlm@145 995 0x1D ;D3A6
rlm@145 996 0xD3 ;D3A7
rlm@145 997
rlm@145 998
rlm@145 999 ;; Mode 0 -- input-mode mode
rlm@145 1000 ;; means that we are waiting for a mode, so set the mode to
rlm@145 1001 ;; whatever is currently in input-number. If nothing is
rlm@145 1002 ;; entered, then the program stays in input-mode mode
rlm@145 1003
rlm@145 1004 ;; set current-mode to input-number
rlm@145 1005 0xFA ;D3A8 ; load input-number (0xD352)
rlm@145 1006 0x52 ;D3A9 ; into A
rlm@145 1007 0xD3 ;D3AA
rlm@145 1008
rlm@145 1009 0xEA ;D3AB ; load A into current-mode
rlm@145 1010 0x82 ;D3AC ; (0xD382)
rlm@145 1011 0xD3 ;D3AD
rlm@145 1012
rlm@145 1013 0xC3 ;D3AE ; go back to beginning
rlm@145 1014 0x1D ;D3AF
rlm@145 1015 0xD3 ;D3B0
rlm@145 1016 ;; End Mode 0
rlm@145 1017
rlm@145 1018
rlm@145 1019 ;; Mode 1 -- set-length mode
rlm@145 1020 ;; This is the header for writing things to memory.
rlm@145 1021 ;; User specifies the number of bytes to write.
rlm@145 1022 ;; Mode is auto advanced to Mode 2 after this mode
rlm@145 1023 ;; completes.
rlm@145 1024
rlm@145 1025 ;; Set bytes left to write to input-number;
rlm@145 1026 ;; set current-mode to 0x02.
rlm@145 1027 0xFA ;D3B1 ; load input-number (0xD352)
rlm@145 1028 0x52 ;D3B2 ; into A
rlm@145 1029 0xD3 ;D3B3
rlm@145 1030
rlm@145 1031 0xEA ;D3B4 ; load A into bytes-left-to-write
rlm@145 1032 0x83 ;D3B5 ; (0xD383)
rlm@145 1033 0xD3 ;D3B6
rlm@145 1034
rlm@145 1035 0x3E ;D3B7 ; load 0x02 into A.
rlm@145 1036 0x02 ;D3B8
rlm@145 1037
rlm@145 1038 0xEA ;D3B9 ; load A to current-mode
rlm@145 1039 0x82 ;D3BA ; advancing from Mode 1 to
rlm@145 1040 0xD3 ;D3BB ; Mode 2
rlm@145 1041
rlm@145 1042 0xC3 ;D3BC ; go back to beginning
rlm@145 1043 0x1D ;D3BD
rlm@145 1044 0xD3 ;D3BE
rlm@145 1045 ;; End Mode 1
rlm@145 1046
rlm@145 1047
rlm@145 1048 ;; Mode 2 -- set start-point-high mode
rlm@145 1049 ;; Middle part of the header for writing things to memory.
rlm@145 1050 ;; User specifies the start location in RAM to which
rlm@145 1051 ;; data will be written.
rlm@145 1052 ;; Mode is auto advanced to Mode 3 after this mode completes.
rlm@145 1053
rlm@145 1054 ;; Set start-point-high to input-number;
rlm@145 1055 ;; set current mode to 0x03.
rlm@145 1056 0xFA ;D3BF ; load input-number (0xD352)
rlm@145 1057 0x52 ;D3C0 ; into A
rlm@145 1058 0xD3 ;D3C1
rlm@145 1059
rlm@145 1060 0xEA ;D3C2 ; load A into start-point-high
rlm@145 1061 0x85 ;D3C3 ; (0xD385)
rlm@145 1062 0xD3 ;D3C4
rlm@145 1063
rlm@145 1064 0x3E ;D3C5 ; load 0x03 into A.
rlm@145 1065 0x03 ;D3C6
rlm@145 1066
rlm@145 1067 0xEA ;D3C7 ; load A to current-mode,
rlm@145 1068 0x82 ;D3C8 ; advancing from Mode 2 to
rlm@145 1069 0xD3 ;D3C9 ; Mode 3.
rlm@145 1070
rlm@145 1071 0xC3 ;D3CA ; go back to beginning
rlm@145 1072 0x1D ;D3CB
rlm@145 1073 0xD3 ;D3CC
rlm@145 1074 ;;End Mode 2
rlm@145 1075
rlm@145 1076
rlm@145 1077 ;; Mode 3 -- set-start-point-low mode
rlm@145 1078 ;; Final part of header for writing things to memory.
rlm@145 1079 ;; User specifies the low bytes of 16 bit start-point.
rlm@145 1080
rlm@145 1081 ;; Set start-point-low to input-number;
rlm@145 1082 ;; set current mode to 0x04
rlm@145 1083 0xFA ;D3CD ; load input-number into A
rlm@145 1084 0x52 ;D3CE
rlm@145 1085 0xD3 ;D3CF
rlm@145 1086
rlm@145 1087 0xEA ;D3D0 ; load A into start-point-low
rlm@145 1088 0x86 ;D3D1
rlm@145 1089 0xD3 ;D3D2
rlm@145 1090
rlm@145 1091 0x3E ;D3D3 ; load 0x04 into A.
rlm@145 1092 0x04 ;D3D4
rlm@145 1093
rlm@145 1094 0xEA ;D3D5 ; load A to current-mode,
rlm@145 1095 0x82 ;D3D6 ; advancing from Mode 3 to
rlm@145 1096 0xD3 ;D3D7 ; Mode 4.
rlm@145 1097
rlm@145 1098 0xC3 ;D3D8 ; go back to beginning
rlm@145 1099 0x1D ;D3D9
rlm@145 1100 0xD3 ;D3DA
rlm@145 1101
rlm@145 1102 ;; Mode 4 -- write bytes mode
rlm@145 1103
rlm@145 1104 ;; This is where RAM manipulation happens. User supplies
rlm@145 1105 ;; bytes every frame, which are written sequentially to
rlm@145 1106 ;; start-point until bytes-to-write have been written. Once
rlm@145 1107 ;; bytes-to-write have been written, the mode is reset to 0.
rlm@145 1108
rlm@145 1109 ;; compare bytes-written with bytes-to-write.
rlm@145 1110 ;; if they are the same, then reset mode to 0
rlm@145 1111
rlm@145 1112 0xFA ;D3DB ; load bytes-to-write into A
rlm@145 1113 0x83 ;D3DC
rlm@145 1114 0xD3 ;D3DD
rlm@145 1115
rlm@145 1116 0x47 ;D3DE ; load A into B
rlm@145 1117
rlm@145 1118 0xFA ;D3DF ; load bytes-written into A
rlm@145 1119 0x84 ;D3E0
rlm@145 1120 0xD3 ;D3E1
rlm@145 1121
rlm@145 1122 0xB8 ;D3E2 ; compare A with B
rlm@145 1123
rlm@145 1124 0xCA ;D3E3 ; if they are equal, go to cleanup
rlm@145 1125 0x07 ;D3E4
rlm@145 1126 0xD4 ;D3E5
rlm@145 1127
rlm@145 1128 ;; Write Memory Section
rlm@145 1129 ;; Write the input-number, interpreted as an 8-bit number,
rlm@145 1130 ;; into the current target register, determined by
rlm@145 1131 ;; (+ start-point bytes-written).
rlm@145 1132 ;; Then, increment bytes-written by 1.
rlm@145 1133
rlm@145 1134 0xFA ;D3E6 ; load start-point-high into A
rlm@145 1135 0x85 ;D3E7
rlm@145 1136 0xD3 ;D3E8
rlm@145 1137
rlm@145 1138 0x67 ;D3E9 ; load A into H
rlm@145 1139
rlm@145 1140 0xFA ;D3EA ; load start-point-low into A
rlm@145 1141 0x86 ;D3EB
rlm@145 1142 0xD3 ;D3EC
rlm@145 1143
rlm@145 1144 0x6F ;D3ED ; load A into L
rlm@145 1145
rlm@145 1146 0xFA ;D3EE ; load bytes-written into A
rlm@145 1147 0x84 ;D3EF
rlm@145 1148 0xD3 ;D3F0
rlm@145 1149
rlm@145 1150 0x00 ;D3F1 ; These are here because
rlm@145 1151 0x00 ;D3F2 ; I screwed up again.
rlm@145 1152 0x00 ;D3F3
rlm@145 1153
rlm@145 1154 0x85 ;D3F4 ; add L to A; store A in L.
rlm@145 1155 0x6F ;D3F5
rlm@145 1156
rlm@145 1157 0x30 ;D3F6 ; If the addition overflowed,
rlm@145 1158 0x01 ;D3F7
rlm@145 1159 0x24 ;D3F8 ; increment H.
rlm@145 1160
rlm@145 1161 ;; Now, HL points to the correct place in memory
rlm@145 1162
rlm@145 1163 0xFA ;D3F9 ; load input-number into A
rlm@145 1164 0x52 ;D3FA
rlm@145 1165 0xD3 ;D3FB
rlm@145 1166
rlm@145 1167 0x77 ;D3FC ; load A into (HL)
rlm@145 1168
rlm@145 1169 0xFA ;D3FD ; load bytes-written into A
rlm@145 1170 0x84 ;D3FE
rlm@145 1171 0xD3 ;D3FF
rlm@145 1172
rlm@145 1173 0x3C ;D400 ; increment A
rlm@145 1174
rlm@145 1175 0xEA ;D401 ; load A into bytes-written
rlm@145 1176 0x84 ;D402
rlm@145 1177 0xD3 ;D403
rlm@145 1178
rlm@145 1179 0xC3 ;D404 ; go back to beginning.
rlm@145 1180 0x1D ;D405
rlm@145 1181 0xD3 ;D406
rlm@145 1182 ;; End Write Memory Section
rlm@145 1183
rlm@145 1184 ;; Mode 4 Cleanup Section
rlm@145 1185 ;; reset bytes-written to 0
rlm@145 1186 ;; set mode to 0
rlm@145 1187 0x3E ;D407 ; load 0 into A
rlm@145 1188 0x00 ;D408
rlm@145 1189
rlm@145 1190 0xEA ;D409 ; load A into bytes-written
rlm@145 1191 0x84 ;D40A
rlm@145 1192 0xD3 ;D40B
rlm@145 1193
rlm@145 1194 0xEA ;D40C ; load A into current-mode
rlm@145 1195 0x82 ;D40D
rlm@145 1196 0xD3 ;D40E
rlm@145 1197
rlm@145 1198 0xC3 ;D40F ; go back to beginning
rlm@145 1199 0x1D ;D410
rlm@145 1200 0xD3 ;D411
rlm@145 1201
rlm@145 1202 ;; End Mode 4
rlm@145 1203
rlm@145 1204 ])
rlm@145 1205
rlm@145 1206
rlm@145 1207
rlm@145 1208 (def frame-count 0xD31F)
rlm@145 1209 (def input 0xD352)
rlm@145 1210 (def current-mode 0xD382)
rlm@145 1211 (def bytes-to-write 0xD383)
rlm@145 1212 (def bytes-written 0xD384)
rlm@145 1213 (def start-point-high 0xD385)
rlm@145 1214 (def start-point-low 0xD386)
rlm@145 1215
rlm@145 1216
rlm@145 1217
rlm@145 1218 (defn write-memory []
rlm@145 1219 (-> (tick (mid-game))
rlm@145 1220 (IE! 0) ; disable interrupts
rlm@145 1221 (inject-item-assembly (write-memory-assembly))))
rlm@145 1222
rlm@145 1223 (defn test-write-memory []
rlm@145 1224 (set-state! (write-memory))
rlm@145 1225 (dorun
rlm@145 1226 (dotimes [_ 5000]
rlm@145 1227 (view-memory (step @current-state) current-mode))))
rlm@145 1228
rlm@145 1229 (def bytes-to-write 0xD383)
rlm@145 1230 (def start-point 0xD384)
rlm@145 1231
rlm@145 1232 (defn print-blank-assembly
rlm@145 1233 [start end]
rlm@145 1234 (dorun
rlm@145 1235 (map
rlm@145 1236 #(println (format "0x00 ;%04X " %))
rlm@145 1237 (range start end))))
rlm@145 1238
rlm@145 1239 (defn test-mode-2 []
rlm@145 1240 (->
rlm@145 1241 (write-memory)
rlm@145 1242 (view-memory frame-count)
rlm@145 1243 (step)
rlm@145 1244 (step [:a])
rlm@145 1245 (step [:b])
rlm@145 1246 (step [:start])
rlm@145 1247 (step [])
rlm@145 1248 (view-memory frame-count)))
rlm@145 1249
rlm@145 1250
rlm@145 1251
rlm@145 1252 (defn dylan-test-mode
rlm@145 1253 ([] (dylan-test-mode (write-mem-dyl)))
rlm@145 1254 ([target-state]
rlm@145 1255 (let [
rlm@145 1256 v-blank-prev 54046
rlm@145 1257 btn-register 65280
rlm@145 1258 eggs 0xD374
rlm@145 1259 ]
rlm@145 1260
rlm@145 1261 (->
rlm@145 1262 target-state
rlm@145 1263
rlm@145 1264 (tick)
rlm@145 1265 (tick)
rlm@145 1266 (tick)
rlm@145 1267 (tick);; jumps back to beginning
rlm@145 1268
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 (tick)
rlm@145 1281
rlm@145 1282
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)
rlm@145 1303 (tick) ;; just complemented A
rlm@145 1304
rlm@145 1305 (tick)
rlm@145 1306 (DE! 0x1800)
rlm@145 1307 (AF! 0x7700) ;; change inputs @ A
rlm@145 1308 (tick)
rlm@145 1309 (tick)
rlm@145 1310 (tick)
rlm@145 1311 (tick)
rlm@145 1312 (tick)
rlm@145 1313
rlm@145 1314 ;;(view-memory eggs)
rlm@145 1315 (tick)
rlm@145 1316 (tick)
rlm@145 1317 ;;(view-memory eggs)
rlm@145 1318 (tick)
rlm@145 1319 (tick)
rlm@145 1320 (tick)
rlm@145 1321 (tick)
rlm@145 1322 (tick)
rlm@145 1323 (tick)
rlm@145 1324 (d-tick)
rlm@145 1325
rlm@145 1326
rlm@145 1327 ;;(view-memory btn-register)
rlm@145 1328 (view-register "A" A)
rlm@145 1329 (view-register "B" B)
rlm@145 1330
rlm@145 1331 ;;(view-register "C" C)
rlm@145 1332 (view-register "D" D)
rlm@145 1333 (view-register "E" E)
rlm@145 1334 (view-register "H" H)
rlm@145 1335 (view-register "L" L)
rlm@145 1336 ))))
rlm@145 1337
rlm@145 1338 (defn test-mode-4
rlm@145 1339 ([] (test-mode-4 (write-memory)))
rlm@145 1340 ([target-state]
rlm@145 1341 (->
rlm@145 1342 target-state
rlm@145 1343 (#(do (println "memory from 0xC00F to 0xC01F:"
rlm@145 1344 (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
rlm@145 1345 (view-memory current-mode)
rlm@145 1346 (step [])
rlm@145 1347 (step [])
rlm@145 1348 (step [])
rlm@145 1349 (#(do (println "after three steps") %))
rlm@145 1350 (view-memory current-mode)
rlm@145 1351
rlm@145 1352 ;; Activate memory writing mode
rlm@145 1353
rlm@145 1354 (#(do (println "step with [:a]") %))
rlm@145 1355 (step [:a])
rlm@145 1356 (view-memory current-mode)
rlm@145 1357 (view-memory bytes-to-write)
rlm@145 1358 (view-memory start-point-high)
rlm@145 1359 (view-memory start-point-low)
rlm@145 1360
rlm@145 1361 ;; Specify four bytes to be written
rlm@145 1362
rlm@145 1363 (#(do (println "step with [:select]")%))
rlm@145 1364 (step [:select])
rlm@145 1365 (view-memory current-mode)
rlm@145 1366 (view-memory bytes-to-write)
rlm@145 1367 (view-memory start-point-high)
rlm@145 1368 (view-memory start-point-low)
rlm@145 1369
rlm@145 1370 ;; Specify target memory address as 0xC00F
rlm@145 1371
rlm@145 1372 (#(do (println "step with [:u :d]")%))
rlm@145 1373 (step [:u :d])
rlm@145 1374 (view-memory current-mode)
rlm@145 1375 (view-memory bytes-to-write)
rlm@145 1376 (view-memory start-point-high)
rlm@145 1377 (view-memory start-point-low)
rlm@145 1378
rlm@145 1379 (#(do (println "step with [:a :b :start :select]")%))
rlm@145 1380 (step [:a :b :start :select])
rlm@145 1381 (view-memory current-mode)
rlm@145 1382 (view-memory bytes-to-write)
rlm@145 1383 (view-memory start-point-high)
rlm@145 1384 (view-memory start-point-low)
rlm@145 1385
rlm@145 1386 ;; Start reprogramming memory
rlm@145 1387
rlm@145 1388 (#(do (println "step with [:a]")%))
rlm@145 1389 (step [:a])
rlm@145 1390 (view-memory current-mode)
rlm@145 1391 (view-memory bytes-written)
rlm@145 1392
rlm@145 1393 (#(do (println "step with [:b]")%))
rlm@145 1394 (step [:b])
rlm@145 1395 (view-memory current-mode)
rlm@145 1396 (view-memory bytes-written)
rlm@145 1397
rlm@145 1398 (#(do (println "step with [:a :b]")%))
rlm@145 1399 (step [:a :b])
rlm@145 1400 (view-memory current-mode)
rlm@145 1401 (view-memory bytes-written)
rlm@145 1402
rlm@145 1403 (#(do (println "step with [:select]")%))
rlm@145 1404 (step [:select])
rlm@145 1405 (view-memory current-mode)
rlm@145 1406 (view-memory bytes-written)
rlm@145 1407
rlm@145 1408 ;; Reprogramming done, program ready for more commands.
rlm@145 1409
rlm@145 1410 (#(do (println "step with []")%))
rlm@145 1411 (step [])
rlm@145 1412 (view-memory current-mode)
rlm@145 1413 (view-memory bytes-written)
rlm@145 1414
rlm@145 1415 (#(do (println "memory from 0xC00F to 0xC01F:"
rlm@145 1416 (subvec (vec (memory %)) 0xC00F 0xC01F)) %)))))
rlm@145 1417
ocsenave@184 1418
ocsenave@184 1419
ocsenave@184 1420
ocsenave@184 1421
ocsenave@184 1422
ocsenave@184 1423 ;;; ASSEMBLY-READING UTILITIES
ocsenave@184 1424
ocsenave@184 1425 (def opcodes
ocsenave@184 1426 [
ocsenave@184 1427 "NOP"
ocsenave@184 1428 "LD BC,nn"
ocsenave@184 1429 "LD (BC),A"
ocsenave@184 1430 "INC BC"
ocsenave@184 1431 "INC B"
ocsenave@184 1432 "DEC B"
ocsenave@184 1433 "LD B,n"
ocsenave@184 1434 "RLC A"
ocsenave@184 1435 "LD (nn),SP"
ocsenave@184 1436 "ADD HL,BC"
ocsenave@184 1437 "LD A,(BC)"
ocsenave@184 1438 "DEC BC"
ocsenave@184 1439 "INC C"
ocsenave@184 1440 "DEC C"
ocsenave@184 1441 "LD C,n"
ocsenave@184 1442 "RRC A"
ocsenave@184 1443
ocsenave@184 1444 "STOP"
ocsenave@184 1445 "LD DE,nn"
ocsenave@184 1446 "LD (DE),A"
ocsenave@184 1447 "INC DE"
ocsenave@184 1448 "INC D"
ocsenave@184 1449 "DEC D"
ocsenave@184 1450 "LD D,n"
ocsenave@184 1451 "RL A"
ocsenave@184 1452 "JR n"
ocsenave@184 1453 "ADD HL,DE"
ocsenave@184 1454 "LD A,(DE)"
ocsenave@184 1455 "DEC DE"
ocsenave@184 1456 "INC E"
ocsenave@184 1457 "DEC E"
ocsenave@184 1458 "LD E,n"
ocsenave@184 1459 "RR A"
ocsenave@184 1460
ocsenave@184 1461 "JR NZ,n"
ocsenave@184 1462 "LD HL,nn"
ocsenave@184 1463 "LDI (HL),A"
ocsenave@184 1464 "INC HL"
ocsenave@184 1465 "INC H"
ocsenave@184 1466 "DEC H"
ocsenave@184 1467 "LD H,n"
ocsenave@184 1468 "DAA"
ocsenave@184 1469 "JR Z,n"
ocsenave@184 1470 "ADD HL,HL"
ocsenave@184 1471 "LDI A,(HL)"
ocsenave@184 1472 "DEC HL"
ocsenave@184 1473 "INC L"
ocsenave@184 1474 "DEC L"
ocsenave@184 1475 "LD L,n"
ocsenave@184 1476 "CPL"
ocsenave@184 1477
ocsenave@184 1478 "JR NC,n"
ocsenave@184 1479 "LD SP,nn"
ocsenave@184 1480 "LDD (HL),A"
ocsenave@184 1481 "INC SP"
ocsenave@184 1482 "INC (HL)"
ocsenave@184 1483 "DEC (HL)"
ocsenave@184 1484 "LD (HL),n"
ocsenave@184 1485 "SCF"
ocsenave@184 1486 "JR C,n"
ocsenave@184 1487 "ADD HL,SP"
ocsenave@184 1488 "LDD A,(HL)"
ocsenave@184 1489 "DEC SP"
ocsenave@184 1490 "INC A"
ocsenave@184 1491 "DEC A"
ocsenave@184 1492 "LD A,n"
ocsenave@184 1493 "CCF"
ocsenave@184 1494
ocsenave@184 1495 "LD B,B"
ocsenave@184 1496 "LD B,C"
ocsenave@184 1497 "LD B,D"
ocsenave@184 1498 "LD B,E"
ocsenave@184 1499 "LD B,H"
ocsenave@184 1500 "LD B,L"
ocsenave@184 1501 "LD B,(HL)"
ocsenave@184 1502 "LD B,A"
ocsenave@184 1503 "LD C,B"
ocsenave@184 1504 "LD C,C"
ocsenave@184 1505 "LD C,D"
ocsenave@184 1506 "LD C,E"
ocsenave@184 1507 "LD C,H"
ocsenave@184 1508 "LD C,L"
ocsenave@184 1509 "LD C,(HL)"
ocsenave@184 1510 "LD C,A"
ocsenave@184 1511
ocsenave@184 1512 "LD D,B"
ocsenave@184 1513 "LD D,C"
ocsenave@184 1514 "LD D,D"
ocsenave@184 1515 "LD D,E"
ocsenave@184 1516 "LD D,H"
ocsenave@184 1517 "LD D,L"
ocsenave@184 1518 "LD D,(HL)"
ocsenave@184 1519 "LD D,A"
ocsenave@184 1520 "LD E,B"
ocsenave@184 1521 "LD E,C"
ocsenave@184 1522 "LD E,D"
ocsenave@184 1523 "LD E,E"
ocsenave@184 1524 "LD E,H"
ocsenave@184 1525 "LD E,L"
ocsenave@184 1526 "LD E,(HL)"
ocsenave@184 1527 "LD E,A"
ocsenave@184 1528
ocsenave@184 1529 "LD H,B"
ocsenave@184 1530 "LD H,C"
ocsenave@184 1531 "LD H,D"
ocsenave@184 1532 "LD H,E"
ocsenave@184 1533 "LD H,H"
ocsenave@184 1534 "LD H,L"
ocsenave@184 1535 "LD H,(HL)"
ocsenave@184 1536 "LD H,A"
ocsenave@184 1537 "LD L,B"
ocsenave@184 1538 "LD L,C"
ocsenave@184 1539 "LD L,D"
ocsenave@184 1540 "LD L,E"
ocsenave@184 1541 "LD L,H"
ocsenave@184 1542 "LD L,L"
ocsenave@184 1543 "LD L,(HL)"
ocsenave@184 1544 "LD L,A"
ocsenave@184 1545
ocsenave@184 1546 "LD (HL),B"
ocsenave@184 1547 "LD (HL),C"
ocsenave@184 1548 "LD (HL),D"
ocsenave@184 1549 "LD (HL),E"
ocsenave@184 1550 "LD (HL),H"
ocsenave@184 1551 "LD (HL),L"
ocsenave@184 1552 "HALT"
ocsenave@184 1553 "LD (HL),A"
ocsenave@184 1554 "LD A,B"
ocsenave@184 1555 "LD A,C"
ocsenave@184 1556 "LD A,D"
ocsenave@184 1557 "LD A,E"
ocsenave@184 1558 "LD A,H"
ocsenave@184 1559 "LD A,L"
ocsenave@184 1560 "LD A,(HL)"
ocsenave@184 1561 "LD A,A"
ocsenave@184 1562
ocsenave@184 1563 "ADD A,B"
ocsenave@184 1564 "ADD A,C"
ocsenave@184 1565 "ADD A,D"
ocsenave@184 1566 "ADD A,E"
ocsenave@184 1567 "ADD A,H"
ocsenave@184 1568 "ADD A,L"
ocsenave@184 1569 "ADD A,(HL)"
ocsenave@184 1570 "ADD A,A"
ocsenave@184 1571 "ADC A,B"
ocsenave@184 1572 "ADC A,C"
ocsenave@184 1573 "ADC A,D"
ocsenave@184 1574 "ADC A,E"
ocsenave@184 1575 "ADC A,H"
ocsenave@184 1576 "ADC A,L"
ocsenave@184 1577 "ADC A,(HL)"
ocsenave@184 1578 "ADC A,A"
ocsenave@184 1579
ocsenave@184 1580 "SUB A,B"
ocsenave@184 1581 "SUB A,C"
ocsenave@184 1582 "SUB A,D"
ocsenave@184 1583 "SUB A,E"
ocsenave@184 1584 "SUB A,H"
ocsenave@184 1585 "SUB A,L"
ocsenave@184 1586 "SUB A,(HL)"
ocsenave@184 1587 "SUB A,A"
ocsenave@184 1588 "SBC A,B"
ocsenave@184 1589 "SBC A,C"
ocsenave@184 1590 "SBC A,D"
ocsenave@184 1591 "SBC A,E"
ocsenave@184 1592 "SBC A,H"
ocsenave@184 1593 "SBC A,L"
ocsenave@184 1594 "SBC A,(HL)"
ocsenave@184 1595 "SBC A,A"
ocsenave@184 1596
ocsenave@184 1597 "AND B"
ocsenave@184 1598 "AND C"
ocsenave@184 1599 "AND D"
ocsenave@184 1600 "AND E"
ocsenave@184 1601 "AND H"
ocsenave@184 1602 "AND L"
ocsenave@184 1603 "AND (HL)"
ocsenave@184 1604 "AND A"
ocsenave@184 1605 "XOR B"
ocsenave@184 1606 "XOR C"
ocsenave@184 1607 "XOR D"
ocsenave@184 1608 "XOR E"
ocsenave@184 1609 "XOR H"
ocsenave@184 1610 "XOR L"
ocsenave@184 1611 "XOR (HL)"
ocsenave@184 1612 "XOR A"
ocsenave@184 1613
ocsenave@184 1614 "OR B"
ocsenave@184 1615 "OR C"
ocsenave@184 1616 "OR D"
ocsenave@184 1617 "OR E"
ocsenave@184 1618 "OR H"
ocsenave@184 1619 "OR L"
ocsenave@184 1620 "OR (HL)"
ocsenave@184 1621 "OR A"
ocsenave@184 1622 "CP B"
ocsenave@184 1623 "CP C"
ocsenave@184 1624 "CP D"
ocsenave@184 1625 "CP E"
ocsenave@184 1626 "CP H"
ocsenave@184 1627 "CP L"
ocsenave@184 1628 "CP (HL)"
ocsenave@184 1629 "CP A"
ocsenave@184 1630
ocsenave@184 1631 "RET NZ"
ocsenave@184 1632 "POP BC"
ocsenave@184 1633 "JP NZ,nn"
ocsenave@184 1634 "JP nn"
ocsenave@184 1635 "CALL NZ,nn"
ocsenave@184 1636 "PUSH BC"
ocsenave@184 1637 "ADD A,n"
ocsenave@184 1638 "RST 0"
ocsenave@184 1639 "RET Z"
ocsenave@184 1640 "RET"
ocsenave@184 1641 "JP Z,nn"
ocsenave@184 1642 "Ext ops"
ocsenave@184 1643 "CALL Z,nn"
ocsenave@184 1644 "CALL nn"
ocsenave@184 1645 "ADC A,n"
ocsenave@184 1646 "RST 8"
ocsenave@184 1647
ocsenave@184 1648 "RET NC"
ocsenave@184 1649 "POP DE"
ocsenave@184 1650 "JP NC,nn"
ocsenave@184 1651 "XX"
ocsenave@184 1652 "CALL NC,nn"
ocsenave@184 1653 "PUSH DE"
ocsenave@184 1654 "SUB A,n"
ocsenave@184 1655 "RST 10"
ocsenave@184 1656 "RET C"
ocsenave@184 1657 "RETI"
ocsenave@184 1658 "JP C,nn"
ocsenave@184 1659 "XX"
ocsenave@184 1660 "CALL C,nn"
ocsenave@184 1661 "XX"
ocsenave@184 1662 "SBC A,n"
ocsenave@184 1663 "RST 18"
ocsenave@184 1664
ocsenave@184 1665 "LDH (n),A"
ocsenave@184 1666 "POP HL"
ocsenave@184 1667 "LDH (C),A"
ocsenave@184 1668 "XX"
ocsenave@184 1669 "XX"
ocsenave@184 1670 "PUSH HL"
ocsenave@184 1671 "AND n"
ocsenave@184 1672 "RST 20"
ocsenave@184 1673 "ADD SP,d"
ocsenave@184 1674 "JP (HL)"
ocsenave@184 1675 "LD (nn),A"
ocsenave@184 1676 "XX"
ocsenave@184 1677 "XX"
ocsenave@184 1678 "XX"
ocsenave@184 1679 "XOR n"
ocsenave@184 1680 "RST 28"
ocsenave@184 1681
ocsenave@184 1682 "LDH A,(n)"
ocsenave@184 1683 "POP AF"
ocsenave@184 1684 "XX"
ocsenave@184 1685 "DI"
ocsenave@184 1686 "XX"
ocsenave@184 1687 "PUSH AF"
ocsenave@184 1688 "OR n"
ocsenave@184 1689 "RST 30"
ocsenave@184 1690 "LDHL SP,d"
ocsenave@184 1691 "LD SP,HL"
ocsenave@184 1692 "LD A,(nn)"
ocsenave@184 1693 "EI"
ocsenave@184 1694 "XX"
ocsenave@184 1695 "XX"
ocsenave@184 1696 "CP n"
ocsenave@184 1697 "RST 38"])
ocsenave@184 1698
ocsenave@184 1699
ocsenave@184 1700 (defn hex
ocsenave@184 1701 "Converts the number into a hexadecimal-formatted symbol."
ocsenave@184 1702 [n]
ocsenave@184 1703 (symbol (str "0x" (.toUpperCase (Integer/toHexString n)))))
ocsenave@184 1704
ocsenave@184 1705
ocsenave@184 1706
ocsenave@184 1707 (defn arity
ocsenave@184 1708 "Returns the arity of the given opcode (hex numeral)."
ocsenave@184 1709 [op]
ocsenave@184 1710 (cond
ocsenave@184 1711 (#{0x06 0x0E 0x16 0x1E
ocsenave@184 1712 0x20 0x26 0x28 0x2E
ocsenave@184 1713 0x30 0x36 0x38 0x3E
ocsenave@184 1714 0xC6 0xD6 0xCE 0xDE
ocsenave@184 1715 0xE0 0xF0 0xE6 0xF6
ocsenave@184 1716 0xEE 0xFE} op)
ocsenave@184 1717 1
ocsenave@184 1718 (#{0x01 0x08 0x11 0x21
ocsenave@184 1719 0x31 0xC2 0xC3 0xC4
ocsenave@184 1720 0xCA 0xDA 0xCC 0xDC
ocsenave@184 1721 0xCD 0xEA 0xFA} op)
ocsenave@184 1722 2
ocsenave@184 1723 :else
ocsenave@184 1724 0))