Mercurial > vba-clojure
comparison 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 |
comparison
equal
deleted
inserted
replaced
75:eb7d4efe0f34 | 76:d7c38ce83421 |
---|---|
2 (:import com.aurellem.gb.Gb) | 2 (:import com.aurellem.gb.Gb) |
3 (:import java.io.File) | 3 (:import java.io.File) |
4 (:import (java.nio IntBuffer ByteOrder))) | 4 (:import (java.nio IntBuffer ByteOrder))) |
5 | 5 |
6 (Gb/loadVBA) | 6 (Gb/loadVBA) |
7 | |
8 (def ^:dynamic *max-history* 1e4) | |
9 | |
10 (def ^:dynamic *backup-saves-to-disk* true) | |
11 | |
12 (def ^:dynamic *save-history* true) | |
13 | |
14 (def ^:dynamic *save-state-cache* | |
15 (File. "/home/r/proj/pokemon-escape/save-states/")) | |
7 | 16 |
8 (def yellow-rom-image | 17 (def yellow-rom-image |
9 (File. "/home/r/proj/pokemon-escape/roms/yellow.gbc")) | 18 (File. "/home/r/proj/pokemon-escape/roms/yellow.gbc")) |
10 | 19 |
11 (def yellow-save-file | 20 (def yellow-save-file |
22 | 31 |
23 (defn reset [] (shutdown) (vba-init)) | 32 (defn reset [] (shutdown) (vba-init)) |
24 | 33 |
25 (defn cpu-data [size arr-fn] | 34 (defn cpu-data [size arr-fn] |
26 (let [store (int-array size)] | 35 (let [store (int-array size)] |
27 (fn [] | 36 (fn [] (arr-fn store) store))) |
28 (arr-fn store) | |
29 store))) | |
30 | 37 |
31 (def ram | 38 (def ram |
32 (cpu-data (Gb/getRAMSize) #(Gb/getRAM %))) | 39 (cpu-data (Gb/getRAMSize) #(Gb/getRAM %))) |
33 | 40 |
34 (def rom | 41 (def rom |
71 (let [[button value] (first masks)] | 78 (let [[button value] (first masks)] |
72 (if (not= 0x0000 (bit-and value mask)) | 79 (if (not= 0x0000 (bit-and value mask)) |
73 (recur (conj buttons button) (rest masks)) | 80 (recur (conj buttons button) (rest masks)) |
74 (recur buttons (rest masks))))))) | 81 (recur buttons (rest masks))))))) |
75 | 82 |
83 (defrecord SaveState [frame save-data]) | |
76 | 84 |
77 (defn save-state [] (Gb/saveState)) | 85 (defn frame [] @current-frame) |
78 | 86 |
79 (def history (atom {})) | 87 (defn save-state [] |
88 (SaveState. | |
89 (frame) | |
90 (Gb/saveState))) | |
91 | |
92 (defn load-state [#^SaveState save] | |
93 (reset! current-frame (:frame save)) | |
94 (Gb/loadState (:save-data save))) | |
95 | |
96 (def empty-history (sorted-map)) | |
97 | |
98 (def history (atom empty-history)) | |
99 | |
100 (defn frame->disk-save [frame] | |
101 (File. *save-state-cache* | |
102 (format "%07d.sav" frame))) | |
103 | |
104 (defn get-save-from-disk [frame] | |
105 (let [save (frame->disk-save frame)] | |
106 (if (.exists save) | |
107 (let [buf (Gb/saveBuffer) | |
108 bytes (org.apache.commons.io.FileUtils/readFileToByteArray | |
109 save)] | |
110 (.put buf bytes) | |
111 (.flip buf) | |
112 (SaveState. frame buf))))) | |
113 | |
114 (defn store-save-to-disk [^SaveState save] | |
115 (let [buf (:save-data save) | |
116 bytes (byte-array (.limit buf)) | |
117 dest (frame->disk-save (:frame save))] | |
118 (.get buf bytes) | |
119 (org.apache.commons.io.FileUtils/writeByteArrayToFile | |
120 dest bytes) | |
121 (.rewind buf))) | |
122 | |
123 (defn find-save-state [frame] | |
124 (let [save (@history frame)] | |
125 (if (not (nil? save)) save | |
126 (get-save-from-disk frame)))) | |
80 | 127 |
81 (defn goto [frame] | 128 (defn goto [frame] |
82 (let [save (@history frame)] | 129 (let [save (find-save-state frame)] |
83 (if (not (nil? save)) | 130 (if (nil? save) |
131 (println frame "is not in history") | |
84 (do | 132 (do |
85 (reset! current-frame frame) | 133 (reset! current-frame frame) |
86 (Gb/loadState save)) | 134 (load-state save))))) |
87 (println "no backup state")))) | |
88 | 135 |
89 (defn clear-history [] (reset! history {})) | 136 (defn clear-history [] (reset! history empty-history)) |
90 | 137 |
91 (defn rewind | 138 (defn rewind |
92 ([n] (goto (- @current-frame n))) | 139 ([] (rewind 1)) |
93 ([] (rewind 1))) | 140 ([n] (goto (- @current-frame n)))) |
94 | 141 |
95 (defn backup-state [frame] | 142 (defn backup-state [frame] |
96 (swap! history #(assoc % frame (save-state)))) | 143 (swap! history #(assoc % frame (save-state))) |
97 | 144 (if (> (count @history) *max-history*) |
98 (def ^:dynamic *save-history* true) | 145 (swap! history #(dissoc % (first (first %)))))) |
99 | 146 |
100 (defn advance [] | 147 (defn advance [] |
101 (swap! current-frame inc) | |
102 (if *save-history* | 148 (if *save-history* |
103 (let [save (save-state)] | 149 (backup-state @current-frame)) |
104 (backup-state @current-frame)))) | 150 (swap! current-frame inc)) |
105 | 151 |
106 (defn step | 152 (defn step |
107 ([] (advance) (Gb/step)) | 153 ([] (advance) (Gb/step)) |
108 ([mask-or-buttons] | 154 ([mask-or-buttons] |
109 (advance) | 155 (advance) |
112 (Gb/step (button-mask mask-or-buttons))))) | 158 (Gb/step (button-mask mask-or-buttons))))) |
113 | 159 |
114 (defn step! [& args] | 160 (defn step! [& args] |
115 (binding [*save-history* false] | 161 (binding [*save-history* false] |
116 (apply step args))) | 162 (apply step args))) |
163 | |
164 (defn play | |
165 ([n] (dorun (dotimes [_ n] (step)))) | |
166 ([] (play Integer/MAX_VALUE))) | |
117 | 167 |
118 (defn frame [] @current-frame) | 168 (defn buf-seq [buffer] |
119 | 169 (let [bytes (byte-array (.capacity buffer))] |
120 | 170 (.get buffer bytes) |
171 (.rewind buffer) | |
172 (seq bytes))) |