Mercurial > vba-clojure
diff clojure/com/aurellem/gb_driver.clj @ 76:d7c38ce83421
working on disk-backup for save-states
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Thu, 08 Mar 2012 19:48:54 -0600 |
parents | eb7d4efe0f34 |
children | 9ba461a5c60f |
line wrap: on
line diff
1.1 --- a/clojure/com/aurellem/gb_driver.clj Thu Mar 08 06:01:09 2012 -0600 1.2 +++ b/clojure/com/aurellem/gb_driver.clj Thu Mar 08 19:48:54 2012 -0600 1.3 @@ -5,6 +5,15 @@ 1.4 1.5 (Gb/loadVBA) 1.6 1.7 +(def ^:dynamic *max-history* 1e4) 1.8 + 1.9 +(def ^:dynamic *backup-saves-to-disk* true) 1.10 + 1.11 +(def ^:dynamic *save-history* true) 1.12 + 1.13 +(def ^:dynamic *save-state-cache* 1.14 + (File. "/home/r/proj/pokemon-escape/save-states/")) 1.15 + 1.16 (def yellow-rom-image 1.17 (File. "/home/r/proj/pokemon-escape/roms/yellow.gbc")) 1.18 1.19 @@ -24,9 +33,7 @@ 1.20 1.21 (defn cpu-data [size arr-fn] 1.22 (let [store (int-array size)] 1.23 - (fn [] 1.24 - (arr-fn store) 1.25 - store))) 1.26 + (fn [] (arr-fn store) store))) 1.27 1.28 (def ram 1.29 (cpu-data (Gb/getRAMSize) #(Gb/getRAM %))) 1.30 @@ -73,35 +80,74 @@ 1.31 (recur (conj buttons button) (rest masks)) 1.32 (recur buttons (rest masks))))))) 1.33 1.34 +(defrecord SaveState [frame save-data]) 1.35 1.36 -(defn save-state [] (Gb/saveState)) 1.37 +(defn frame [] @current-frame) 1.38 1.39 -(def history (atom {})) 1.40 +(defn save-state [] 1.41 + (SaveState. 1.42 + (frame) 1.43 + (Gb/saveState))) 1.44 + 1.45 +(defn load-state [#^SaveState save] 1.46 + (reset! current-frame (:frame save)) 1.47 + (Gb/loadState (:save-data save))) 1.48 + 1.49 +(def empty-history (sorted-map)) 1.50 + 1.51 +(def history (atom empty-history)) 1.52 + 1.53 +(defn frame->disk-save [frame] 1.54 + (File. *save-state-cache* 1.55 + (format "%07d.sav" frame))) 1.56 + 1.57 +(defn get-save-from-disk [frame] 1.58 + (let [save (frame->disk-save frame)] 1.59 + (if (.exists save) 1.60 + (let [buf (Gb/saveBuffer) 1.61 + bytes (org.apache.commons.io.FileUtils/readFileToByteArray 1.62 + save)] 1.63 + (.put buf bytes) 1.64 + (.flip buf) 1.65 + (SaveState. frame buf))))) 1.66 + 1.67 +(defn store-save-to-disk [^SaveState save] 1.68 + (let [buf (:save-data save) 1.69 + bytes (byte-array (.limit buf)) 1.70 + dest (frame->disk-save (:frame save))] 1.71 + (.get buf bytes) 1.72 + (org.apache.commons.io.FileUtils/writeByteArrayToFile 1.73 + dest bytes) 1.74 + (.rewind buf))) 1.75 + 1.76 +(defn find-save-state [frame] 1.77 + (let [save (@history frame)] 1.78 + (if (not (nil? save)) save 1.79 + (get-save-from-disk frame)))) 1.80 1.81 (defn goto [frame] 1.82 - (let [save (@history frame)] 1.83 - (if (not (nil? save)) 1.84 + (let [save (find-save-state frame)] 1.85 + (if (nil? save) 1.86 + (println frame "is not in history") 1.87 (do 1.88 (reset! current-frame frame) 1.89 - (Gb/loadState save)) 1.90 - (println "no backup state")))) 1.91 + (load-state save))))) 1.92 1.93 -(defn clear-history [] (reset! history {})) 1.94 +(defn clear-history [] (reset! history empty-history)) 1.95 1.96 (defn rewind 1.97 - ([n] (goto (- @current-frame n))) 1.98 - ([] (rewind 1))) 1.99 - 1.100 + ([] (rewind 1)) 1.101 + ([n] (goto (- @current-frame n)))) 1.102 + 1.103 (defn backup-state [frame] 1.104 - (swap! history #(assoc % frame (save-state)))) 1.105 - 1.106 -(def ^:dynamic *save-history* true) 1.107 + (swap! history #(assoc % frame (save-state))) 1.108 + (if (> (count @history) *max-history*) 1.109 + (swap! history #(dissoc % (first (first %)))))) 1.110 1.111 (defn advance [] 1.112 - (swap! current-frame inc) 1.113 (if *save-history* 1.114 - (let [save (save-state)] 1.115 - (backup-state @current-frame)))) 1.116 + (backup-state @current-frame)) 1.117 + (swap! current-frame inc)) 1.118 1.119 (defn step 1.120 ([] (advance) (Gb/step)) 1.121 @@ -114,7 +160,13 @@ 1.122 (defn step! [& args] 1.123 (binding [*save-history* false] 1.124 (apply step args))) 1.125 + 1.126 +(defn play 1.127 + ([n] (dorun (dotimes [_ n] (step)))) 1.128 + ([] (play Integer/MAX_VALUE))) 1.129 1.130 -(defn frame [] @current-frame) 1.131 - 1.132 - 1.133 +(defn buf-seq [buffer] 1.134 + (let [bytes (byte-array (.capacity buffer))] 1.135 + (.get buffer bytes) 1.136 + (.rewind buffer) 1.137 + (seq bytes))) 1.138 \ No newline at end of file