changeset 83:95cb2152d7cd

fleshing out functional gb interface
author Robert McIntyre <rlm@mit.edu>
date Fri, 09 Mar 2012 19:18:00 -0600
parents 04d539d26bdc
children 26f002f2868c
files clojure/com/aurellem/gb_driver.clj clojure/com/aurellem/gb_funs.clj java/src/com/aurellem/gb/Gb.java src/clojure/clojure.cpp
diffstat 4 files changed, 138 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/clojure/com/aurellem/gb_driver.clj	Fri Mar 09 13:24:02 2012 -0600
     1.2 +++ b/clojure/com/aurellem/gb_driver.clj	Fri Mar 09 19:18:00 2012 -0600
     1.3 @@ -177,3 +177,30 @@
     1.4    `(binding [*save-history* false]
     1.5       ~@forms))
     1.6  
     1.7 +
     1.8 +(require '(clojure [zip :as zip]))
     1.9 +
    1.10 +
    1.11 +
    1.12 +
    1.13 +(defn tree->str [original]
    1.14 +  (loop [s ".\n" loc (zip/down (zip/seq-zip (seq original)))]
    1.15 +    (if (zip/end? loc) s
    1.16 +        (let [d (count (zip/path loc))
    1.17 +	      rep
    1.18 +              (str
    1.19 +               s
    1.20 +               (if (and (zip/up loc)
    1.21 +                        (> (count (-> loc zip/up zip/rights)) 0))
    1.22 +                 "|" "")
    1.23 +               (apply str (repeat (dec d) "   "))
    1.24 +               (if (= (count (zip/rights loc)) 0)
    1.25 +                 "`-- "
    1.26 +                 "|-- ")
    1.27 +               (zip/node loc)
    1.28 +               "\n")]
    1.29 +          (recur rep (zip/next loc))))))
    1.30 +
    1.31 +
    1.32 +
    1.33 +
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/clojure/com/aurellem/gb_funs.clj	Fri Mar 09 19:18:00 2012 -0600
     2.3 @@ -0,0 +1,104 @@
     2.4 +(ns com.aurellem.gb-funs
     2.5 +    (:import com.aurellem.gb.Gb)
     2.6 +    (:import java.io.File)
     2.7 +    (:import org.apache.commons.io.FileUtils)
     2.8 +    (:import (java.nio IntBuffer ByteOrder)))
     2.9 +
    2.10 +;; Savestates
    2.11 +(defrecord SaveState [frame data])
    2.12 +
    2.13 +(def ^:dynamic *save-state-cache*
    2.14 +  (File. "/home/r/proj/pokemon-escape/save-states/"))
    2.15 +
    2.16 +(defn frame->filename [frame]
    2.17 +  (File. *save-state-cache* (format "%07d.sav" frame)))
    2.18 +  
    2.19 +(defn write-save! [^SaveState save]
    2.20 +  (let [buf (:data save)
    2.21 +        bytes (byte-array (.limit buf))
    2.22 +        dest (frame->filename (:frame save))]
    2.23 +    (.get buf bytes)
    2.24 +    (FileUtils/writeByteArrayToFile dest bytes)
    2.25 +    (.rewind buf)
    2.26 +    save))
    2.27 +
    2.28 +(defn read-save [frame]
    2.29 +  (let [save (frame->filename frame)]
    2.30 +    (if (.exists save)
    2.31 +      (let [buf (Gb/saveBuffer)
    2.32 +            bytes (FileUtils/readFileToByteArray save)]
    2.33 +        (.put buf bytes)
    2.34 +        (.flip buf)
    2.35 +        (SaveState. frame buf)))))
    2.36 +;;;;;;;;;;;;;;;;
    2.37 +
    2.38 +;; Gameboy management
    2.39 +(Gb/loadVBA)
    2.40 +
    2.41 +(def yellow-rom-image
    2.42 +  (File. "/home/r/proj/pokemon-escape/roms/yellow.gbc"))
    2.43 +
    2.44 +(def yellow-save-file
    2.45 +  (File. "/home/r/proj/pokemon-escape/roms/yellow.sav"))
    2.46 +
    2.47 +(def on? (atom nil))
    2.48 +
    2.49 +(defn shutdown! [] (Gb/shutdown) (reset! on? false))
    2.50 +
    2.51 +(defn restart! []
    2.52 +  (shutdown!)
    2.53 +  (.delete yellow-save-file)
    2.54 +  (Gb/startEmulator (.getCanonicalPath yellow-rom-image))
    2.55 +  (reset! on? true))
    2.56 +
    2.57 +;;; The first state!
    2.58 +(defn gen-root! []
    2.59 +  (restart!)
    2.60 +  (write-save! (SaveState. 0  (Gb/saveState))))
    2.61 +
    2.62 +(defn root []
    2.63 +  (if (.exists (frame->filename 0))
    2.64 +    (read-save 0)
    2.65 +    (gen-root!)))
    2.66 +
    2.67 +;;;; Press Buttons
    2.68 +
    2.69 +(def button-code
    2.70 +  {;; main buttons
    2.71 +   :a         0x0001
    2.72 +   :b         0x0002
    2.73 +
    2.74 +   ;; directional pad
    2.75 +   :r         0x0010
    2.76 +   :l         0x0020
    2.77 +   :u         0x0040
    2.78 +   :d         0x0080
    2.79 +
    2.80 +   ;; meta buttons
    2.81 +   :select    0x0004
    2.82 +   :start     0x0008
    2.83 +
    2.84 +   ;; pseudo-buttons
    2.85 +   :restart   0x0800 ; hard reset -- not really a button
    2.86 +   :listen -1        ; listen for user input
    2.87 +   })
    2.88 +
    2.89 +(defn button-mask [buttons]
    2.90 +  (reduce bit-or 0x0000 (map button-code buttons)))
    2.91 +
    2.92 +(def current-state (atom nil))
    2.93 +
    2.94 +(defn step
    2.95 +  ([^SaveState state buttons]
    2.96 +     (if (not @on?) (restart!))
    2.97 +     (if (not= @current-state state)
    2.98 +       (Gb/loadState (:data state)))
    2.99 +     (Gb/step (button-mask buttons))
   2.100 +     (reset! current-state 
   2.101 +             (SaveState. (inc (:frame state))(Gb/saveState)))))
   2.102 +
   2.103 +(defn play
   2.104 +  ([^SaveState state]
   2.105 +     (step state [:listen]))
   2.106 +  ([] (step (if @current-state @current-state (root)))))
   2.107 +  
     3.1 --- a/java/src/com/aurellem/gb/Gb.java	Fri Mar 09 13:24:02 2012 -0600
     3.2 +++ b/java/src/com/aurellem/gb/Gb.java	Fri Mar 09 19:18:00 2012 -0600
     3.3 @@ -28,7 +28,11 @@
     3.4  
     3.5      public static native void step();
     3.6  
     3.7 -    public static native void step(int keymask);
     3.8 +    public static native void nstep(int keymask);
     3.9 +
    3.10 +    public static void step(int keymask){
    3.11 +	if (-1 == keymask) {step();}
    3.12 +	else {nstep(keymask);}}
    3.13  
    3.14      public static native void shutdown();
    3.15  
     4.1 --- a/src/clojure/clojure.cpp	Fri Mar 09 13:24:02 2012 -0600
     4.2 +++ b/src/clojure/clojure.cpp	Fri Mar 09 19:18:00 2012 -0600
     4.3 @@ -46,7 +46,7 @@
     4.4   * Method:    step
     4.5   * Signature: ()V
     4.6   */
     4.7 -JNIEXPORT void JNICALL Java_com_aurellem_gb_Gb_step__
     4.8 +JNIEXPORT void JNICALL Java_com_aurellem_gb_Gb_step
     4.9  (JNIEnv *env, jclass clazz){
    4.10    step();
    4.11  }
    4.12 @@ -56,7 +56,7 @@
    4.13   * Method:    step
    4.14   * Signature: (I)V
    4.15   */
    4.16 -JNIEXPORT void JNICALL Java_com_aurellem_gb_Gb_step__I
    4.17 +JNIEXPORT void JNICALL Java_com_aurellem_gb_Gb_nstep
    4.18  (JNIEnv *env, jclass clazz, jint keymask){
    4.19    step(keymask);
    4.20  }