Mercurial > vba-clojure
diff clojure/com/aurellem/gb_driver.clj @ 87:e8855121f413
collect cruft, rename other files
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 10 Mar 2012 14:48:17 -0600 |
parents | 95cb2152d7cd |
children | 65c2854c5875 |
line wrap: on
line diff
1.1 --- a/clojure/com/aurellem/gb_driver.clj Sat Mar 10 14:24:10 2012 -0600 1.2 +++ b/clojure/com/aurellem/gb_driver.clj Sat Mar 10 14:48:17 2012 -0600 1.3 @@ -1,40 +1,140 @@ 1.4 (ns com.aurellem.gb-driver 1.5 - (:import com.aurellem.gb.Gb) 1.6 - (:import java.io.File) 1.7 - (:import org.apache.commons.io.FileUtils) 1.8 - (:import (java.nio IntBuffer ByteOrder))) 1.9 + (:import com.aurellem.gb.Gb) 1.10 + (:import java.io.File) 1.11 + (:import org.apache.commons.io.FileUtils) 1.12 + (:import (java.nio IntBuffer ByteOrder))) 1.13 1.14 -(Gb/loadVBA) 1.15 - 1.16 -(def ^:dynamic *max-history* 2e4) 1.17 - 1.18 -(def ^:dynamic *backup-saves-to-disk* true) 1.19 - 1.20 -(def ^:dynamic *save-history* true) 1.21 +;; Savestates 1.22 +(defrecord SaveState [frame data]) 1.23 1.24 (def ^:dynamic *save-state-cache* 1.25 (File. "/home/r/proj/pokemon-escape/save-states/")) 1.26 1.27 +(defn frame->filename [frame] 1.28 + (File. *save-state-cache* (format "%07d.sav" frame))) 1.29 + 1.30 +(defn write-save! [^SaveState save] 1.31 + (let [buf (:data save) 1.32 + bytes (byte-array (.limit buf)) 1.33 + dest (frame->filename (:frame save))] 1.34 + (.get buf bytes) 1.35 + (FileUtils/writeByteArrayToFile dest bytes) 1.36 + (.rewind buf) 1.37 + save)) 1.38 + 1.39 +(defn read-save [frame] 1.40 + (let [save (frame->filename frame)] 1.41 + (if (.exists save) 1.42 + (let [buf (Gb/saveBuffer) 1.43 + bytes (FileUtils/readFileToByteArray save)] 1.44 + (.put buf bytes) 1.45 + (.flip buf) 1.46 + (SaveState. frame buf))))) 1.47 +;;;;;;;;;;;;;;;; 1.48 + 1.49 +;; Gameboy management 1.50 +(Gb/loadVBA) 1.51 + 1.52 (def yellow-rom-image 1.53 (File. "/home/r/proj/pokemon-escape/roms/yellow.gbc")) 1.54 1.55 (def yellow-save-file 1.56 (File. "/home/r/proj/pokemon-escape/roms/yellow.sav")) 1.57 1.58 -(def current-frame (atom 0)) 1.59 +(def on? (atom nil)) 1.60 1.61 -(defn vba-init [] 1.62 - (reset! current-frame 0) 1.63 +(defn shutdown! [] (Gb/shutdown) (reset! on? false)) 1.64 + 1.65 +(defn restart! [] 1.66 + (shutdown!) 1.67 (.delete yellow-save-file) 1.68 - (Gb/startEmulator (.getCanonicalPath yellow-rom-image))) 1.69 + (Gb/startEmulator (.getCanonicalPath yellow-rom-image)) 1.70 + (reset! on? true)) 1.71 1.72 -(defn shutdown [] (Gb/shutdown)) 1.73 +;;; The first state! 1.74 +(defn gen-root! [] 1.75 + (restart!) 1.76 + (write-save! (SaveState. 0 (Gb/saveState)))) 1.77 1.78 -(defn reset [] (shutdown) (vba-init)) 1.79 +(defn root [] 1.80 + (if (.exists (frame->filename 0)) 1.81 + (read-save 0) 1.82 + (gen-root!))) 1.83 + 1.84 +;;;; Press Buttons 1.85 + 1.86 +(def button-code 1.87 + {;; main buttons 1.88 + :a 0x0001 1.89 + :b 0x0002 1.90 + 1.91 + ;; directional pad 1.92 + :r 0x0010 1.93 + :l 0x0020 1.94 + :u 0x0040 1.95 + :d 0x0080 1.96 + 1.97 + ;; meta buttons 1.98 + :select 0x0004 1.99 + :start 0x0008 1.100 + 1.101 + ;; pseudo-buttons 1.102 + :restart 0x0800 ; hard reset 1.103 + :listen -1 ; listen for user input 1.104 + }) 1.105 + 1.106 +(defn button-mask [buttons] 1.107 + (reduce bit-or 0x0000 (map button-code buttons))) 1.108 + 1.109 +(def current-state (atom nil)) 1.110 + 1.111 + 1.112 +(defn set-state! [^SaveState state] 1.113 + (assert (:data state) "Not a valid state!") 1.114 + (if (not @on?) (restart!)) 1.115 + (if (not= @current-state state) 1.116 + (Gb/loadState (:data state))) 1.117 + (reset! current-state state)) 1.118 + 1.119 +(defrecord Move [keys state]) 1.120 + 1.121 +(defn step 1.122 + ([^SaveState state buttons] 1.123 + (set-state! state) 1.124 + (Gb/step (button-mask buttons)) 1.125 + (reset! current-state 1.126 + (SaveState. (inc (:frame state))(Gb/saveState)))) 1.127 + ([^SaveState state] 1.128 + (step state [:listen])) 1.129 + ([] (step (if @current-state @current-state (root))))) 1.130 + 1.131 +(defn move 1.132 + [^Move move buttons] 1.133 + (Move. (step (:state move) buttons) buttons)) 1.134 + 1.135 + 1.136 +(defn play 1.137 + ([^SaveState state n] 1.138 + (reduce (fn [s _] (step s)) state (range n))) 1.139 + ([n] 1.140 + (play @current-state n))) 1.141 + 1.142 +(defn play-moves 1.143 + ([moves [prev state]] 1.144 + (set-state! state) 1.145 + (dorun (map (fn [move] (step @current-state move)) moves)) 1.146 + [(concat prev moves) @current-state])) 1.147 + 1.148 +;;;;;;;;;;; 1.149 + 1.150 + 1.151 +;;;;;;;;;;;;;;; CPU data 1.152 + 1.153 + 1.154 1.155 (defn cpu-data [size arr-fn] 1.156 (let [store (int-array size)] 1.157 - (fn [] (arr-fn store) store))) 1.158 + (fn [state] (set-state! state) (arr-fn store) store))) 1.159 1.160 (def ram 1.161 (cpu-data (Gb/getRAMSize) #(Gb/getRAM %))) 1.162 @@ -51,156 +151,25 @@ 1.163 (def registers 1.164 (cpu-data Gb/NUM_REGISTERS #(Gb/getRegisters %))) 1.165 1.166 -(def button-code 1.167 - {;; main buttons 1.168 - :a 0x0001 1.169 - :b 0x0002 1.170 +;; TODO add register names 1.171 1.172 - ;; directional pad 1.173 - :r 0x0010 1.174 - :l 0x0020 1.175 - :u 0x0040 1.176 - :d 0x0080 1.177 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1.178 1.179 - ;; meta buttons 1.180 - :select 0x0004 1.181 - :start 0x0008 1.182 +(defn AF [state] 1.183 + (nth (registers state) 2)) 1.184 1.185 - ;; hard reset -- not really a button 1.186 - :reset 0x0800}) 1.187 +(defn BC [state] 1.188 + (nth (registers state) 3)) 1.189 1.190 -(defn button-mask [buttons] 1.191 - (reduce bit-or 0x0000 (map button-code buttons))) 1.192 +(defn DE [state] 1.193 + (nth (registers state) 4)) 1.194 + 1.195 +;;;;;;;;;;;;;;; 1.196 1.197 -(defn buttons [mask] 1.198 - (loop [buttons [] 1.199 - masks (seq button-code)] 1.200 - (if (empty? masks) buttons 1.201 - (let [[button value] (first masks)] 1.202 - (if (not= 0x0000 (bit-and value mask)) 1.203 - (recur (conj buttons button) (rest masks)) 1.204 - (recur buttons (rest masks))))))) 1.205 - 1.206 -(defrecord SaveState [frame save-data]) 1.207 - 1.208 -(defn frame [] @current-frame) 1.209 - 1.210 -(defn save-state [] 1.211 - (SaveState. (frame) (Gb/saveState))) 1.212 - 1.213 -(defn load-state [#^SaveState save] 1.214 - (reset! current-frame (:frame save)) 1.215 - (Gb/loadState (:save-data save))) 1.216 - 1.217 -(def empty-history (sorted-map)) 1.218 - 1.219 -(def history (atom empty-history)) 1.220 - 1.221 -(defn frame->disk-save [frame] 1.222 - (File. *save-state-cache* 1.223 - (format "%07d.sav" frame))) 1.224 - 1.225 -(defn get-save-from-disk [frame] 1.226 - (let [save (frame->disk-save frame)] 1.227 - (if (.exists save) 1.228 - (let [buf (Gb/saveBuffer) 1.229 - bytes (FileUtils/readFileToByteArray save)] 1.230 - (.put buf bytes) 1.231 - (.flip buf) 1.232 - (SaveState. frame buf))))) 1.233 - 1.234 -(defn store-save-to-disk [^SaveState save] 1.235 - (let [buf (:save-data save) 1.236 - bytes (byte-array (.limit buf)) 1.237 - dest (frame->disk-save (:frame save))] 1.238 - (.get buf bytes) 1.239 - (FileUtils/writeByteArrayToFile dest bytes) 1.240 - (.rewind buf) dest)) 1.241 - 1.242 -(defn find-save-state [frame] 1.243 - (let [save (@history frame)] 1.244 - (if (not (nil? save)) save 1.245 - (get-save-from-disk frame)))) 1.246 - 1.247 -(defn goto [frame] 1.248 - (let [save (find-save-state frame)] 1.249 - (if (nil? save) 1.250 - (println frame "is not in history") 1.251 - (do 1.252 - (reset! current-frame frame) 1.253 - (load-state save))))) 1.254 - 1.255 -(defn clear-history [] (reset! history empty-history)) 1.256 - 1.257 -(defn rewind 1.258 - ([] (rewind 1)) 1.259 - ([n] (goto (- @current-frame n)))) 1.260 - 1.261 -(defn backup-state 1.262 - ([] (backup-state (frame))) 1.263 - ([frame] 1.264 - (let [save (save-state)] 1.265 - (swap! history #(assoc % frame save)) 1.266 - ;;(store-save-to-disk save) 1.267 - (if (> (count @history) *max-history*) 1.268 - (swap! history #(dissoc % (first (first %)))))))) 1.269 - 1.270 -(defn advance [] 1.271 - (if *save-history* 1.272 - (backup-state @current-frame)) 1.273 - (swap! current-frame inc)) 1.274 - 1.275 -(defn step 1.276 - ([] (advance) (Gb/step)) 1.277 - ([mask-or-buttons] 1.278 - (advance) 1.279 - (if (number? mask-or-buttons) 1.280 - (Gb/step mask-or-buttons) 1.281 - (Gb/step (button-mask mask-or-buttons))))) 1.282 - 1.283 -(defn play-moves 1.284 - ([start moves] 1.285 - (goto start) 1.286 - (dorun (map step moves)) 1.287 - (backup-state) 1.288 - (frame)) 1.289 - ([moves] 1.290 - (dorun (map step moves)) 1.291 - (backup-state) 1.292 - (frame))) 1.293 - 1.294 -(defn play 1.295 - ([] (play Integer/MAX_VALUE)) 1.296 - ([n] (dorun (dotimes [_ n] (step))))) 1.297 - 1.298 -(defmacro without-saves [& forms] 1.299 - `(binding [*save-history* false] 1.300 - ~@forms)) 1.301 - 1.302 - 1.303 -(require '(clojure [zip :as zip])) 1.304 - 1.305 - 1.306 - 1.307 - 1.308 -(defn tree->str [original] 1.309 - (loop [s ".\n" loc (zip/down (zip/seq-zip (seq original)))] 1.310 - (if (zip/end? loc) s 1.311 - (let [d (count (zip/path loc)) 1.312 - rep 1.313 - (str 1.314 - s 1.315 - (if (and (zip/up loc) 1.316 - (> (count (-> loc zip/up zip/rights)) 0)) 1.317 - "|" "") 1.318 - (apply str (repeat (dec d) " ")) 1.319 - (if (= (count (zip/rights loc)) 0) 1.320 - "`-- " 1.321 - "|-- ") 1.322 - (zip/node loc) 1.323 - "\n")] 1.324 - (recur rep (zip/next loc)))))) 1.325 - 1.326 - 1.327 - 1.328 - 1.329 +(defmacro defn-memo 1.330 + [& forms] 1.331 + (let [fun-name (first forms)] 1.332 + `(do 1.333 + (defn ~@forms) 1.334 + (alter-var-root (var ~fun-name) memoize)))) 1.335 + 1.336 \ No newline at end of file