diff clojure/com/aurellem/gb/assembly.clj @ 145:412ca096a9ba

major refactoring complete.
author Robert McIntyre <rlm@mit.edu>
date Mon, 19 Mar 2012 21:23:46 -0500
parents
children 5d9a7a0ca09a
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/clojure/com/aurellem/gb/assembly.clj	Mon Mar 19 21:23:46 2012 -0500
     1.3 @@ -0,0 +1,1431 @@
     1.4 +(ns com.aurellem.gb.assembly
     1.5 +  (:use (com.aurellem.gb gb-driver vbm util items))
     1.6 +  (:import [com.aurellem.gb.gb_driver SaveState]))
     1.7 +
     1.8 +(defn inject-assembly
     1.9 +  ([^SaveState state
    1.10 +   program-counter registers
    1.11 +   assembly-code]
    1.12 +  (let [scratch-memory (memory state)]
    1.13 +    ;; inject assembly code
    1.14 +    (dorun (map (fn [index val]
    1.15 +                  (aset scratch-memory index val))
    1.16 +                (range program-counter
    1.17 +                       (+ program-counter (count assembly-code)))
    1.18 +                assembly-code))
    1.19 +    (-> state
    1.20 +        (write-memory! scratch-memory)
    1.21 +        (write-registers! registers)
    1.22 +        (PC! program-counter)))))
    1.23 +
    1.24 +(defn inject-item-assembly
    1.25 +  ([^SaveState state assembly-code]
    1.26 +     (inject-assembly state (inc item-list-start)
    1.27 +                      (registers state)
    1.28 +                      assembly-code))
    1.29 +  ([assembly-code]
    1.30 +     (inject-item-assembly @current-state assembly-code)))
    1.31 +
    1.32 +(defn run-assembly
    1.33 +  ([info-fn assembly n]
    1.34 +     (let [final-state
    1.35 +           (reduce (fn [state _]
    1.36 +                     (tick (info-fn state)))
    1.37 +                   (inject-item-assembly
    1.38 +                     (mid-game) assembly)
    1.39 +                   (range n))]
    1.40 +       final-state))
    1.41 +  ([assembly n]
    1.42 +     (run-assembly d-tick assembly n)))
    1.43 +
    1.44 +(def buttons-port 0xFF00)
    1.45 +
    1.46 +(defn trace [state]
    1.47 +  (loop [program-counters [(first (registers @current-state)) ]
    1.48 +         opcodes [(aget (memory @current-state) (PC @current-state))]]
    1.49 +    (let [frame-boundary?
    1.50 +          (com.aurellem.gb.Gb/tick)]
    1.51 +      (if frame-boundary?
    1.52 +        [program-counters opcodes]
    1.53 +        (recur
    1.54 +         (conj program-counters
    1.55 +               (first (registers @current-state)))
    1.56 +         (conj opcodes
    1.57 +               (aget (memory @current-state)
    1.58 +                     (PC @current-state))))))))
    1.59 +
    1.60 +(defn print-trace [state n]
    1.61 +  (let [[program-counters opcodes] (trace state)]
    1.62 +    (dorun (map (fn [pc op] (println (format "%04X: 0x%02X" pc op)))
    1.63 +                (take n program-counters)
    1.64 +                (take n opcodes)))))
    1.65 +
    1.66 +(defn good-trace []
    1.67 +  (-> (mid-game) (tick) (IE! 0)
    1.68 +      (set-inv-mem [0x00 0x00 0X00 0x00])
    1.69 +      (PC! item-list-start)(print-interrupt)
    1.70 +      (d-tick) (tick) (d-tick) (tick) (d-tick)))
    1.71 +
    1.72 +(defn read-down-button []
    1.73 +  (-> (tick (mid-game))
    1.74 +      (IE! 0) ; disable interrupts
    1.75 +      (inject-item-assembly
    1.76 +       ;; write 00010000 to 0xFF00 to select joypad
    1.77 +       [0x18   ;D31D                    ; jump over          
    1.78 +        0x01   ;D31E                    ; the next 8 bits
    1.79 +                                        ;D31F
    1.80 +        (Integer/parseInt "00100000" 2) ; data section 
    1.81 +        
    1.82 +        0xFA   ;D320                    ; load (D31F) into A
    1.83 +        0x1F   ;D321      -->       
    1.84 +        0xD3   ;D322      -->  D31F     
    1.85 +
    1.86 +        0xEA   ;D323                    ; load (A), which is 
    1.87 +        0x00   ;D324      -->           ; 00010000, into FF00
    1.88 +        0xFF   ;D325      -->  FF00     
    1.89 +        
    1.90 +        0x18   ;D326                    ; this is the place where
    1.91 +        0x01   ;D327                    ; we will store whether
    1.92 +        0x00   ;D328                    ; "down" is pressed.
    1.93 +
    1.94 +        0xFA   ;D329                    ; (FF00) -> A
    1.95 +        0x00   ;D32A                   
    1.96 +        0xFF   ;D32B
    1.97 +
    1.98 +        0xCB   ;D32C                    ; Test whether "down"
    1.99 +        0x5F   ;D32D                    ; is pressed.
   1.100 +
   1.101 +        0x28   ;D32E                    ; if down is pressed,
   1.102 +        0x03   ;D32F                    ; skip the next section 
   1.103 +                                        ; of code.
   1.104 +        ;; down-is-not-pressed
   1.105 +        0xC3   ;D330
   1.106 +        0x1D   ;D331                    ; return to beginning
   1.107 +        0xD3   ;D332
   1.108 +        
   1.109 +        ;; down-is-pressed 
   1.110 +        0xEA   ;D334                    ; write A to D328 if 
   1.111 +        0x28   ;D335                    ; "down" was pressed
   1.112 +        0xD3   ;D336
   1.113 +
   1.114 +        0xC3   ;D330
   1.115 +        0x1D   ;D331                    ; return to beginning
   1.116 +        0xD3   ;D332
   1.117 +        ])))
   1.118 +
   1.119 +(defn test-read-down []
   1.120 + (= (view-memory (step (step (read-down-button) [:d])) 0xD328)
   1.121 +    (view-memory (step (step (read-down-button))) 0xD328)))
   1.122 +
   1.123 +(defn count-frames []
   1.124 +  (-> (tick (mid-game))
   1.125 +      (IE! 0) ; disable interrupts
   1.126 +      (inject-item-assembly
   1.127 +       [0x18   ;D31D                    ; jump over          
   1.128 +        0x02   ;D31E                    ; the next 2 bytes
   1.129 +        0x00   ;D31F                    ; frame-count
   1.130 +        0x00   ;D320                    ; v-blank-prev
   1.131 +        
   1.132 +        0xFA   ;D321
   1.133 +        0x41   ;D322                    ; load (FF41) into A
   1.134 +        0xFF   ;D323                    ; this contains mode flags
   1.135 +        
   1.136 +        ;; if we're in v-blank, the bit-1 is 0
   1.137 +        ;; and bit-2 is 1  Otherwise, it is not v-blank.
   1.138 +        0xCB   ;D324                     ; test bit-1 of A
   1.139 +        0x4F   ;D325                         
   1.140 +
   1.141 +        0xC2   ;D326                     ; if bit-1 is not 0
   1.142 +        0x44   ;D327                     ; GOTO not-v-blank
   1.143 +        0xD3   ;D328
   1.144 +        
   1.145 +        0xCB   ;D329                     ; test bit-0 of A 
   1.146 +        0x47   ;D32A
   1.147 +
   1.148 +        0xCA   ;D32B                     ; if bit-0 is not 1
   1.149 +        0x44   ;D32C                     ; GOTO not-v-blank
   1.150 +        0xD3   ;D32D
   1.151 +        ;;; in v-blank mode
   1.152 +           ;; if v-blank-prev was 0,
   1.153 +           ;; increment frame-count
   1.154 +
   1.155 +        0xFA   ;D32E                    ; load v-blank-prev to A
   1.156 +        0x20   ;D32F
   1.157 +        0xD3   ;D330
   1.158 +        
   1.159 +        0xCB   ;D331
   1.160 +        0x47   ;D332                    ; test bit-0 of A 
   1.161 +
   1.162 +        0x20   ;D333                    ; skip next section
   1.163 +        0x07   ;D334                    ; if v-blank-prev was not zero 
   1.164 +        
   1.165 +           ;; v-blank was 0, increment frame-count
   1.166 +        0xFA   ;D335                    ; load frame-count into A
   1.167 +        0x1F   ;D336
   1.168 +        0xD3   ;D337                   
   1.169 +
   1.170 +        0x3C   ;D338                    ; inc A
   1.171 +
   1.172 +        0xEA   ;D339                    ; load A into frame-count
   1.173 +        0x1F   ;D33A
   1.174 +        0xD3   ;D33B
   1.175 +
   1.176 +           ;; set v-blank-prev to 1
   1.177 +        0x3E   ;D33C                    ; load 1 into A
   1.178 +        0x01   ;D33D                    
   1.179 +
   1.180 +        0xEA   ;D33E                    ; load A into v-blank-prev
   1.181 +        0x20   ;D33F
   1.182 +        0xD3   ;D340
   1.183 +
   1.184 +        0xC3   ;D341                   ; return to beginning
   1.185 +        0x1D   ;D342
   1.186 +        0xD3   ;D343
   1.187 +
   1.188 +        ;;; not in v-blank mode
   1.189 +           ;; set v-blank-prev to 0
   1.190 +        0x3E   ;D344                    ; load 0 into A        
   1.191 +        0x00   ;D345
   1.192 +
   1.193 +        0xEA   ;D346                    ; load A into v-blank-prev
   1.194 +        0x20   ;D347
   1.195 +        0xD3   ;D348
   1.196 +
   1.197 +        0xC3   ;D349                   ; return to beginning
   1.198 +        0x1D   ;D34A
   1.199 +        0xD3   ;D34B
   1.200 +        ])))
   1.201 +
   1.202 +(defn step-count-frames []
   1.203 +  (-> (read-down-button)
   1.204 +      (d-tick)
   1.205 +      (tick)  ;; skip over data section
   1.206 +      (d-tick)  
   1.207 +      (view-register "Register A" A)
   1.208 +      (tick)  ;; load-data into A
   1.209 +      (view-register "Register A" A)
   1.210 +      (d-tick)
   1.211 +      (view-memory 0xFF00)
   1.212 +      (tick) ;; load A into 0xFF00
   1.213 +      (view-memory 0xFF00)
   1.214 +      (d-tick)
   1.215 +      (tick)
   1.216 +      (d-tick)
   1.217 +      (tick)
   1.218 +      (d-tick)
   1.219 +      (tick)
   1.220 +      (d-tick)
   1.221 +      (tick)
   1.222 +      (d-tick)
   1.223 +      (tick)
   1.224 +      (d-tick)
   1.225 +      (tick)
   1.226 +      (print-inventory)))
   1.227 +
   1.228 +(defn test-count-frames []
   1.229 +  (= 255 (aget (memory ((apply comp (repeat 255 step))
   1.230 +                        (count-frames)))
   1.231 +               0xD31F)))
   1.232 +
   1.233 +;; specs for main bootstrap program
   1.234 +;; starts in "mode-select" mode
   1.235 +;;   Each button press takes place in a single frame.
   1.236 +;;   mode-select-mode takes one of the main buttons
   1.237 +;;   which selects one of up to eight modes
   1.238 +;;   mode 1 activated by the "A" button
   1.239 +;;   the next two button presses indicates the start
   1.240 +;;   memory location which to which the bootstrap
   1.241 +;;   program will write.
   1.242 +;;   This is done by using each of the eight buttons to
   1.243 +;;   spell out an 8 bit number.  The order of buttons is
   1.244 +;;   [:d :u :l :r :start :select :b :a]
   1.245 +;;   [:a :start :l]  -->  00101001
   1.246 +
   1.247 +;;   the next button press determines how many bytes are to be
   1.248 +;;   written, starting at the start position.
   1.249 +
   1.250 +;;   then, the actual bytes are entered and are written to the
   1.251 +;;   start address in sequence.
   1.252 +
   1.253 +(defn input-number-assembly []
   1.254 +  [0x18   ;D31D                    ; jump over          
   1.255 +   0x02   ;D31E                    ; the next 2 bytes
   1.256 +   0x00   ;D31F                    ; frame-count
   1.257 +   0x00   ;D320                    ; v-blank-prev
   1.258 +   
   1.259 +   0xFA   ;D321
   1.260 +   0x41   ;D322                    ; load (FF41) into A
   1.261 +   0xFF   ;D323                    ; this contains mode flags
   1.262 +   
   1.263 +   ;; if we're in v-blank, the bit-1 is 0
   1.264 +   ;; and bit-2 is 1  Otherwise, it is not v-blank.
   1.265 +   0xCB   ;D324                     ; test bit-1 of A
   1.266 +   0x4F   ;D325                         
   1.267 +
   1.268 +   0xC2   ;D326                     ; if bit-1 is not 0
   1.269 +   0x44   ;D327                     ; GOTO not-v-blank
   1.270 +   0xD3   ;D328
   1.271 +   
   1.272 +   0xCB   ;D329                     ; test bit-0 of A 
   1.273 +   0x47   ;D32A
   1.274 +
   1.275 +   0xCA   ;D32B                     ; if bit-0 is not 1
   1.276 +   0x44   ;D32C                     ; GOTO not-v-blank
   1.277 +   0xD3   ;D32D
   1.278 +   
   1.279 +        ;;; in v-blank mode
   1.280 +
   1.281 +   ;; if v-blank-prev was 0,
   1.282 +   ;; increment frame-count
   1.283 +
   1.284 +   0xFA   ;D32E                    ; load v-blank-prev to A
   1.285 +   0x20   ;D32F
   1.286 +   0xD3   ;D330
   1.287 +   
   1.288 +   0xCB   ;D331
   1.289 +   0x47   ;D332                    ; test bit-0 of A 
   1.290 +
   1.291 +   0x20   ;D333                    ; skip next section
   1.292 +   0x07   ;D334                    ; if v-blank-prev was not zero 
   1.293 +   
   1.294 +   ;; v-blank was 0, increment frame-count
   1.295 +   0xFA   ;D335                    ; load frame-count into A
   1.296 +   0x1F   ;D336
   1.297 +   0xD3   ;D337                   
   1.298 +
   1.299 +   0x3C   ;D338                    ; inc A
   1.300 +
   1.301 +   0xEA   ;D339                    ; load A into frame-count
   1.302 +   0x1F   ;D33A
   1.303 +   0xD3   ;D33B
   1.304 +
   1.305 +   ;; set v-blank-prev to 1
   1.306 +   0x3E   ;D33C                    ; load 1 into A
   1.307 +   0x01   ;D33D                    
   1.308 +
   1.309 +   0xEA   ;D33E                    ; load A into v-blank-prev
   1.310 +   0x20   ;D33F
   1.311 +   0xD3   ;D340
   1.312 +
   1.313 +   0xC3   ;D341                   ; GOTO input handling code
   1.314 +   0x4E   ;D342
   1.315 +   0xD3   ;D343
   1.316 +
   1.317 +        ;;; not in v-blank mode
   1.318 +   ;; set v-blank-prev to 0
   1.319 +   0x3E   ;D344                    ; load 0 into A        
   1.320 +   0x00   ;D345
   1.321 +
   1.322 +   0xEA   ;D346                    ; load A into v-blank-prev
   1.323 +   0x20   ;D347
   1.324 +   0xD3   ;D348
   1.325 +
   1.326 +   0xC3   ;D349                   ; return to beginning
   1.327 +   0x1D   ;D34A
   1.328 +   0xD3   ;D34B
   1.329 +
   1.330 +   0x00   ;D34C                   ; these are here 
   1.331 +   0x00   ;D34D                   ; for glue
   1.332 +   
   1.333 +   
   1.334 +        ;;; calculate input number based on button presses
   1.335 +   0x18   ;D34E                    ;  skip next 3 bytes
   1.336 +   0x03   ;D34F
   1.337 +                                        ;D350
   1.338 +   (Integer/parseInt "00100000" 2) ;  select directional pad
   1.339 +                                        ;D351
   1.340 +   (Integer/parseInt "00010000" 2) ;  select buttons
   1.341 +   0x00   ;D352                    ;  input-number
   1.342 +
   1.343 +   ;; select directional pad, store low bits in B
   1.344 +   
   1.345 +   0xFA   ;D353                    ; load (D350) into A
   1.346 +   0x50   ;D354      -->       
   1.347 +   0xD3   ;D355      -->  D31F     
   1.348 +   
   1.349 +   0xEA   ;D356                    ; load A, which is 
   1.350 +   0x00   ;D357      -->           ; 00010000, into FF00
   1.351 +   0xFF   ;D358      -->  FF00     
   1.352 +
   1.353 +   0x06   ;D359
   1.354 +                                        ;D35A
   1.355 +   (Integer/parseInt "11110000" 2) ; "11110000" -> B 
   1.356 +   0xFA   ;D35B                    ; (FF00) -> A
   1.357 +   0x00   ;D35C                   
   1.358 +   0xFF   ;D35D
   1.359 +
   1.360 +   0xCB   ;D35E                    ; swap nybbles on A
   1.361 +   0x37   ;D35F
   1.362 +   0xA0   ;D360                    ; (AND A B) -> A
   1.363 +   0x47   ;D361                    ; A -> B
   1.364 +
   1.365 +   ;; select buttons store bottom bits in C
   1.366 +   
   1.367 +   0xFA   ;                        ; load (D351) into A
   1.368 +   0x51   ;          -->       
   1.369 +   0xD3   ;          -->  D31F     
   1.370 +   
   1.371 +   0xEA   ;                        ; load (A), which is 
   1.372 +   0x00   ;          -->           ; 00001000, into FF00
   1.373 +   0xFF   ;          -->  FF00     
   1.374 +
   1.375 +   0x0E   ;    
   1.376 +   (Integer/parseInt "00001111" 2) ; "00001111" -> C 
   1.377 +
   1.378 +   0xFA   ;                        ; (FF00) -> A
   1.379 +   0x00   ;                       
   1.380 +   0xFF   ;    
   1.381 +   
   1.382 +   0xA1   ;                        ; (AND A C) -> A
   1.383 +   0x4F   ;                        ; A -> C
   1.384 +
   1.385 +   ;; combine the B and C registers into the input number
   1.386 +   0x79   ;                        ; C -> A
   1.387 +   0xB0   ;                        ; (OR A B) -> A
   1.388 +   0x2F   ;                        ; negate A
   1.389 +
   1.390 +   0xEA   ;                        ; store A into input-number
   1.391 +   0x52   ;
   1.392 +   0xD3   ;
   1.393 +
   1.394 +   0xC3   ;                        ; return to beginning
   1.395 +   0x1D   ;    
   1.396 +   0xD3   ;    
   1.397 +   ])
   1.398 +
   1.399 +
   1.400 +
   1.401 +(defn input-number []
   1.402 +  (-> (tick (mid-game))
   1.403 +      (IE! 0) ; disable interrupts
   1.404 +      (inject-item-assembly (input-number-assembly))))
   1.405 +  
   1.406 +(defn test-input-number
   1.407 +  "Input freestyle buttons and observe the effects at the repl."
   1.408 +  []
   1.409 +  (set-state! (input-number)) 
   1.410 +  (dotimes [_ 90000] (step (view-memory @current-state 0xD352))))
   1.411 +
   1.412 +
   1.413 +    
   1.414 +
   1.415 +
   1.416 +
   1.417 +
   1.418 +
   1.419 +
   1.420 +
   1.421 +
   1.422 +
   1.423 +
   1.424 +
   1.425 +
   1.426 +
   1.427 +
   1.428 +
   1.429 +
   1.430 +
   1.431 +
   1.432 +
   1.433 +
   1.434 +
   1.435 +
   1.436 +
   1.437 +
   1.438 +
   1.439 +
   1.440 +(defn write-memory-assembly*
   1.441 +  "Currently, grabs input from the user each frame."
   1.442 +  []
   1.443 +  [
   1.444 +   ;; --------- FRAME METRONOME
   1.445 +   0x18 ;; jump ahead to cleanup. first time only.
   1.446 +   0x40 ;; v-blank-prev [D31E]
   1.447 +
   1.448 +   0xFA ;; load modes into A [D31F]
   1.449 +   0x41
   1.450 +   0xFF
   1.451 +
   1.452 +   0x47 ;; A -> B
   1.453 +   0xCB ;; rotate A
   1.454 +   0x2F
   1.455 +   0x2F ;; invert A
   1.456 +
   1.457 +   0xA0
   1.458 +   0x47 ;; now B_0 contains (VB==1)
   1.459 +
   1.460 +   0xFA ;; load v-blank-prev
   1.461 +   0x1E
   1.462 +   0xD3
   1.463 +
   1.464 +   0x2F ;; complement v-blank-prev
   1.465 +   
   1.466 +   0xA0 ;; A & B --> A
   1.467 +   0x4F ;; now C_0 contains increment?
   1.468 +
   1.469 +
   1.470 +   0x78 ;; B->A
   1.471 +   0xEA ;; spit A --> vbprev
   1.472 +   0x1E
   1.473 +   0xD3
   1.474 +
   1.475 +   0xCB   ;test C_0
   1.476 +   0x41
   1.477 +   0x20   ; JUMP ahead to button input if nonzero
   1.478 +   0x02
   1.479 +   0x18   ; JUMP  back to frame metronome (D31F)
   1.480 +   0xE7
   1.481 +   
   1.482 +   ;; -------- GET BUTTON INPUT
   1.483 +
   1.484 +        ;; btw, C_0 is now 1
   1.485 +        ;; prepare to select bits
   1.486 +
   1.487 +   0x06 ;; load 0x00 into B
   1.488 +   0x00 ;; to initialize for "OR" loop
   1.489 + 
   1.490 +   0x3E ;; load 0x20 into A, to measure dpad
   1.491 +   0x20
   1.492 +
   1.493 +   
   1.494 +   0xE0 ;; load A into [FF00] ;; start of OR loop [D33C]
   1.495 +   0x00
   1.496 +   
   1.497 +   0xF0 ;; load A from [FF00]
   1.498 +   0x00
   1.499 +
   1.500 +   0xE6 ;; bitmask 00001111
   1.501 +   0x0F
   1.502 +   
   1.503 +   0xB0 ;; A or B --> A
   1.504 +   0xCB
   1.505 +   0x41 ;; test bit 0 of C
   1.506 +   0x28 ;; JUMP forward if 0
   1.507 +   0x08
   1.508 +
   1.509 +   0x47 ;; A -> B
   1.510 +   0xCB ;; swap B nybbles
   1.511 +   0x30 
   1.512 +   0x0C ;; increment C
   1.513 +   0x3E ;; load 0x10 into A, to measure btns
   1.514 +   0x10
   1.515 +   0x18 ;; JUMP back to "load A into [FF00]" [20 steps?]
   1.516 +   0xED
   1.517 +
   1.518 +
   1.519 +   ;; ------ TAKE ACTION BASED ON USER INPUT
   1.520 +
   1.521 +   ;; "input mode"
   1.522 +   ;; mode 0x00 : select mode
   1.523 +   ;; mode 0x08 : select bytes-to-write
   1.524 +   ;; mode 0x10 : select hi-bit
   1.525 +   ;; mode 0x18 : select lo-bit
   1.526 +
   1.527 +   ;; "output mode"
   1.528 +   ;; mode 0x20 : write bytes
   1.529 +   ;; mode 0xFF : jump PC
   1.530 +
   1.531 +
   1.532 +   ;; registers
   1.533 +   ;; D : mode select
   1.534 +   ;; E : count of bytes to write
   1.535 +   ;; H : address-high
   1.536 +   ;; L : address-low
   1.537 +   
   1.538 +   ;; now A contains the pressed keys
   1.539 +   0x2F ; complement A, by request. [D34F]
   1.540 +   
   1.541 +   0x47 ; A->B ;; now B contains the pressed keys
   1.542 +   0x7B ; E->A ;; now A contains the count.
   1.543 +
   1.544 +   0xCB ; test bit 5 of D (are we in o/p mode?)
   1.545 +   0x6A
   1.546 +   0x28 ; if test == 0, skip this o/p section
   1.547 +   0x13 ; JUMP
   1.548 +   
   1.549 +   0xCB ; else, test bit 0 of D (fragile; are we in pc mode?)
   1.550 +   0x42
   1.551 +   0x28 ; if test == 0, skip the following command
   1.552 +   0x01
   1.553 +
   1.554 +   ;; output mode I: moving the program counter
   1.555 +   0xE9 ; ** move PC to (HL)
   1.556 +
   1.557 +   ;; output mode II: writing bytes
   1.558 +   0xFE ; A compare 0. finished writing?
   1.559 +   0x00
   1.560 +   0x20 ; if we are not finished, skip cleanup
   1.561 +   0x04 ; JUMP
   1.562 +
   1.563 +   ;; CLEANUP
   1.564 +   ;; btw, A is already zero.
   1.565 +   0xAF ; zero A  [D35F]
   1.566 +   0x57 ; A->D; makes D=0.
   1.567 +   0x18 ; end of frame
   1.568 +   0xBC
   1.569 +   
   1.570 +   ;; ---- end of cleanup
   1.571 +
   1.572 +   
   1.573 +   ;; continue writing bytes
   1.574 +   0x1D ;; decrement E, the number of bytes to write [D363]
   1.575 +   0x78 ;; B->A; now A contains the pressed keys
   1.576 +   0x77 ;; copy A to (HL)
   1.577 +   0x23 ;; increment HL
   1.578 +   0x18 ;; end frame. [goto D31F]
   1.579 +   0xB6 ;; TODO: set skip length backwards
   1.580 +
   1.581 +
   1.582 +   ;; ---- end of o/p section
   1.583 +   
   1.584 +   ;; i/p mode
   1.585 +   ;; adhere to the mode discipline:
   1.586 +   ;; D must be one of 0x00 0x08 0x10 0x18.
   1.587 +
   1.588 +   0x3E ;; load the constant 57 into A. [D369]
   1.589 +   0x57
   1.590 +   0x82 ;; add the mode to A
   1.591 +   0xEA ;; store A into "thing to execute"
   1.592 +   0x74
   1.593 +   0xD3
   1.594 +
   1.595 +   0x3E ;; load the constant 8 into A
   1.596 +   0x08
   1.597 +   0x82 ;; add the mode to A
   1.598 +   
   1.599 +   0x57 ;; store the incremented mode into D
   1.600 +   0x78 ;; B->A; now A contains the pressed keys
   1.601 +   
   1.602 +   0x00 ;; var: thing to execute [D374]
   1.603 +
   1.604 +   0x18 ;; end frame
   1.605 +   0xA8
   1.606 +   ]
   1.607 +  )
   1.608 +
   1.609 +(defn write-mem-dyl []
   1.610 +  (-> (tick (mid-game))
   1.611 +      (IE! 0)
   1.612 +      (inject-item-assembly (write-memory-assembly*))))
   1.613 +
   1.614 +
   1.615 +(defn dylan* []
   1.616 +  (->
   1.617 +   (write-mem-dyl)
   1.618 +
   1.619 +   (tick)
   1.620 +   (tick)
   1.621 +   (tick)
   1.622 +   (tick)
   1.623 +   (tick)
   1.624 +   (tick)
   1.625 +   (tick)
   1.626 +   (tick)
   1.627 +   (tick)
   1.628 +   (tick)
   1.629 +   (tick)
   1.630 +   (tick)
   1.631 +   (tick)
   1.632 +   (tick)
   1.633 +   (tick)
   1.634 +   (tick)
   1.635 +   (tick)
   1.636 +   (tick)
   1.637 +   (tick)
   1.638 +   (tick)
   1.639 +   (tick)
   1.640 +   (tick)
   1.641 +   (tick)
   1.642 +   (tick)
   1.643 +   (tick)
   1.644 +   (tick)
   1.645 +   (tick)
   1.646 +   (tick)
   1.647 +   (tick)
   1.648 +   (tick)
   1.649 +   (tick)
   1.650 +   (tick)
   1.651 +   (tick)
   1.652 +   (tick)
   1.653 +   (tick)
   1.654 +   (tick)
   1.655 +
   1.656 +   ;;(view-memory 0xD374)
   1.657 +   (tick)
   1.658 +   (tick)
   1.659 +   (tick)
   1.660 +   (tick)
   1.661 +   (tick)
   1.662 +   (tick)
   1.663 +   (tick)
   1.664 +   (tick)
   1.665 +   (tick)
   1.666 +   (tick)
   1.667 +   (tick)
   1.668 +   (tick)
   1.669 +   (tick)
   1.670 +   (tick)
   1.671 +   (tick)
   1.672 +   ;;(view-memory 0xD374)
   1.673 +   (d-tick)
   1.674 +
   1.675 +   (view-register "A" A)
   1.676 +   (view-register "B" B)
   1.677 +   (view-register "C" C))
   1.678 +
   1.679 +)
   1.680 +
   1.681 +
   1.682 +(defn dylan []
   1.683 +  (->
   1.684 +   (write-mem-dyl)
   1.685 +   (tick)
   1.686 +   (tick)
   1.687 +   (tick)
   1.688 +   (tick)
   1.689 +   (tick)
   1.690 +   (tick)
   1.691 +   (tick)
   1.692 +   (tick)
   1.693 +   (tick)
   1.694 +   (tick)
   1.695 +   (tick)
   1.696 +   (tick)
   1.697 +   (tick)
   1.698 +   (tick)
   1.699 +   (tick) ;; first loop
   1.700 +
   1.701 +
   1.702 +   (tick)
   1.703 +   (tick)
   1.704 +   (tick)
   1.705 +   (tick)
   1.706 +   (tick)
   1.707 +   (tick)
   1.708 +   (tick)
   1.709 +   (tick)
   1.710 +   (tick)
   1.711 +   (tick)
   1.712 +   (tick)
   1.713 +   (tick)
   1.714 +   (tick) ;; dpad bits
   1.715 +
   1.716 +   (tick)
   1.717 +   (tick)
   1.718 +   (tick)
   1.719 +   (tick)
   1.720 +   (tick)
   1.721 +   (tick)
   1.722 +   (tick)
   1.723 +   (tick)
   1.724 +   (d-tick)
   1.725 +   
   1.726 +
   1.727 +   
   1.728 +   (view-register "A" A)
   1.729 +   (view-register "B" B)
   1.730 +   (view-register "C" C)
   1.731 +   
   1.732 +   ))
   1.733 +
   1.734 +
   1.735 +
   1.736 +
   1.737 +(defn d2 []
   1.738 +  (->
   1.739 +   (write-mem-dyl)
   1.740 +   (view-memory 0xD31F)
   1.741 +   step step step step step
   1.742 +   (view-memory 0xD31F)))
   1.743 +
   1.744 +
   1.745 +
   1.746 +
   1.747 +
   1.748 +
   1.749 +
   1.750 +
   1.751 +
   1.752 +
   1.753 +
   1.754 +
   1.755 +
   1.756 +
   1.757 +
   1.758 +
   1.759 +
   1.760 +
   1.761 +
   1.762 +
   1.763 +(defn write-memory-assembly []
   1.764 +  [
   1.765 +   ;; Main Timing Loop
   1.766 +   ;;   Constantly check for v-blank and Trigger main state machine on
   1.767 +   ;;   every transtion from v-blank to non-v-blank.
   1.768 +    
   1.769 +   0x18   ; D31D                  ; Variable declaration
   1.770 +   0x02   ; D31E                   
   1.771 +   0x00   ; D31F                  ; frame-count
   1.772 +   0x00   ; D320                  ; v-blank-prev 
   1.773 +   
   1.774 +   0xF0   ; D321                  ; load v-blank mode flags into A
   1.775 +   0x41
   1.776 +   0x00
   1.777 +
   1.778 +
   1.779 +   ;; Branch dependent on v-blank.  v-blank happens when the last two
   1.780 +   ;; bits in A are "01"
   1.781 +   0xCB   ; D324                  
   1.782 +   0x4F   ; D325                  
   1.783 +
   1.784 +   0xC2   ; D326                  ; if bit-1 is not 0, then
   1.785 +   0x3E   ; D327                  ; GOTO non-v-blank.
   1.786 +   0xD3   ; D328                  
   1.787 +
   1.788 +   0xCB   ; D329                  
   1.789 +   0x47   ; D32A                  
   1.790 +
   1.791 +   0xCA   ; D32B                  ; if bit-0 is not 1, then
   1.792 +   0x3E   ; D32C                  ; GOTO non-v-blank.
   1.793 +   0xD3   ; D32D                  
   1.794 +
   1.795 +   ;; V-Blank
   1.796 +   ;;   Activate state-machine if this is a transition event.
   1.797 +
   1.798 +   0xFA   ; D32E                  ; load v-bank-prev into A
   1.799 +   0x20   ; D32F                  
   1.800 +   0xD3   ; D330                  
   1.801 +
   1.802 +   0xFE   ; D331                  ; compare A to 0. >--------\ 
   1.803 +   0x00   ; D332                                              \
   1.804 +                                  ;                           |
   1.805 +   ;;   set v-blank-prev to 1.                                |
   1.806 +   0x3E   ; D333                  ; load 1 into A.            |
   1.807 +   0x01   ; D334                                              | 
   1.808 +                                  ;                           |
   1.809 +   0xEA   ; D335                  ; load A into v-blank-prev  |
   1.810 +   0x20   ; D336                                              |
   1.811 +   0xD3   ; D337                                              |
   1.812 +                                  ;                           /
   1.813 +   ;;   if v-blank-prev was 0, activate state-machine <------/
   1.814 +   0xCA   ; D338                  ; if v-blank-prev 
   1.815 +   0x46   ; D339                  ;   was 0, 
   1.816 +   0xD3   ; D33A                  ; GOTO state-machine
   1.817 +
   1.818 +   0xC3   ; D33B                  
   1.819 +   0x1D   ; D33C                  
   1.820 +   0xD3   ; D33D                  ; GOTO beginning
   1.821 +   ;; END V-blank
   1.822 +
   1.823 +   ;; Non-V-Blank
   1.824 +   ;;   Set v-blank-prev to 0
   1.825 +   0x3E   ; D33E                  ; load 0 into A
   1.826 +   0x00   ; D33F                  
   1.827 +
   1.828 +   0xEA   ; D340                  ; load A into v-blank-prev
   1.829 +   0x20   ; D341                  
   1.830 +   0xD3   ; D342
   1.831 +   
   1.832 +   0xC3   ; D343                  
   1.833 +   0x1D   ; D344                  
   1.834 +   0xD3   ; D345                  ; GOTO beginning
   1.835 +   ;; END Not-V-Blank
   1.836 +
   1.837 +   
   1.838 +   ;; Main State Machine -- Input Section
   1.839 +   ;;   This is called once every frame.
   1.840 +   ;;   It collects input and uses it to drive the
   1.841 +   ;;   state transitions.
   1.842 +
   1.843 +   ;; Increment frame-count
   1.844 +   0xFA   ; D346                  ; load frame-count into A
   1.845 +   0x1F   ; D347                  
   1.846 +   0xD3   ; D348
   1.847 +   
   1.848 +   0x3C   ; D349                  ; inc A
   1.849 +
   1.850 +   0xEA   ; D34A                  
   1.851 +   0x1F   ; D34B                  ; load A into frame-count
   1.852 +   0xD3   ; D34C
   1.853 +
   1.854 +   0x00   ; D34D                  ; glue :)
   1.855 +   
   1.856 +   0x18   ;D34E                    ;  skip next 3 bytes
   1.857 +   0x03   ;D34F
   1.858 +          ;D350
   1.859 +   (Integer/parseInt "00100000" 2) ;  select directional pad
   1.860 +          ;D351
   1.861 +   (Integer/parseInt "00010000" 2) ;  select buttons
   1.862 +   0x00   ;D352                    ;  input-number
   1.863 +
   1.864 +   ;; select directional pad; store low bits in B
   1.865 +   
   1.866 +   0xFA   ;D353                    ; load (D350) into A
   1.867 +   0x50   ;D354      -->       
   1.868 +   0xD3   ;D355      -->  D350     
   1.869 +   
   1.870 +   0xE0   ;D356                    ; load (A), which is 
   1.871 +   0x00   ;D357      -->           ; 00010000, into FF00
   1.872 +   0x00   ;D358      -->  FF00     ;; NO-OP
   1.873 +
   1.874 +   0x06   ;D359
   1.875 +          ;D35A
   1.876 +   (Integer/parseInt "11110000" 2) ; "11110000" -> B 
   1.877 +   0xF0   ;D35B                    ; (FF00) -> A
   1.878 +   0x00   ;D35C                   
   1.879 +   0x00   ;D35D                    ;; NO-OP
   1.880 +
   1.881 +   0xCB   ;D35E                    ; swap nybbles on A
   1.882 +   0x37   ;D35F
   1.883 +   0xA0   ;D360                    ; (AND A B) -> A
   1.884 +   0x47   ;D361                    ; A -> B
   1.885 +
   1.886 +   ;; select buttons; store bottom bits in C
   1.887 +   
   1.888 +   0xFA   ;D362                    ; load (D351) into A
   1.889 +   0x51   ;D363      -->       
   1.890 +   0xD3   ;D364      -->  D351     
   1.891 +   
   1.892 +   0xE0   ;D365                    ; load (A), which is 
   1.893 +   0x00   ;D366      -->           ; 00001000, into FF00
   1.894 +   0x00   ;D367      -->  FF00     ;; NO-OP
   1.895 +
   1.896 +   0x0E   ;D368
   1.897 +          ;D369
   1.898 +   (Integer/parseInt "00001111" 2) ; "00001111" -> C 
   1.899 +
   1.900 +   0xF0   ;D36A                    ; (FF00) -> A
   1.901 +   0x00   ;D36B                   
   1.902 +   0x00   ;D36C
   1.903 +   
   1.904 +   0xA1   ;D36D                    ; (AND A C) -> A
   1.905 +   0x4F   ;D36E                    ; A -> C
   1.906 +
   1.907 +   ;; combine the B and C registers into the input number
   1.908 +   0x79   ;D36F                    ; C -> A
   1.909 +   0xB0   ;D370                    ; (OR A B) -> A
   1.910 +   0x2F   ;D371                    ; negate A
   1.911 +
   1.912 +   0xEA   ;D372                    ; store A into input-number
   1.913 +   0x52   ;D373
   1.914 +   0xD3   ;D374
   1.915 +
   1.916 +   0x00   ;D375                  
   1.917 +   0x00   ;D376
   1.918 +   0x00   ;D377
   1.919 +   0x00   ;D378
   1.920 +   0x00   ;D379
   1.921 +   0x00   ;D37A
   1.922 +   0x00   ;D37B                   ; these are here because 
   1.923 +   0x00   ;D37C                   ; I messed up :(
   1.924 +   0x00   ;D37D
   1.925 +   0x00   ;D37E
   1.926 +   0x00   ;D37F
   1.927 +   
   1.928 +   ;; beginning of main state machine   
   1.929 +   0x18   ;D380                    ; Declaration of variables
   1.930 +   0x05   ;D381                    ;  5 variables:
   1.931 +   0x00   ;D382                    ;    current-mode
   1.932 +   0x00   ;D383                    ;    bytes-to-write
   1.933 +   0x00   ;D384                    ;    bytes-written
   1.934 +   0x00   ;D385                    ;    start-point-high
   1.935 +   0x00   ;D386                    ;    start-point-low
   1.936 +
   1.937 +
   1.938 +   ;; banch on current mode
   1.939 +   0xFA   ;D387                    ; load current-mode (0xD382)
   1.940 +   0x82   ;D388                    ; into A
   1.941 +   0xD3   ;D389
   1.942 +   0x00   ;D38A
   1.943 +
   1.944 +
   1.945 +   ;;  GOTO Mode 0 (input-mode) if current-mode is 0
   1.946 +   0xFE   ;D38B
   1.947 +   0x00   ;D38C                    ; compare A with 0x00
   1.948 +
   1.949 +   0xCA   ;D38D                    ; goto Mode 0 if A == 0
   1.950 +   0xA8   ;D38E
   1.951 +   0xD3   ;D38F
   1.952 +
   1.953 +   ;; GOTO Mode 1 (set-length) if current-mode is 1
   1.954 +   0xFE   ;D390
   1.955 +   0x01   ;D391                    ; compare A with 0x01
   1.956 +
   1.957 +   0xCA   ;D392                  
   1.958 +   0xB1   ;D393 
   1.959 +   0xD3   ;D394                    ; goto Mode 1 if A == 1
   1.960 +
   1.961 +   ;; GOTO Mode 2 (set-start-point-high) if current mode is 2
   1.962 +   0xFE   ;D395                    
   1.963 +   0x02   ;D396                    ; compare A with 0x02
   1.964 +
   1.965 +   0xCA   ;D397
   1.966 +   0xBF   ;D398
   1.967 +   0xD3   ;D399                    ; goto Mode 2 if A == 2
   1.968 +
   1.969 +   ;; GOTO Mode 3 (set-start-point-low) if current mode is 3
   1.970 +   0xFE   ;D39A
   1.971 +   0x03   ;D39B
   1.972 +
   1.973 +   0xCA   ;D39C
   1.974 +   0xCD   ;D39D
   1.975 +   0xD3   ;D39E                    ; goto Mode 3 if A == 3
   1.976 +
   1.977 +   ;; GOTO Mode 4 (write-memory) if current mode is 4
   1.978 +   0xFE   ;D39F
   1.979 +   0x04   ;D3A0
   1.980 +
   1.981 +   0xCA   ;D3A1
   1.982 +   0xDB   ;D3A2
   1.983 +   0xD3   ;D3A3
   1.984 +
   1.985 +   0x00   ;D3A4
   1.986 +   ;; End of Mode checking, goto beginning
   1.987 +   0xC3   ;D3A5
   1.988 +   0x1D   ;D3A6
   1.989 +   0xD3   ;D3A7
   1.990 +
   1.991 +
   1.992 +   ;; Mode 0 -- input-mode mode
   1.993 +   ;;     means that we are waiting for a mode, so set the mode to
   1.994 +   ;;     whatever is currently in input-number.  If nothing is
   1.995 +   ;;     entered, then the program stays in input-mode mode
   1.996 +
   1.997 +   ;;   set current-mode to input-number
   1.998 +   0xFA   ;D3A8                    ; load input-number (0xD352) 
   1.999 +   0x52   ;D3A9                    ; into A
  1.1000 +   0xD3   ;D3AA
  1.1001 +
  1.1002 +   0xEA   ;D3AB                    ; load A into current-mode
  1.1003 +   0x82   ;D3AC                    ; (0xD382)
  1.1004 +   0xD3   ;D3AD
  1.1005 +
  1.1006 +   0xC3   ;D3AE                    ; go back to beginning
  1.1007 +   0x1D   ;D3AF
  1.1008 +   0xD3   ;D3B0
  1.1009 +   ;; End Mode 0
  1.1010 +
  1.1011 +
  1.1012 +   ;; Mode 1 -- set-length mode
  1.1013 +   ;;      This is the header for writing things to memory.
  1.1014 +   ;;      User specifies the number of bytes to write.
  1.1015 +   ;;      Mode is auto advanced to Mode 2 after this mode
  1.1016 +   ;;      completes.
  1.1017 +
  1.1018 +   ;;      Set bytes left to write to input-number;
  1.1019 +   ;;      set current-mode to 0x02.
  1.1020 +   0xFA   ;D3B1                   ; load input-number (0xD352)
  1.1021 +   0x52   ;D3B2                   ; into A
  1.1022 +   0xD3   ;D3B3
  1.1023 +   
  1.1024 +   0xEA   ;D3B4                   ; load A into bytes-left-to-write
  1.1025 +   0x83   ;D3B5                   ; (0xD383)
  1.1026 +   0xD3   ;D3B6
  1.1027 +
  1.1028 +   0x3E   ;D3B7                   ; load 0x02 into A.
  1.1029 +   0x02   ;D3B8
  1.1030 +   
  1.1031 +   0xEA   ;D3B9                   ; load A to current-mode
  1.1032 +   0x82   ;D3BA                   ; advancing from Mode 1 to 
  1.1033 +   0xD3   ;D3BB                   ; Mode 2
  1.1034 +   
  1.1035 +   0xC3   ;D3BC                   ; go back to beginning
  1.1036 +   0x1D   ;D3BD
  1.1037 +   0xD3   ;D3BE
  1.1038 +   ;; End Mode 1
  1.1039 +
  1.1040 +
  1.1041 +   ;; Mode 2 -- set start-point-high mode
  1.1042 +   ;;      Middle part of the header for writing things to memory.
  1.1043 +   ;;      User specifies the start location in RAM to which 
  1.1044 +   ;;      data will be written.
  1.1045 +   ;;      Mode is auto advanced to Mode 3 after this mode completes.
  1.1046 +
  1.1047 +   ;;      Set start-point-high to input-number;
  1.1048 +   ;;      set current mode to 0x03.
  1.1049 +   0xFA   ;D3BF                   ; load input-number (0xD352)
  1.1050 +   0x52   ;D3C0                   ; into A
  1.1051 +   0xD3   ;D3C1
  1.1052 +
  1.1053 +   0xEA   ;D3C2                   ; load A into start-point-high
  1.1054 +   0x85   ;D3C3                   ; (0xD385)
  1.1055 +   0xD3   ;D3C4
  1.1056 +
  1.1057 +   0x3E   ;D3C5                   ; load 0x03 into A.
  1.1058 +   0x03   ;D3C6
  1.1059 +
  1.1060 +   0xEA   ;D3C7                   ; load A to current-mode,
  1.1061 +   0x82   ;D3C8                   ; advancing from Mode 2 to 
  1.1062 +   0xD3   ;D3C9                   ; Mode 3.
  1.1063 +   
  1.1064 +   0xC3   ;D3CA                   ; go back to beginning
  1.1065 +   0x1D   ;D3CB
  1.1066 +   0xD3   ;D3CC
  1.1067 +   ;;End Mode 2
  1.1068 +
  1.1069 +
  1.1070 +   ;; Mode 3 -- set-start-point-low mode
  1.1071 +   ;;      Final part of header for writing things to memory.
  1.1072 +   ;;      User specifies the low bytes of 16 bit start-point.
  1.1073 +
  1.1074 +   ;;      Set start-point-low to input-number;
  1.1075 +   ;;      set current mode to 0x04
  1.1076 +   0xFA   ;D3CD                   ; load input-number into A
  1.1077 +   0x52   ;D3CE                   
  1.1078 +   0xD3   ;D3CF                   
  1.1079 +
  1.1080 +   0xEA   ;D3D0                   ; load A into start-point-low
  1.1081 +   0x86   ;D3D1                   
  1.1082 +   0xD3   ;D3D2                   
  1.1083 +
  1.1084 +   0x3E   ;D3D3                   ; load 0x04 into A.
  1.1085 +   0x04   ;D3D4                   
  1.1086 +
  1.1087 +   0xEA   ;D3D5                   ; load A to current-mode,
  1.1088 +   0x82   ;D3D6                   ; advancing from Mode 3 to 
  1.1089 +   0xD3   ;D3D7                   ; Mode 4.
  1.1090 +
  1.1091 +   0xC3   ;D3D8                   ; go back to beginning
  1.1092 +   0x1D   ;D3D9                   
  1.1093 +   0xD3   ;D3DA                   
  1.1094 +   
  1.1095 +   ;; Mode 4 -- write bytes mode
  1.1096 +
  1.1097 +   ;;      This is where RAM manipulation happens.  User supplies
  1.1098 +   ;;      bytes every frame, which are written sequentially to
  1.1099 +   ;;      start-point until bytes-to-write have been written. Once
  1.1100 +   ;;      bytes-to-write have been written, the mode is reset to 0.
  1.1101 +
  1.1102 +   ;;   compare bytes-written with bytes-to-write.
  1.1103 +   ;;   if they are the same, then reset mode to 0
  1.1104 +  
  1.1105 +   0xFA   ;D3DB                   ; load bytes-to-write into A
  1.1106 +   0x83   ;D3DC
  1.1107 +   0xD3   ;D3DD
  1.1108 +
  1.1109 +   0x47   ;D3DE                   ; load A into B
  1.1110 +
  1.1111 +   0xFA   ;D3DF                   ; load bytes-written into A
  1.1112 +   0x84   ;D3E0
  1.1113 +   0xD3   ;D3E1
  1.1114 +
  1.1115 +   0xB8   ;D3E2                   ; compare A with B
  1.1116 +
  1.1117 +   0xCA   ;D3E3                   ; if they are equal, go to cleanup
  1.1118 +   0x07   ;D3E4                   
  1.1119 +   0xD4   ;D3E5                   
  1.1120 +
  1.1121 +   ;;  Write Memory Section
  1.1122 +   ;;    Write the input-number, interpreted as an 8-bit number,
  1.1123 +   ;;    into the current target register, determined by
  1.1124 +   ;;    (+ start-point bytes-written).
  1.1125 +   ;;    Then, increment bytes-written by 1.
  1.1126 +   
  1.1127 +   0xFA   ;D3E6                   ; load start-point-high into A
  1.1128 +   0x85   ;D3E7                   
  1.1129 +   0xD3   ;D3E8                   
  1.1130 +
  1.1131 +   0x67   ;D3E9                   ; load A into H
  1.1132 +
  1.1133 +   0xFA   ;D3EA                   ; load start-point-low into A
  1.1134 +   0x86   ;D3EB                   
  1.1135 +   0xD3   ;D3EC
  1.1136 +   
  1.1137 +   0x6F   ;D3ED                   ; load A into L
  1.1138 +   
  1.1139 +   0xFA   ;D3EE                   ; load bytes-written into A
  1.1140 +   0x84   ;D3EF                   
  1.1141 +   0xD3   ;D3F0                   
  1.1142 +   
  1.1143 +   0x00   ;D3F1                   ; These are here because
  1.1144 +   0x00   ;D3F2                   ; I screwed up again.
  1.1145 +   0x00   ;D3F3                   
  1.1146 +
  1.1147 +   0x85   ;D3F4                   ; add L to A; store A in L.
  1.1148 +   0x6F   ;D3F5                   
  1.1149 +
  1.1150 +   0x30   ;D3F6                   ; If the addition overflowed,
  1.1151 +   0x01   ;D3F7                   
  1.1152 +   0x24   ;D3F8                   ; increment H.
  1.1153 +
  1.1154 +   ;;   Now, HL points to the correct place in memory
  1.1155 +   
  1.1156 +   0xFA   ;D3F9                   ; load input-number into A
  1.1157 +   0x52   ;D3FA                   
  1.1158 +   0xD3   ;D3FB                   
  1.1159 +
  1.1160 +   0x77   ;D3FC                   ; load A into (HL)
  1.1161 +
  1.1162 +   0xFA   ;D3FD                   ; load bytes-written into A
  1.1163 +   0x84   ;D3FE                   
  1.1164 +   0xD3   ;D3FF                   
  1.1165 +
  1.1166 +   0x3C   ;D400                   ; increment A
  1.1167 +
  1.1168 +   0xEA   ;D401                   ; load A into bytes-written
  1.1169 +   0x84   ;D402                   
  1.1170 +   0xD3   ;D403
  1.1171 +
  1.1172 +   0xC3   ;D404                   ; go back to beginning.
  1.1173 +   0x1D   ;D405
  1.1174 +   0xD3   ;D406
  1.1175 +   ;;  End Write Memory Section
  1.1176 +
  1.1177 +   ;;  Mode 4 Cleanup Section
  1.1178 +   ;;    reset bytes-written to 0
  1.1179 +   ;;    set mode to 0
  1.1180 +   0x3E   ;D407                   ; load 0 into A
  1.1181 +   0x00   ;D408                  
  1.1182 +
  1.1183 +   0xEA   ;D409                   ; load A into bytes-written
  1.1184 +   0x84   ;D40A                   
  1.1185 +   0xD3   ;D40B                   
  1.1186 +
  1.1187 +   0xEA   ;D40C                   ; load A into current-mode
  1.1188 +   0x82   ;D40D                   
  1.1189 +   0xD3   ;D40E                   
  1.1190 +
  1.1191 +   0xC3   ;D40F                    ; go back to beginning
  1.1192 +   0x1D   ;D410
  1.1193 +   0xD3   ;D411
  1.1194 +
  1.1195 +   ;; End Mode 4
  1.1196 +   
  1.1197 +   ])
  1.1198 +
  1.1199 +
  1.1200 +
  1.1201 +(def frame-count 0xD31F)
  1.1202 +(def input 0xD352)
  1.1203 +(def current-mode      0xD382)
  1.1204 +(def bytes-to-write    0xD383)
  1.1205 +(def bytes-written     0xD384)
  1.1206 +(def start-point-high  0xD385)
  1.1207 +(def start-point-low   0xD386)
  1.1208 +
  1.1209 +
  1.1210 +
  1.1211 +(defn write-memory []
  1.1212 +  (-> (tick (mid-game))
  1.1213 +      (IE! 0) ; disable interrupts
  1.1214 +      (inject-item-assembly (write-memory-assembly))))
  1.1215 +
  1.1216 +(defn test-write-memory []
  1.1217 +  (set-state! (write-memory))
  1.1218 +  (dorun
  1.1219 +   (dotimes [_ 5000]
  1.1220 +     (view-memory (step @current-state) current-mode))))
  1.1221 +
  1.1222 +(def bytes-to-write 0xD383)
  1.1223 +(def start-point 0xD384)
  1.1224 +
  1.1225 +(defn print-blank-assembly
  1.1226 +  [start end]
  1.1227 +  (dorun
  1.1228 +   (map
  1.1229 +    #(println (format "0x00   ;%04X                   " %))
  1.1230 +    (range start end))))
  1.1231 +
  1.1232 +(defn test-mode-2 []
  1.1233 +  (->
  1.1234 +   (write-memory)
  1.1235 +   (view-memory frame-count)
  1.1236 +   (step)
  1.1237 +   (step [:a])
  1.1238 +   (step [:b])
  1.1239 +   (step [:start])
  1.1240 +   (step [])
  1.1241 +   (view-memory frame-count)))
  1.1242 +
  1.1243 +
  1.1244 +
  1.1245 +(defn dylan-test-mode
  1.1246 +  ([] (dylan-test-mode (write-mem-dyl)))
  1.1247 +  ([target-state]
  1.1248 +     (let [
  1.1249 +           v-blank-prev 54046
  1.1250 +           btn-register 65280
  1.1251 +           eggs 0xD374
  1.1252 +           ]
  1.1253 +       
  1.1254 +       (->
  1.1255 +        target-state
  1.1256 +        
  1.1257 +        (tick)
  1.1258 +        (tick)
  1.1259 +        (tick)
  1.1260 +        (tick);; jumps back to beginning
  1.1261 +        
  1.1262 +        (tick)
  1.1263 +        (tick)
  1.1264 +        (tick)
  1.1265 +        (tick)
  1.1266 +        (tick)
  1.1267 +        (tick)
  1.1268 +        (tick)
  1.1269 +        (tick)
  1.1270 +        (tick)
  1.1271 +        (tick)
  1.1272 +        (tick)
  1.1273 +        (tick)
  1.1274 +
  1.1275 +               
  1.1276 +        (tick)
  1.1277 +        (tick)
  1.1278 +        (tick)
  1.1279 +        (tick)
  1.1280 +        (tick)
  1.1281 +        (tick)
  1.1282 +        (tick)
  1.1283 +        (tick)
  1.1284 +        (tick)
  1.1285 +        (tick)
  1.1286 +        (tick)
  1.1287 +        (tick)
  1.1288 +        (tick)
  1.1289 +        (tick)
  1.1290 +        (tick)
  1.1291 +        (tick)
  1.1292 +        (tick)
  1.1293 +        (tick)
  1.1294 +        (tick)
  1.1295 +        (tick)
  1.1296 +        (tick) ;; just complemented A
  1.1297 +
  1.1298 +        (tick)
  1.1299 +        (DE! 0x1800)
  1.1300 +        (AF! 0x7700) ;; change inputs @ A
  1.1301 +        (tick)
  1.1302 +        (tick)
  1.1303 +        (tick)
  1.1304 +        (tick)
  1.1305 +        (tick)
  1.1306 +
  1.1307 +        ;;(view-memory eggs)
  1.1308 +        (tick)
  1.1309 +        (tick)
  1.1310 +        ;;(view-memory eggs)
  1.1311 +        (tick)
  1.1312 +        (tick)
  1.1313 +        (tick)
  1.1314 +        (tick)
  1.1315 +        (tick)
  1.1316 +        (tick)
  1.1317 +        (d-tick)
  1.1318 +
  1.1319 +        
  1.1320 +        ;;(view-memory btn-register) 
  1.1321 +        (view-register "A" A)
  1.1322 +        (view-register "B" B)
  1.1323 +        
  1.1324 +        ;;(view-register "C" C)
  1.1325 +        (view-register "D" D)
  1.1326 +        (view-register "E" E)
  1.1327 +        (view-register "H" H)
  1.1328 +        (view-register "L" L)
  1.1329 +        ))))
  1.1330 +  
  1.1331 +
  1.1332 +
  1.1333 +(defn drive-dylan []
  1.1334 +  (-> (write-mem-dyl)
  1.1335 +      (#(do (println "memory from 0xC00F to 0xC01F:"
  1.1336 +                     (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
  1.1337 +      (step [])
  1.1338 +      (step [])
  1.1339 +      (step [])
  1.1340 +      (step [:start])
  1.1341 +      (step [:select])
  1.1342 +      (step [:u :d])
  1.1343 +      (step [:a :b :start :select])
  1.1344 +      (step [:a])
  1.1345 +      (step [:b])
  1.1346 +      (step [:a :b])
  1.1347 +      (step [:select])
  1.1348 +      (step [])
  1.1349 +      (step [])
  1.1350 +      (step [])
  1.1351 +      (#(do (println "memory from 0xC00F to 0xC01F:"
  1.1352 +                     (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
  1.1353 +      ))
  1.1354 +
  1.1355 +(defn test-mode-4
  1.1356 +  ([] (test-mode-4 (write-memory)))
  1.1357 +  ([target-state]
  1.1358 +     (->
  1.1359 +      target-state
  1.1360 +      (#(do (println "memory from 0xC00F to 0xC01F:"
  1.1361 +                     (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
  1.1362 +      (view-memory current-mode)
  1.1363 +      (step [])
  1.1364 +      (step [])
  1.1365 +      (step [])
  1.1366 +      (#(do (println "after three steps") %))
  1.1367 +      (view-memory current-mode)
  1.1368 +
  1.1369 +      ;; Activate memory writing mode
  1.1370 +      
  1.1371 +      (#(do (println "step with [:a]") %))
  1.1372 +      (step [:a])
  1.1373 +      (view-memory current-mode)
  1.1374 +      (view-memory bytes-to-write)
  1.1375 +      (view-memory start-point-high)
  1.1376 +      (view-memory start-point-low)
  1.1377 +
  1.1378 +      ;; Specify four bytes to be written
  1.1379 +      
  1.1380 +      (#(do (println "step with [:select]")%))
  1.1381 +      (step [:select])
  1.1382 +      (view-memory current-mode)
  1.1383 +      (view-memory bytes-to-write)
  1.1384 +      (view-memory start-point-high)
  1.1385 +      (view-memory start-point-low)
  1.1386 +
  1.1387 +      ;; Specify target memory address as 0xC00F
  1.1388 +      
  1.1389 +      (#(do (println "step with [:u :d]")%))
  1.1390 +      (step [:u :d])
  1.1391 +      (view-memory current-mode)
  1.1392 +      (view-memory bytes-to-write)
  1.1393 +      (view-memory start-point-high)
  1.1394 +      (view-memory start-point-low)
  1.1395 +
  1.1396 +      (#(do (println "step with [:a :b :start :select]")%))
  1.1397 +      (step [:a :b :start :select])
  1.1398 +      (view-memory current-mode)
  1.1399 +      (view-memory bytes-to-write)
  1.1400 +      (view-memory start-point-high)
  1.1401 +      (view-memory start-point-low)
  1.1402 +
  1.1403 +      ;; Start reprogramming memory
  1.1404 +
  1.1405 +      (#(do (println "step with [:a]")%))
  1.1406 +      (step [:a])
  1.1407 +      (view-memory current-mode)
  1.1408 +      (view-memory bytes-written)
  1.1409 +
  1.1410 +      (#(do (println "step with [:b]")%))
  1.1411 +      (step [:b])
  1.1412 +      (view-memory current-mode)
  1.1413 +      (view-memory bytes-written)
  1.1414 +
  1.1415 +      (#(do (println "step with [:a :b]")%))
  1.1416 +      (step [:a :b])
  1.1417 +      (view-memory current-mode)
  1.1418 +      (view-memory bytes-written)
  1.1419 +
  1.1420 +      (#(do (println "step with [:select]")%))
  1.1421 +      (step [:select])
  1.1422 +      (view-memory current-mode)
  1.1423 +      (view-memory bytes-written)
  1.1424 +
  1.1425 +      ;; Reprogramming done, program ready for more commands.
  1.1426 +
  1.1427 +      (#(do (println "step with []")%))
  1.1428 +      (step [])
  1.1429 +      (view-memory current-mode)
  1.1430 +      (view-memory bytes-written)
  1.1431 +      
  1.1432 +      (#(do (println "memory from 0xC00F to 0xC01F:"
  1.1433 +                     (subvec (vec (memory %)) 0xC00F 0xC01F)) %)))))
  1.1434 +