annotate clojure/com/aurellem/gb_funs.clj @ 86:9864032ef3c8

cleaned up code and made it to the end of the title
author Robert McIntyre <rlm@mit.edu>
date Sat, 10 Mar 2012 14:24:10 -0600
parents 3f4fdd270059
children
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@84 82 :restart 0x0800 ; hard reset
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@84 91
rlm@84 92 (defn set-state! [^SaveState state]
rlm@85 93 (assert (:data state) "Not a valid state!")
rlm@84 94 (if (not @on?) (restart!))
rlm@84 95 (if (not= @current-state state)
rlm@84 96 (Gb/loadState (:data state)))
rlm@84 97 (reset! current-state state))
rlm@84 98
rlm@84 99 (defrecord Move [keys state])
rlm@84 100
rlm@83 101 (defn step
rlm@83 102 ([^SaveState state buttons]
rlm@84 103 (set-state! state)
rlm@83 104 (Gb/step (button-mask buttons))
rlm@83 105 (reset! current-state
rlm@84 106 (SaveState. (inc (:frame state))(Gb/saveState))))
rlm@83 107 ([^SaveState state]
rlm@83 108 (step state [:listen]))
rlm@83 109 ([] (step (if @current-state @current-state (root)))))
rlm@84 110
rlm@84 111 (defn move
rlm@84 112 [^Move move buttons]
rlm@84 113 (Move. (step (:state move) buttons) buttons))
rlm@84 114
rlm@84 115
rlm@84 116 (defn play
rlm@85 117 ([^SaveState state n]
rlm@84 118 (reduce (fn [s _] (step s)) state (range n)))
rlm@85 119 ([n]
rlm@85 120 (play @current-state n)))
rlm@85 121
rlm@85 122 (defn play-moves
rlm@86 123 ([moves [prev state]]
rlm@86 124 (set-state! state)
rlm@86 125 (dorun (map (fn [move] (step @current-state move)) moves))
rlm@86 126 [(concat prev moves) @current-state]))
rlm@85 127
rlm@84 128 ;;;;;;;;;;;
rlm@84 129
rlm@84 130
rlm@84 131 ;;;;;;;;;;;;;;; CPU data
rlm@84 132
rlm@84 133
rlm@84 134
rlm@84 135 (defn cpu-data [size arr-fn]
rlm@84 136 (let [store (int-array size)]
rlm@84 137 (fn [state] (set-state! state) (arr-fn store) store)))
rlm@84 138
rlm@84 139 (def ram
rlm@84 140 (cpu-data (Gb/getRAMSize) #(Gb/getRAM %)))
rlm@84 141
rlm@84 142 (def rom
rlm@84 143 (cpu-data (Gb/getROMSize) #(Gb/getROM %)))
rlm@84 144
rlm@84 145 (def working-ram
rlm@84 146 (cpu-data Gb/WRAM_SIZE #(Gb/getWRAM %)))
rlm@84 147
rlm@84 148 (def video-ram
rlm@84 149 (cpu-data Gb/VRAM_SIZE #(Gb/getVRAM %)))
rlm@84 150
rlm@84 151 (def registers
rlm@84 152 (cpu-data Gb/NUM_REGISTERS #(Gb/getRegisters %)))
rlm@84 153
rlm@84 154 ;; TODO add register names
rlm@84 155
rlm@84 156 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
rlm@84 157
rlm@84 158 (defn AF [state]
rlm@84 159 (nth (registers state) 2))
rlm@84 160
rlm@84 161 (defn BC [state]
rlm@84 162 (nth (registers state) 3))
rlm@84 163
rlm@85 164 (defn DE [state]
rlm@85 165 (nth (registers state) 4))
rlm@84 166
rlm@86 167 ;;;;;;;;;;;;;;;
rlm@86 168
rlm@86 169 (defmacro defn-memo
rlm@86 170 [& forms]
rlm@86 171 (let [fun-name (first forms)]
rlm@86 172 `(do
rlm@86 173 (defn ~@forms)
rlm@86 174 (alter-var-root (var ~fun-name) memoize))))
rlm@84 175