diff clojure/com/aurellem/gb/dylan_assembly.clj @ 239:19fd38fe376e

revived a functional version of Dylan's assembly.
author Robert McIntyre <rlm@mit.edu>
date Sun, 25 Mar 2012 00:38:45 -0500
parents
children 7c89fe478de4
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/clojure/com/aurellem/gb/dylan_assembly.clj	Sun Mar 25 00:38:45 2012 -0500
     1.3 @@ -0,0 +1,199 @@
     1.4 +(ns com.aurellem.gb.dylan-assembly
     1.5 +  "A much more compact version of write-memory-assembly"
     1.6 +  {:author "Dylan Holmes"}
     1.7 +  (:use (com.aurellem.gb gb-driver assembly util))
     1.8 +  (:import [com.aurellem.gb.gb_driver SaveState]))
     1.9 +
    1.10 +(defn write-memory-assembly-compact
    1.11 +  "Currently, grabs input from the user each frame."
    1.12 +  []
    1.13 +  [
    1.14 +   ;; --------- FRAME METRONOME
    1.15 +   0x18 ;; jump ahead to cleanup. first time only.
    1.16 +   0x40 ;; v-blank-prev [D31E]
    1.17 +
    1.18 +   0xFA ;; load modes into A [D31F]
    1.19 +   0x41
    1.20 +   0xFF
    1.21 +
    1.22 +   0x47 ;; A -> B
    1.23 +   0xCB ;; rotate A
    1.24 +   0x2F
    1.25 +   0x2F ;; invert A
    1.26 +
    1.27 +   0xA0
    1.28 +   0x47 ;; now B_0 contains (VB==1)
    1.29 +
    1.30 +   0xFA ;; load v-blank-prev
    1.31 +   0x1E
    1.32 +   0xD3
    1.33 +
    1.34 +   0x2F ;; complement v-blank-prev
    1.35 +   
    1.36 +   0xA0 ;; A & B --> A
    1.37 +   0x4F ;; now C_0 contains increment?
    1.38 +
    1.39 +
    1.40 +   0x78 ;; B->A
    1.41 +   0xEA ;; spit A --> vbprev
    1.42 +   0x1E
    1.43 +   0xD3
    1.44 +
    1.45 +   0xCB   ;test C_0
    1.46 +   0x41
    1.47 +   0x20   ; JUMP ahead to button input if nonzero
    1.48 +   0x02
    1.49 +   0x18   ; JUMP  back to frame metronome (D31F)
    1.50 +   0xE7
    1.51 +   
    1.52 +   ;; -------- GET BUTTON INPUT
    1.53 +
    1.54 +        ;; btw, C_0 is now 1
    1.55 +        ;; prepare to select bits
    1.56 +
    1.57 +   0x06 ;; load 0x00 into B
    1.58 +   0x00 ;; to initialize for "OR" loop
    1.59 + 
    1.60 +   0x3E ;; load 0x20 into A, to measure dpad
    1.61 +   0x20
    1.62 +
    1.63 +   
    1.64 +   0xE0 ;; load A into [FF00] ;; start of OR loop [D33C]
    1.65 +   0x00
    1.66 +   
    1.67 +   0xF0 ;; load A from [FF00]
    1.68 +   0x00
    1.69 +
    1.70 +   0xE6 ;; bitmask 00001111
    1.71 +   0x0F
    1.72 +   
    1.73 +   0xB0 ;; A or B --> A
    1.74 +   0xCB
    1.75 +   0x41 ;; test bit 0 of C
    1.76 +   0x28 ;; JUMP forward if 0
    1.77 +   0x08
    1.78 +
    1.79 +   0x47 ;; A -> B
    1.80 +   0xCB ;; swap B nybbles
    1.81 +   0x30 
    1.82 +   0x0C ;; increment C
    1.83 +   0x3E ;; load 0x10 into A, to measure btns
    1.84 +   0x10
    1.85 +   0x18 ;; JUMP back to "load A into [FF00]" [20 steps?]
    1.86 +   0xED
    1.87 +
    1.88 +
    1.89 +   ;; ------ TAKE ACTION BASED ON USER INPUT
    1.90 +
    1.91 +   ;; "input mode"
    1.92 +   ;; mode 0x00 : select mode
    1.93 +   ;; mode 0x08 : select bytes-to-write
    1.94 +   ;; mode 0x10 : select hi-bit
    1.95 +   ;; mode 0x18 : select lo-bit
    1.96 +
    1.97 +   ;; "output mode"
    1.98 +   ;; mode 0x20 : write bytes
    1.99 +   ;; mode 0xFF : jump PC
   1.100 +
   1.101 +
   1.102 +   ;; registers
   1.103 +   ;; D : mode select
   1.104 +   ;; E : count of bytes to write
   1.105 +   ;; H : address-high
   1.106 +   ;; L : address-low
   1.107 +   
   1.108 +   ;; now A contains the pressed keys
   1.109 +   0x2F ; complement A, by request. [D34F]
   1.110 +   
   1.111 +   0x47 ; A->B ;; now B contains the pressed keys
   1.112 +   0x7B ; E->A ;; now A contains the count.
   1.113 +
   1.114 +   0xCB ; test bit 5 of D (are we in o/p mode?)
   1.115 +   0x6A
   1.116 +   0x28 ; if test == 0, skip this o/p section
   1.117 +   0x13 ; JUMP
   1.118 +   
   1.119 +   0xCB ; else, test bit 0 of D (fragile; are we in pc mode?)
   1.120 +   0x42
   1.121 +   0x28 ; if test == 0, skip the following command
   1.122 +   0x01
   1.123 +
   1.124 +   ;; output mode I: moving the program counter
   1.125 +   0xE9 ; ** move PC to (HL)
   1.126 +
   1.127 +   ;; output mode II: writing bytes
   1.128 +   0xFE ; A compare 0. finished writing?
   1.129 +   0x00
   1.130 +   0x20 ; if we are not finished, skip cleanup
   1.131 +   0x04 ; JUMP
   1.132 +
   1.133 +   ;; CLEANUP
   1.134 +   ;; btw, A is already zero.
   1.135 +   0xAF ; zero A  [D35F]
   1.136 +   0x57 ; A->D; makes D=0.
   1.137 +   0x18 ; end of frame
   1.138 +   0xBC
   1.139 +   
   1.140 +   ;; ---- end of cleanup
   1.141 +
   1.142 +   
   1.143 +   ;; continue writing bytes
   1.144 +   0x1D ;; decrement E, the number of bytes to write [D363]
   1.145 +   0x78 ;; B->A; now A contains the pressed keys
   1.146 +   0x77 ;; copy A to (HL)
   1.147 +   0x23 ;; increment HL
   1.148 +   0x18 ;; end frame. [goto D31F]
   1.149 +   0xB6 ;; TODO: set skip length backwards
   1.150 +
   1.151 +
   1.152 +   ;; ---- end of o/p section
   1.153 +   
   1.154 +   ;; i/p mode
   1.155 +   ;; adhere to the mode discipline:
   1.156 +   ;; D must be one of 0x00 0x08 0x10 0x18.
   1.157 +
   1.158 +   0x3E ;; load the constant 57 into A. [D369]
   1.159 +   0x57
   1.160 +   0x82 ;; add the mode to A
   1.161 +   0xEA ;; store A into "thing to execute"
   1.162 +   0x74
   1.163 +   0xD3
   1.164 +
   1.165 +   0x3E ;; load the constant 8 into A
   1.166 +   0x08
   1.167 +   0x82 ;; add the mode to A
   1.168 +   
   1.169 +   0x57 ;; store the incremented mode into D
   1.170 +   0x78 ;; B->A; now A contains the pressed keys
   1.171 +   
   1.172 +   0x00 ;; var: thing to execute [D374]
   1.173 +
   1.174 +   0x18 ;; end frame
   1.175 +   0xA8])
   1.176 +
   1.177 +(defn write-mem-compact []
   1.178 +  (-> (tick (mid-game))
   1.179 +      (IE! 0)
   1.180 +      (inject-item-assembly (write-memory-assembly-compact))))
   1.181 +
   1.182 +(defn drive-compact []
   1.183 +  (-> (write-mem-compact)
   1.184 +      (#(do (println "memory from 0xC00F to 0xC01F:"
   1.185 +                     (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
   1.186 +      (step [])
   1.187 +      (step [])
   1.188 +      (step [])
   1.189 +      (step [:start])
   1.190 +      (step [:select])
   1.191 +      (step [:u :d])
   1.192 +      (step [:a :b :start :select])
   1.193 +      (step [:a])
   1.194 +      (step [:b])
   1.195 +      (step [:a :b])
   1.196 +      (step [:select])
   1.197 +      (step [])
   1.198 +      (step [])
   1.199 +      (step [])
   1.200 +      (#(do (println "memory from 0xC00F to 0xC01F:"
   1.201 +                     (subvec (vec (memory %)) 0xC00F 0xC01F)) %))))
   1.202 +