Mercurial > vba-clojure
diff clojure/com/aurellem/cruft/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 | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/clojure/com/aurellem/cruft/gb_driver.clj Sat Mar 10 14:48:17 2012 -0600 1.3 @@ -0,0 +1,206 @@ 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 + 1.10 +(Gb/loadVBA) 1.11 + 1.12 +(def ^:dynamic *max-history* 2e4) 1.13 + 1.14 +(def ^:dynamic *backup-saves-to-disk* true) 1.15 + 1.16 +(def ^:dynamic *save-history* true) 1.17 + 1.18 +(def ^:dynamic *save-state-cache* 1.19 + (File. "/home/r/proj/pokemon-escape/save-states/")) 1.20 + 1.21 +(def yellow-rom-image 1.22 + (File. "/home/r/proj/pokemon-escape/roms/yellow.gbc")) 1.23 + 1.24 +(def yellow-save-file 1.25 + (File. "/home/r/proj/pokemon-escape/roms/yellow.sav")) 1.26 + 1.27 +(def current-frame (atom 0)) 1.28 + 1.29 +(defn vba-init [] 1.30 + (reset! current-frame 0) 1.31 + (.delete yellow-save-file) 1.32 + (Gb/startEmulator (.getCanonicalPath yellow-rom-image))) 1.33 + 1.34 +(defn shutdown [] (Gb/shutdown)) 1.35 + 1.36 +(defn reset [] (shutdown) (vba-init)) 1.37 + 1.38 +(defn cpu-data [size arr-fn] 1.39 + (let [store (int-array size)] 1.40 + (fn [] (arr-fn store) store))) 1.41 + 1.42 +(def ram 1.43 + (cpu-data (Gb/getRAMSize) #(Gb/getRAM %))) 1.44 + 1.45 +(def rom 1.46 + (cpu-data (Gb/getROMSize) #(Gb/getROM %))) 1.47 + 1.48 +(def working-ram 1.49 + (cpu-data Gb/WRAM_SIZE #(Gb/getWRAM %))) 1.50 + 1.51 +(def video-ram 1.52 + (cpu-data Gb/VRAM_SIZE #(Gb/getVRAM %))) 1.53 + 1.54 +(def registers 1.55 + (cpu-data Gb/NUM_REGISTERS #(Gb/getRegisters %))) 1.56 + 1.57 +(def button-code 1.58 + {;; main buttons 1.59 + :a 0x0001 1.60 + :b 0x0002 1.61 + 1.62 + ;; directional pad 1.63 + :r 0x0010 1.64 + :l 0x0020 1.65 + :u 0x0040 1.66 + :d 0x0080 1.67 + 1.68 + ;; meta buttons 1.69 + :select 0x0004 1.70 + :start 0x0008 1.71 + 1.72 + ;; hard reset -- not really a button 1.73 + :reset 0x0800}) 1.74 + 1.75 +(defn button-mask [buttons] 1.76 + (reduce bit-or 0x0000 (map button-code buttons))) 1.77 + 1.78 +(defn buttons [mask] 1.79 + (loop [buttons [] 1.80 + masks (seq button-code)] 1.81 + (if (empty? masks) buttons 1.82 + (let [[button value] (first masks)] 1.83 + (if (not= 0x0000 (bit-and value mask)) 1.84 + (recur (conj buttons button) (rest masks)) 1.85 + (recur buttons (rest masks))))))) 1.86 + 1.87 +(defrecord SaveState [frame save-data]) 1.88 + 1.89 +(defn frame [] @current-frame) 1.90 + 1.91 +(defn save-state [] 1.92 + (SaveState. (frame) (Gb/saveState))) 1.93 + 1.94 +(defn load-state [#^SaveState save] 1.95 + (reset! current-frame (:frame save)) 1.96 + (Gb/loadState (:save-data save))) 1.97 + 1.98 +(def empty-history (sorted-map)) 1.99 + 1.100 +(def history (atom empty-history)) 1.101 + 1.102 +(defn frame->disk-save [frame] 1.103 + (File. *save-state-cache* 1.104 + (format "%07d.sav" frame))) 1.105 + 1.106 +(defn get-save-from-disk [frame] 1.107 + (let [save (frame->disk-save frame)] 1.108 + (if (.exists save) 1.109 + (let [buf (Gb/saveBuffer) 1.110 + bytes (FileUtils/readFileToByteArray save)] 1.111 + (.put buf bytes) 1.112 + (.flip buf) 1.113 + (SaveState. frame buf))))) 1.114 + 1.115 +(defn store-save-to-disk [^SaveState save] 1.116 + (let [buf (:save-data save) 1.117 + bytes (byte-array (.limit buf)) 1.118 + dest (frame->disk-save (:frame save))] 1.119 + (.get buf bytes) 1.120 + (FileUtils/writeByteArrayToFile dest bytes) 1.121 + (.rewind buf) dest)) 1.122 + 1.123 +(defn find-save-state [frame] 1.124 + (let [save (@history frame)] 1.125 + (if (not (nil? save)) save 1.126 + (get-save-from-disk frame)))) 1.127 + 1.128 +(defn goto [frame] 1.129 + (let [save (find-save-state frame)] 1.130 + (if (nil? save) 1.131 + (println frame "is not in history") 1.132 + (do 1.133 + (reset! current-frame frame) 1.134 + (load-state save))))) 1.135 + 1.136 +(defn clear-history [] (reset! history empty-history)) 1.137 + 1.138 +(defn rewind 1.139 + ([] (rewind 1)) 1.140 + ([n] (goto (- @current-frame n)))) 1.141 + 1.142 +(defn backup-state 1.143 + ([] (backup-state (frame))) 1.144 + ([frame] 1.145 + (let [save (save-state)] 1.146 + (swap! history #(assoc % frame save)) 1.147 + ;;(store-save-to-disk save) 1.148 + (if (> (count @history) *max-history*) 1.149 + (swap! history #(dissoc % (first (first %)))))))) 1.150 + 1.151 +(defn advance [] 1.152 + (if *save-history* 1.153 + (backup-state @current-frame)) 1.154 + (swap! current-frame inc)) 1.155 + 1.156 +(defn step 1.157 + ([] (advance) (Gb/step)) 1.158 + ([mask-or-buttons] 1.159 + (advance) 1.160 + (if (number? mask-or-buttons) 1.161 + (Gb/step mask-or-buttons) 1.162 + (Gb/step (button-mask mask-or-buttons))))) 1.163 + 1.164 +(defn play-moves 1.165 + ([start moves] 1.166 + (goto start) 1.167 + (dorun (map step moves)) 1.168 + (backup-state) 1.169 + (frame)) 1.170 + ([moves] 1.171 + (dorun (map step moves)) 1.172 + (backup-state) 1.173 + (frame))) 1.174 + 1.175 +(defn play 1.176 + ([] (play Integer/MAX_VALUE)) 1.177 + ([n] (dorun (dotimes [_ n] (step))))) 1.178 + 1.179 +(defmacro without-saves [& forms] 1.180 + `(binding [*save-history* false] 1.181 + ~@forms)) 1.182 + 1.183 + 1.184 +(require '(clojure [zip :as zip])) 1.185 + 1.186 + 1.187 + 1.188 + 1.189 +(defn tree->str [original] 1.190 + (loop [s ".\n" loc (zip/down (zip/seq-zip (seq original)))] 1.191 + (if (zip/end? loc) s 1.192 + (let [d (count (zip/path loc)) 1.193 + rep 1.194 + (str 1.195 + s 1.196 + (if (and (zip/up loc) 1.197 + (> (count (-> loc zip/up zip/rights)) 0)) 1.198 + "|" "") 1.199 + (apply str (repeat (dec d) " ")) 1.200 + (if (= (count (zip/rights loc)) 0) 1.201 + "`-- " 1.202 + "|-- ") 1.203 + (zip/node loc) 1.204 + "\n")] 1.205 + (recur rep (zip/next loc)))))) 1.206 + 1.207 + 1.208 + 1.209 +