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 %)))