Mercurial > vba-clojure
diff clojure/com/aurellem/gb_driver.clj @ 106:3a60bb14a64a
better functional assembly interface; removed frame numbers from SaveStates
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Wed, 14 Mar 2012 21:37:37 -0500 |
parents | 2f8089eacab9 |
children | ad96e9464d6a |
line wrap: on
line diff
1.1 --- a/clojure/com/aurellem/gb_driver.clj Tue Mar 13 14:40:01 2012 -0500 1.2 +++ b/clojure/com/aurellem/gb_driver.clj Wed Mar 14 21:37:37 2012 -0500 1.3 @@ -5,31 +5,36 @@ 1.4 (:import (java.nio IntBuffer ByteOrder))) 1.5 1.6 ;; Savestates 1.7 -(defrecord SaveState [frame data]) 1.8 +(defrecord SaveState [data]) 1.9 1.10 (def ^:dynamic *save-state-cache* 1.11 (File. "/home/r/proj/pokemon-escape/save-states/")) 1.12 1.13 -(defn frame->filename [frame] 1.14 - (File. *save-state-cache* (format "%07d.sav" frame))) 1.15 - 1.16 -(defn write-state! [^SaveState save] 1.17 - (let [buf (:data save) 1.18 - bytes (byte-array (.limit buf)) 1.19 - dest (frame->filename (:frame save))] 1.20 - (.get buf bytes) 1.21 - (FileUtils/writeByteArrayToFile dest bytes) 1.22 - (.rewind buf) 1.23 - dest)) 1.24 +(def current-state (atom nil)) 1.25 1.26 -(defn read-state [frame] 1.27 - (let [save (frame->filename frame)] 1.28 +(defn state-cache-file [name] 1.29 + (File. *save-state-cache* (str name ".sav"))) 1.30 + 1.31 +(defn write-state! 1.32 + ([^SaveState name] 1.33 + (write-state! @current-state name)) 1.34 + ([^SaveState save ^String name] 1.35 + (let [buffer (:data save) 1.36 + bytes (byte-array (.limit buffer)) 1.37 + dest (state-cache-file name)] 1.38 + (.get buffer bytes) 1.39 + (FileUtils/writeByteArrayToFile dest bytes) 1.40 + (.rewind buffer) 1.41 + dest))) 1.42 + 1.43 +(defn read-state [name] 1.44 + (let [save (state-cache-file name)] 1.45 (if (.exists save) 1.46 - (let [buf (Gb/saveBuffer) 1.47 + (let [buffer (Gb/saveBuffer) 1.48 bytes (FileUtils/readFileToByteArray save)] 1.49 - (.put buf bytes) 1.50 - (.flip buf) 1.51 - (SaveState. frame buf))))) 1.52 + (.put buffer bytes) 1.53 + (.flip buffer) 1.54 + (SaveState. buffer))))) 1.55 ;;;;;;;;;;;;;;;; 1.56 1.57 ;; Gameboy management 1.58 @@ -54,13 +59,12 @@ 1.59 ;;; The first state! 1.60 (defn gen-root! [] 1.61 (restart!) 1.62 - (let [state (SaveState. 0 (Gb/saveState))] 1.63 - (write-state! state) 1.64 - state)) 1.65 + (let [state (SaveState. (Gb/saveState))] 1.66 + (write-state! state "root" ) state)) 1.67 1.68 (defn root [] 1.69 - (if (.exists (frame->filename 0)) 1.70 - (read-state 0) 1.71 + (if (.exists (state-cache-file "root")) 1.72 + (read-state "root") 1.73 (gen-root!))) 1.74 1.75 ;;;; Press Buttons 1.76 @@ -88,27 +92,24 @@ 1.77 (defn button-mask [buttons] 1.78 (reduce bit-or 0x0000 (map button-code buttons))) 1.79 1.80 -(def current-state (atom nil)) 1.81 - 1.82 (defn set-state! [^SaveState state] 1.83 (assert (:data state) "Not a valid state!") 1.84 (if (not @on?) (restart!)) 1.85 - (Gb/loadState (:data state)) 1.86 - (reset! current-state state)) 1.87 - 1.88 -(defrecord Move [keys state]) 1.89 + (if (not= state @current-state) 1.90 + (do 1.91 + (Gb/loadState (:data state)) 1.92 + (reset! current-state state)))) 1.93 1.94 (defn update-state [] 1.95 (reset! current-state 1.96 - (SaveState. (:frame @current-state) 1.97 - (Gb/saveState)))) 1.98 + (SaveState. (Gb/saveState)))) 1.99 1.100 (defn step 1.101 ([^SaveState state buttons] 1.102 (set-state! state) 1.103 (Gb/step (button-mask buttons)) 1.104 (reset! current-state 1.105 - (SaveState. (inc (:frame state))(Gb/saveState)))) 1.106 + (SaveState. (Gb/saveState)))) 1.107 ([^SaveState state] 1.108 (step state [:listen])) 1.109 ([] (step (if @current-state @current-state (root))))) 1.110 @@ -120,18 +121,24 @@ 1.111 (Gb/tick) 1.112 (update-state))) 1.113 1.114 -(defn move 1.115 - [^Move move buttons] 1.116 - (Move. (step (:state move) buttons) buttons)) 1.117 - 1.118 (defn play 1.119 ([^SaveState state n] 1.120 - (reduce (fn [s _] (step s)) state (range n))) 1.121 + (try 1.122 + (set-state! state) 1.123 + (dorun (dotimes [_ n] 1.124 + (Thread/sleep 1) 1.125 + (Gb/step))) 1.126 + 1.127 + (finally 1.128 + (update-state)))) 1.129 ([n] 1.130 (play @current-state n))) 1.131 1.132 -(defn continue! [] 1.133 - (play @current-state Integer/MAX_VALUE)) 1.134 +(defn continue! 1.135 + ([state] 1.136 + (play state Integer/MAX_VALUE)) 1.137 + ([] 1.138 + (continue! @current-state))) 1.139 1.140 (defn play-moves 1.141 ([moves [prev state]] 1.142 @@ -152,10 +159,16 @@ 1.143 (set-state! state) (arr-fn store) store)))) 1.144 1.145 (defn write-cpu-data [size store-fn] 1.146 - (fn [new-data] 1.147 - (let [store (int-array new-data)] 1.148 - (assert (= size (count new-data))) 1.149 - (store-fn store)))) 1.150 + (fn store-data 1.151 + ([state new-data] 1.152 + (set-state! state) 1.153 + (let [store (int-array new-data)] 1.154 + (assert (= size (count new-data))) 1.155 + (store-fn store) 1.156 + (update-state))) 1.157 + ([new-data] 1.158 + (store-data @current-state new-data)))) 1.159 + 1.160 1.161 (def memory 1.162 (cpu-data Gb/GB_MEMORY #(Gb/getMemory %)))