Mercurial > vba-clojure
view clojure/com/aurellem/gb/vbm.clj @ 340:dea7e476eba7
preliminary item-writer complete
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sun, 08 Apr 2012 04:10:49 -0500 |
parents | 25b7bb7da3b1 |
children | c8cda378e1a0 |
line wrap: on
line source
1 (ns com.aurellem.gb.vbm2 (:import java.io.File)3 (:import org.apache.commons.io.FileUtils)4 (:use com.aurellem.gb.gb-driver))6 ;;;;;;;;;;;;; read vbm file8 (def ^:dynamic *moves-cache*9 (File. user-home "proj/vba-clojure/moves/"))11 (defn buttons [mask]12 (loop [buttons []13 masks (seq (dissoc button-code :listen))]14 (if (empty? masks) buttons15 (let [[button value] (first masks)]16 (if (not= 0x0000 (bit-and value mask))17 (recur (conj buttons button) (rest masks))18 (recur buttons (rest masks)))))))20 (defn vbm-bytes [#^File vbm]21 (let [bytes (FileUtils/readFileToByteArray vbm)22 ints (int-array (count bytes))]23 (areduce bytes idx _ nil24 (aset ints idx25 (bit-and 0xFF (aget bytes idx))))26 ints))28 (def vbm-header-length 255)30 (defn repair-vbm31 "Two 0's must be inserted after every reset."32 [vbm-masks]33 (loop [fixed []34 pending vbm-masks]35 (if (empty? pending) fixed36 (let [mask (first pending)]37 (if (not= 0x0000 (bit-and mask (button-code :restart)))38 (recur (conj fixed mask 0x0000 0x0000) (next pending))39 (recur (conj fixed mask) (next pending)))))))41 (defn vbm-masks [#^File vbm]42 (repair-vbm43 (map (fn [[a b]]44 (+ (bit-shift-left a 8) b))45 (partition46 2 (drop vbm-header-length (vbm-bytes vbm))))))48 (defn vbm-buttons [#^File vbm]49 (map buttons (vbm-masks vbm)))51 (defn convert-buttons52 "To write a vbm file, we must remove the last two buttons after any53 reset event."54 [buttons]55 (loop [fixed []56 pending buttons]57 (if (empty? pending) fixed58 (let [mask (first pending)]59 (if (contains? (set (first pending)) :restart)60 (recur (conj fixed mask) (drop 3 pending))61 (recur (conj fixed mask) (next pending)))))))63 (defn moves-filename [name]64 (File. *moves-cache* (format "%s.vbm" name)))66 (defn read-moves [name]67 (let [target (moves-filename name)]68 (if (.exists target)69 (vbm-buttons target))))70 ;;;;;;;;;;;;;; write moves to vbm file73 (def vbm-header74 (byte-array75 (map76 byte77 [86 66 77 26 1 0 0 0 105 74 88 79 89 1 0 0 0 0 0 0 0 1 2 112 0 0 078 0 0 0 0 0 1 0 0 0 80 79 75 69 77 79 78 32 89 69 76 76 1 -105 124 479 3 0 0 0 0 0 0 0 0 1 0 0 95 95 95 95 95 95 95 95 95 95 95 95 95 9580 95 95 82 111 98 101 114 116 32 32 77 99 73 110 116 121 114 101 9581 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 9582 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 9583 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 9584 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 9585 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 9586 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 9587 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 9588 95 95 95 95])))90 (def vbm-trailer91 (byte-array92 (map byte [0])))94 (defn buttons->vbm-bytes [buttons]95 (let [bytes-in-ints96 (map button-mask (convert-buttons buttons))97 high-bits (map #(bit-shift-right (bit-and 0xFF00 %) 8)98 bytes-in-ints)99 low-bits (map #(bit-and 0xFF %) bytes-in-ints)100 convert-byte (fn [i] (byte (if (>= i 128) (- i 256) i)))101 contents102 (byte-array103 (concat104 vbm-header105 (map convert-byte (interleave high-bits low-bits))106 vbm-trailer))]107 contents))109 (defn write-moves! [moves name]110 (let [target (moves-filename name)]111 (clojure.java.io/copy (buttons->vbm-bytes moves) target)112 target))114 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;116 (use 'clojure.java.shell)118 (def vba-linux (File. user-home "bin/vba-linux"))120 (defn play-vbm [#^File vbm]121 (.delete yellow-save-file)122 (if (.exists vbm)123 (sh (.getCanonicalPath vba-linux)124 (str "--playmovie=" (.getCanonicalPath vbm))125 (.getCanonicalPath yellow-rom-image)))126 nil)128 (defn test-moves [moves]129 (write-moves! moves "temp")130 (play-vbm (moves-filename "temp")))