annotate 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
rev   line source
rlm@83 1 (ns com.aurellem.gb-funs
rlm@83 2 (:import com.aurellem.gb.Gb)
rlm@83 3 (:import java.io.File)
rlm@83 4 (:import org.apache.commons.io.FileUtils)
rlm@83 5 (:import (java.nio IntBuffer ByteOrder)))
rlm@83 6
rlm@83 7 ;; Savestates
rlm@83 8 (defrecord SaveState [frame data])
rlm@83 9
rlm@83 10 (def ^:dynamic *save-state-cache*
rlm@83 11 (File. "/home/r/proj/pokemon-escape/save-states/"))
rlm@83 12
rlm@83 13 (defn frame->filename [frame]
rlm@83 14 (File. *save-state-cache* (format "%07d.sav" frame)))
rlm@83 15
rlm@83 16 (defn write-save! [^SaveState save]
rlm@83 17 (let [buf (:data save)
rlm@83 18 bytes (byte-array (.limit buf))
rlm@83 19 dest (frame->filename (:frame save))]
rlm@83 20 (.get buf bytes)
rlm@83 21 (FileUtils/writeByteArrayToFile dest bytes)
rlm@83 22 (.rewind buf)
rlm@83 23 save))
rlm@83 24
rlm@83 25 (defn read-save [frame]
rlm@83 26 (let [save (frame->filename frame)]
rlm@83 27 (if (.exists save)
rlm@83 28 (let [buf (Gb/saveBuffer)
rlm@83 29 bytes (FileUtils/readFileToByteArray save)]
rlm@83 30 (.put buf bytes)
rlm@83 31 (.flip buf)
rlm@83 32 (SaveState. frame buf)))))
rlm@83 33 ;;;;;;;;;;;;;;;;
rlm@83 34
rlm@83 35 ;; Gameboy management
rlm@83 36 (Gb/loadVBA)
rlm@83 37
rlm@83 38 (def yellow-rom-image
rlm@83 39 (File. "/home/r/proj/pokemon-escape/roms/yellow.gbc"))
rlm@83 40
rlm@83 41 (def yellow-save-file
rlm@83 42 (File. "/home/r/proj/pokemon-escape/roms/yellow.sav"))
rlm@83 43
rlm@83 44 (def on? (atom nil))
rlm@83 45
rlm@83 46 (defn shutdown! [] (Gb/shutdown) (reset! on? false))
rlm@83 47
rlm@83 48 (defn restart! []
rlm@83 49 (shutdown!)
rlm@83 50 (.delete yellow-save-file)
rlm@83 51 (Gb/startEmulator (.getCanonicalPath yellow-rom-image))
rlm@83 52 (reset! on? true))
rlm@83 53
rlm@83 54 ;;; The first state!
rlm@83 55 (defn gen-root! []
rlm@83 56 (restart!)
rlm@83 57 (write-save! (SaveState. 0 (Gb/saveState))))
rlm@83 58
rlm@83 59 (defn root []
rlm@83 60 (if (.exists (frame->filename 0))
rlm@83 61 (read-save 0)
rlm@83 62 (gen-root!)))
rlm@83 63
rlm@83 64 ;;;; Press Buttons
rlm@83 65
rlm@83 66 (def button-code
rlm@83 67 {;; main buttons
rlm@83 68 :a 0x0001
rlm@83 69 :b 0x0002
rlm@83 70
rlm@83 71 ;; directional pad
rlm@83 72 :r 0x0010
rlm@83 73 :l 0x0020
rlm@83 74 :u 0x0040
rlm@83 75 :d 0x0080
rlm@83 76
rlm@83 77 ;; meta buttons
rlm@83 78 :select 0x0004
rlm@83 79 :start 0x0008
rlm@83 80
rlm@83 81 ;; pseudo-buttons
rlm@83 82 :restart 0x0800 ; hard reset -- not really a button
rlm@83 83 :listen -1 ; listen for user input
rlm@83 84 })
rlm@83 85
rlm@83 86 (defn button-mask [buttons]
rlm@83 87 (reduce bit-or 0x0000 (map button-code buttons)))
rlm@83 88
rlm@83 89 (def current-state (atom nil))
rlm@83 90
rlm@83 91 (defn step
rlm@83 92 ([^SaveState state buttons]
rlm@83 93 (if (not @on?) (restart!))
rlm@83 94 (if (not= @current-state state)
rlm@83 95 (Gb/loadState (:data state)))
rlm@83 96 (Gb/step (button-mask buttons))
rlm@83 97 (reset! current-state
rlm@83 98 (SaveState. (inc (:frame state))(Gb/saveState)))))
rlm@83 99
rlm@83 100 (defn play
rlm@83 101 ([^SaveState state]
rlm@83 102 (step state [:listen]))
rlm@83 103 ([] (step (if @current-state @current-state (root)))))
rlm@83 104