Mercurial > vba-clojure
view clojure/com/aurellem/run/adv_choreo.clj @ 589:d9d86f6018e8
cleanup.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 01 Sep 2012 10:15:04 -0500 |
parents | 6e9368c371d5 |
children | ba185915c24f |
line wrap: on
line source
1 ;;;; "Advanced Choreography" -- this is the final video for this project.3 (ns com.aurellem.run.adv-choreo4 (:use (com.aurellem.gb saves gb-driver util constants5 items vbm characters money6 rlm-assembly))7 (:use (com.aurellem.run util music title save-corruption8 bootstrap-0 bootstrap-1 image9 ram-display final-cut basic-choreo))10 (:require clojure.string)11 (:import java.awt.image.BufferedImage)12 (:import (javax.imageio ImageWriteParam IIOImage ImageIO))13 (:import [com.aurellem.gb.gb_driver SaveState])14 (:import java.io.File))18 ;; Use the gameboy's screen to display the new programming19 ;; instead of a side window. This will make it look much20 ;; cooler and create a terminal-like effect as the game is21 ;; being reprogramed. To do this, use a fixed data entry22 ;; region in ram, and run a program that translates this23 ;; region into the screen. Every time this data entry region24 ;; is full, run a program that copies the data to the25 ;; appropriate region in memory. This will cost ~15 seconds26 ;; at the beginning to set up, and then should have minimal27 ;; overhead (~5%) for the rest of the data transfer, but28 ;; will have a good psychological effect for the viewer29 ;; since he can see that something is actually happening in30 ;; the game.33 ;; Symbol size and type.35 ;; use fonts from zophar's domain:36 ;; http://www.zophar.net/utilities/fonts/8x8-font-archive.html38 ;; Green font on black background for matrix look.41 (defn program-data [base-address]42 (let [image-program43 (display-image-kernel44 base-address46 pinkie-pie-mark47 ;;test-image-color48 )51 music-base-address (+ (count image-program) base-address)53 initial-music-data54 (midi-bytes pony-csv 0 0 0 0)56 data-lengths57 (map (comp count :data)58 [(:kernel initial-music-data)59 (:voice-1 initial-music-data)60 (:voice-2 initial-music-data)]);; noise not needed61 addresses62 (map (partial + music-base-address) (reductions + 0 data-lengths))64 final-music-data65 (apply (partial midi-bytes pony-csv) addresses)67 music-program68 (concat69 (:data (:kernel final-music-data))70 (:data (:voice-1 final-music-data))71 (:data (:voice-2 final-music-data))72 (:data (:noise final-music-data)))]74 (concat75 image-program ;; image program falls through to music program76 music-program)))78 (def glyphs79 "The sixteen 8x8 glyphs which make up the \"terminal\" font."80 (mapv #(ImageIO/read81 (File. user-home (str "proj/vba-clojure/font/" % ".png")))82 ["0" "1" "2" "3" "4" "5" "6" "7" "8"83 "9" "A" "B" "C" "D" "E" "F" "_"]))86 (defn glyph-init-program87 [start-address]88 (let [zero-glyph (image->gb-image (glyphs 0))90 ;; write same pallet information to all pallettes91 A (flatten92 [(write-byte LCD-control-register 0x00);; disable LCD protection93 (set-palettes bg-palette-select bg-palette-data94 (repeat 8 (first (:palettes zero-glyph))))95 (select-LCD-bank 0)96 (write-byte SCX-register 0)97 (write-byte SCY-register 0)])98 B (flatten99 [(write-data100 (+ start-address (count A))101 character-data-address102 (flatten103 (map (comp gb-tile->bytes first :tiles image->gb-image)104 glyphs)))107 (write-byte108 LCD-control-register109 (Integer/parseInt110 (str111 "1" ;; LCDC on/off112 "0" ;; Window code area113 "0" ;; Windowing on?114 "1" ;; BG tile base (1 = 0x8000)115 "0" ;; BG-1 or BG-2 ?116 "0" ;; OBJ-block composition117 "0" ;; OBJ-on flag118 "1") ;; no-effect119 2))])]120 (concat A B )))124 (defn glyph-display-program125 [start-address]126 (let [data-start (+ 2 start-address)127 load-data128 (flatten129 [;; data region130 0x18131 2132 0 0;; current row and column133 ;; save all registers134 0xC5 0xD5 0xE5 0xF5136 ;; load data from data region into registers138 0xF5 ;; push A, which contains current glyph140 0x21141 (reverse (disect-bytes-2 data-start))142 ;; load row and column into DE143 0x2A 0x57 ;; row -> D144 0x2A 0x5F ;; column -> E145 ])148 display-glyph149 (let [init*150 (flatten151 [(repeat 100 0)152 ;; Reset HL to initial value154 ;; clear screen if we are at 0,0155 0x7A 0xB3 ;; D->A, OR E A ==> (= D E 0)156 0x20 ;; skip clear-screen if D and E are not both zero157 :clear-screen-length])159 clear-screen160 (flatten161 [;; save all registers162 0xC5 0xD5 0xE5 0xF5164 (select-LCD-bank 0)165 ;; write 0x00 to memory locations166 ;; 0x9800 to 0x9A34167 0x21168 0x00 0x98 ;; load 0x9800 into HL170 0x16 3 ;; 3 -> D171 0x1E 190 ;; 188 -> E173 ;; Empty space Character ID174 0x3E 16 ;; 0-> A176 ;; begin of do-while loop177 0x22 ;; load A to 0x9800178 0x1D ;; dec E179 0x20180 (->signed-8-bit -4)181 0x15 ;; dec D182 0x1E 190 ;; 188 -> E183 0x20184 (->signed-8-bit -8)185 ;; end of do-while-loop187 ;; restore all registers188 0xF1 0xE1 0xD1 0xC1])191 increment-row-column192 [;; D contains row and E contains column194 ;; every time column (E) reaches 20, set195 ;; column to 0 and increment row196 0x1C ;; inc E197 0x3E 20 0xBB ;; compare E to 20198 0x20199 3200 0x14 ;; increment row201 0x1E 0 ;; set column to 0204 ;; if row==18, set row to 0205 0x3E 18206 0xBA207 0x20208 2209 0x16 0]211 set-HL-from-row-and-column212 (flatten213 [;; formula for memory offset is:214 ;; (+ 0x9800 (* 32 row) column) ==215 0x21 0x00 0x98 ;; load HL with 0x9800217 0x06 0218 0x4B ;; columns (E) -> BC219 0x09 ;; HL += columns222 0xAF ;; 0 -> A224 0x06 0225 0x0E 32 ;; load 32 into BC227 0xBA ;; CP A D228 0x28 ;; skip this next section if A == D229 4230 0x09 ;; HL += 32231 0x3C232 0x18234 (->signed-8-bit -7)])236 render-glyph237 (flatten238 [;; Render each nybble of A as a character239 ;; there are two characters to a glyph.241 set-HL-from-row-and-column243 0xF1 ;; pop A, now A is equal to key input244 0xF5 ;; save A246 0xE6 0xF0 ;; clear second nybble247 0xCB 0x37 ;; swap nybbles248 0x77 ;; store A in video RAM as a character (pun)249 increment-row-column252 set-HL-from-row-and-column254 0xF1 ;; restore A255 0xE6 0x0F ;; select second nybble256 0x77 ;; store second nybble as character257 increment-row-column])260 init (replace261 {:clear-screen-length (count clear-screen)} init*)262 ]264 (concat init clear-screen render-glyph))266 cleanup267 ;; restore all registers268 (flatten269 [;; Reset HL to initial data-start value270 0x21271 (reverse (disect-bytes-2 data-start))272 ;;0x23273 ;; write variables274 0x7A 0x22 ;; D -> rows -> to RAM275 0x7B 0x22 ;; E -> columns276 ])278 stack-cleanup279 [0xF1 0xE1 0xD1 0xC1]280 ]281 (concat load-data282 display-glyph283 cleanup stack-cleanup)))285 (def main-program-base-address 0xC000)287 (defn glyph-bootstrap-program288 [start-address delay-count total-glyph-count]289 (let [init [0xAF 0x4F 0x47] ;; 0->A; 0->C; 0->B290 header (concat (frame-metronome) (read-user-input))292 glyph-display (glyph-display-program293 (+ (count init)294 (count header)295 start-address))297 state-machine-start-address298 (+ start-address (count init) (count header) (count glyph-display))299 state-machine300 (bootstrap-state-machine state-machine-start-address)302 return-to-header303 (flatten304 [0xC3305 (reverse (disect-bytes-2306 (+ (count init) start-address)))])]307 (concat init header glyph-display state-machine return-to-header)))309 (defn-memo begin-glyph-bootstrap310 ([] (begin-glyph-bootstrap (launch-main-bootstrap-program)))311 ([script]312 (let [glyph-init (glyph-init-program relocated-bootstrap-start)313 main-glyph-start (+ relocated-bootstrap-start314 (count glyph-init))315 glyph-program (glyph-bootstrap-program316 main-glyph-start 0 0)]317 (->> script318 (do-nothing 2)319 ;; begin glyph program320 (write-RAM 0xFF1A [0 0 0]) ;; silence remnant music322 (write-RAM323 relocated-bootstrap-start324 (concat glyph-init glyph-program))325 (transfer-control relocated-bootstrap-start)326 (do-nothing 1)))))328 (defn write-all-program-data329 ([] (write-all-program-data (begin-glyph-bootstrap)))330 ([script]331 (let [base-address main-program-base-address]332 (->> script333 (write-RAM base-address (program-data base-address))))))335 (defn activate-program336 ([] (activate-program (write-all-program-data)))337 ([script]338 (->> script339 (transfer-control main-program-base-address)340 (do-nothing 1800))))343 ;; possible screen writing programs345 ;; (program needs to stop executing at some point)346 ;; maybe have total length counter or something?348 ;; automatic counter that reads from program-start and clears the349 ;; screen every 360 (* 18 20) gliphs351 ;; advantages -- very simple and low bandwidth352 ;; disadvantages -- hard to align counter354 ;; implementation -- refactor main-bootstrap-program to provide a355 ;; state-machine code-section which can be recombined into another356 ;; program.