Mercurial > vba-clojure
diff clojure/com/aurellem/gb_funs.clj @ 83:95cb2152d7cd
fleshing out functional gb interface
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 09 Mar 2012 19:18:00 -0600 |
parents | |
children | 26f002f2868c |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/clojure/com/aurellem/gb_funs.clj Fri Mar 09 19:18:00 2012 -0600 1.3 @@ -0,0 +1,104 @@ 1.4 +(ns com.aurellem.gb-funs 1.5 + (:import com.aurellem.gb.Gb) 1.6 + (:import java.io.File) 1.7 + (:import org.apache.commons.io.FileUtils) 1.8 + (:import (java.nio IntBuffer ByteOrder))) 1.9 + 1.10 +;; Savestates 1.11 +(defrecord SaveState [frame data]) 1.12 + 1.13 +(def ^:dynamic *save-state-cache* 1.14 + (File. "/home/r/proj/pokemon-escape/save-states/")) 1.15 + 1.16 +(defn frame->filename [frame] 1.17 + (File. *save-state-cache* (format "%07d.sav" frame))) 1.18 + 1.19 +(defn write-save! [^SaveState save] 1.20 + (let [buf (:data save) 1.21 + bytes (byte-array (.limit buf)) 1.22 + dest (frame->filename (:frame save))] 1.23 + (.get buf bytes) 1.24 + (FileUtils/writeByteArrayToFile dest bytes) 1.25 + (.rewind buf) 1.26 + save)) 1.27 + 1.28 +(defn read-save [frame] 1.29 + (let [save (frame->filename frame)] 1.30 + (if (.exists save) 1.31 + (let [buf (Gb/saveBuffer) 1.32 + bytes (FileUtils/readFileToByteArray save)] 1.33 + (.put buf bytes) 1.34 + (.flip buf) 1.35 + (SaveState. frame buf))))) 1.36 +;;;;;;;;;;;;;;;; 1.37 + 1.38 +;; Gameboy management 1.39 +(Gb/loadVBA) 1.40 + 1.41 +(def yellow-rom-image 1.42 + (File. "/home/r/proj/pokemon-escape/roms/yellow.gbc")) 1.43 + 1.44 +(def yellow-save-file 1.45 + (File. "/home/r/proj/pokemon-escape/roms/yellow.sav")) 1.46 + 1.47 +(def on? (atom nil)) 1.48 + 1.49 +(defn shutdown! [] (Gb/shutdown) (reset! on? false)) 1.50 + 1.51 +(defn restart! [] 1.52 + (shutdown!) 1.53 + (.delete yellow-save-file) 1.54 + (Gb/startEmulator (.getCanonicalPath yellow-rom-image)) 1.55 + (reset! on? true)) 1.56 + 1.57 +;;; The first state! 1.58 +(defn gen-root! [] 1.59 + (restart!) 1.60 + (write-save! (SaveState. 0 (Gb/saveState)))) 1.61 + 1.62 +(defn root [] 1.63 + (if (.exists (frame->filename 0)) 1.64 + (read-save 0) 1.65 + (gen-root!))) 1.66 + 1.67 +;;;; Press Buttons 1.68 + 1.69 +(def button-code 1.70 + {;; main buttons 1.71 + :a 0x0001 1.72 + :b 0x0002 1.73 + 1.74 + ;; directional pad 1.75 + :r 0x0010 1.76 + :l 0x0020 1.77 + :u 0x0040 1.78 + :d 0x0080 1.79 + 1.80 + ;; meta buttons 1.81 + :select 0x0004 1.82 + :start 0x0008 1.83 + 1.84 + ;; pseudo-buttons 1.85 + :restart 0x0800 ; hard reset -- not really a button 1.86 + :listen -1 ; listen for user input 1.87 + }) 1.88 + 1.89 +(defn button-mask [buttons] 1.90 + (reduce bit-or 0x0000 (map button-code buttons))) 1.91 + 1.92 +(def current-state (atom nil)) 1.93 + 1.94 +(defn step 1.95 + ([^SaveState state buttons] 1.96 + (if (not @on?) (restart!)) 1.97 + (if (not= @current-state state) 1.98 + (Gb/loadState (:data state))) 1.99 + (Gb/step (button-mask buttons)) 1.100 + (reset! current-state 1.101 + (SaveState. (inc (:frame state))(Gb/saveState))))) 1.102 + 1.103 +(defn play 1.104 + ([^SaveState state] 1.105 + (step state [:listen])) 1.106 + ([] (step (if @current-state @current-state (root))))) 1.107 +