rlm@530: (ns com.aurellem.run.final-cut rlm@530: (:use (com.aurellem.gb saves gb-driver util constants rlm@530: items vbm characters money rlm@530: rlm-assembly)) rlm@530: (:use (com.aurellem.run util sound music title save-corruption rlm@530: bootstrap-0 bootstrap-1 rlm@530: ram-display rlm@530: )) rlm@530: (:require clojure.string) rlm@530: (:import [com.aurellem.gb.gb_driver SaveState]) rlm@530: (:import java.awt.image.BufferedImage) rlm@530: (:import java.io.File) rlm@530: (:import com.aurellem.gb.WaveWriter)) rlm@530: rlm@530: rlm@530: (def render-dir (File. user-home "proj/vba-clojure/render")) rlm@530: rlm@530: (defn render-files! rlm@530: ([^File target-dir initial-state moves] rlm@530: (let [ram-map-dir (File. target-dir "ram-map") rlm@530: frames-dir (File. target-dir "frames") rlm@530: audio-file (File. target-dir "audio.wav") rlm@533: _ (.mkdir target-dir) rlm@533: _ (.mkdir ram-map-dir) rlm@533: _ (.mkdir frames-dir) rlm@530: wave-writer (WaveWriter. audio-file) rlm@530: moves (vec moves)] rlm@530: (set-state! initial-state) rlm@530: (dorun rlm@530: (map rlm@530: (fn [index] rlm@530: (run-moves @current-state (vector (moves index))) rlm@530: rlm@530: ;; record audio rlm@530: (.process wave-writer (sound-bytes) rlm@530: gb-sound-format) rlm@530: rlm@530: ;; write screenshot rlm@530: (write-png! rlm@530: @current-state rlm@530: (File. frames-dir (format "%07d.png" index))) rlm@530: rlm@530: ;; write ram-image rlm@530: (write-ram-image! rlm@530: @current-state rlm@530: (File. ram-map-dir (format "%07d.png" index)))) rlm@530: (range (count moves)))) rlm@530: (.cleanup wave-writer))) rlm@530: ([initial-state moves] rlm@530: (render-files! render-dir initial-state moves)) rlm@530: ([moves] rlm@530: (render-files! (root) moves))) rlm@530: rlm@531: (defn file-names [#^File dir] rlm@531: (mapv #(.getCanonicalPath %) (next (sort (file-seq dir))))) rlm@531: rlm@531: (defn composite-frames-command rlm@532: [screenshot ram-map target move] rlm@532: (let [actual-keys (set move) rlm@532: keys [:a :b :start :select :u :d :l :r] rlm@532: button-on-name ["-size" "5x5" "xc:red"] rlm@534: button-off-name ["-size" "5x5" "xc:white"]] rlm@532: ["convert" rlm@532: "-size" "318x276" "xc:white" rlm@532: (map rlm@532: (fn [index] rlm@532: (let [position ["-geometry" rlm@532: (str "+" (+ 30 (* index 8)) rlm@532: "+" "225") "-composite"]] rlm@532: (if (actual-keys (keys index)) rlm@532: [button-on-name position] rlm@532: [button-off-name position]))) rlm@532: (range (count keys))) rlm@532: screenshot "-geometry" "+10+10" "-composite" rlm@532: ram-map "-geometry" "+180+10" "-composite" rlm@532: target])) rlm@531: rlm@531: (defn generate-composite-frames! rlm@532: [^File rendered-dir moves] rlm@532: (let [final-frames (File. rendered-dir "final") rlm@532: _ (.mkdir final-frames) rlm@532: screenshots (file-names (File. rendered-dir "frames")) rlm@532: ram-maps (file-names (File. rendered-dir "ram-map")) rlm@532: targets (map #(.getCanonicalPath rlm@532: (File. final-frames (format "%07d.bmp" %))) rlm@532: (range (count screenshots)))] rlm@532: (dorun rlm@532: (map rlm@532: (comp rlm@532: (partial apply clojure.java.shell/sh) rlm@532: flatten rlm@532: (partial apply composite-frames-command) rlm@532: (fn [a b c d] (println c) [a b c d])) rlm@532: screenshots ram-maps targets moves)))) rlm@531: rlm@532: rlm@532: (defn final-cut! [^File render-dir] rlm@532: (let [movie (File. render-dir "final.ogg") rlm@532: final (File. render-dir "final")] rlm@532: (.delete movie) rlm@532: (clojure.java.shell/sh rlm@532: "ffmpeg" "-r" "60" rlm@532: "-i" (str (.getCanonicalPath final) "/" "%07d.bmp") rlm@532: "-i" (.getCanonicalPath (File. render-dir "audio.wav")) rlm@532: "-b:a" "128k" rlm@532: "-b:v" "9000k" rlm@532: "-c:a" "libvorbis" rlm@532: "-c:v" "libtheora" rlm@532: (.getCanonicalPath movie)) nil)) rlm@532: rlm@531: rlm@532: (comment rlm@531: rlm@532: ;; step 1 rlm@532: rlm@532: (render-files! rlm@532: render-dir (root) rlm@532: (take 9000 (first (control-checkpoint)))) rlm@531: rlm@532: ;; step 2 rlm@532: rlm@532: (generate-composite-frames! rlm@532: render-dir rlm@532: (take 9000 (first (control-checkpoint)))) rlm@532: rlm@532: ;; step 3 rlm@532: (final-cut! render-dir) rlm@532: )