Mercurial > vba-clojure
view clojure/com/aurellem/run/music.clj @ 423:971bd1774eab
increased resolution of music-kernel timer.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 17 Apr 2012 06:53:48 -0500 |
parents | f211cd655ccb |
children | 7bd806c4dbb6 |
line wrap: on
line source
1 (ns com.aurellem.run.music2 (:use (com.aurellem.gb saves gb-driver util constants3 items vbm characters money4 rlm-assembly))5 (:use (com.aurellem.run util title save-corruption6 bootstrap-0 bootstrap-1))7 (:import [com.aurellem.gb.gb_driver SaveState]))10 (def music-base new-kernel)15 (defn store [n address]16 (flatten17 [0xF518 0xE520 0x3E21 n23 0x2124 (reverse (disect-bytes-2 address))26 0x7728 0xE129 0xF1]))31 (defn infinite-loop []32 [0x18 0xFE])36 (def divider-register 0xFF04)39 (defrecord Bit-Note [frequency volume duration duty])41 (defn clear-music-registers []42 (flatten43 [(store (Integer/parseInt "00000000" 2) 0xFF10)44 (store (Integer/parseInt "00000000" 2) 0xFF11)45 (store (Integer/parseInt "00000000" 2) 0xFF12)46 (store (Integer/parseInt "00000000" 2) 0xFF13)47 (store (Integer/parseInt "00000000" 2) 0xFF14)49 (store (Integer/parseInt "00000000" 2) 0xFF16) ;; pattern duty 00000050 (store (Integer/parseInt "00000000" 2) 0xFF17) ;; volume 000051 (store (Integer/parseInt "00000000" 2) 0xFF18) ;; frequency-low52 (store (Integer/parseInt "00000000" 2) 0xFF19) ;; 00000 frequency-high54 (store (Integer/parseInt "00000000" 2) 0xFF1A)55 (store (Integer/parseInt "00000000" 2) 0xFF1B)56 (store (Integer/parseInt "00000000" 2) 0xFF1C)57 (store (Integer/parseInt "00000000" 2) 0xFF1D)58 (store (Integer/parseInt "00000000" 2) 0xFF1E)60 (store (Integer/parseInt "00000000" 2) 0xFF20)61 (store (Integer/parseInt "00000000" 2) 0xFF21)62 (store (Integer/parseInt "00000000" 2) 0xFF22)63 (store (Integer/parseInt "00000000" 2) 0xFF23)]))65 (defn play-note66 "Play the note referenced by HL in the appropiate channel.67 Leaves desired-duration in A."68 []69 [0x2A ;; load volume/frequency-high info70 0xF5 ;; push A71 0xE672 (Integer/parseInt "11110000" 2) ;; volume mask73 0xE074 0x17 ;; set volume75 0xF1 ;; pop A76 0xE677 (Integer/parseInt "00000111" 2) ;; frequency-high mask78 0xE079 0x19 ;; set frequency-high81 0x2A ;; load frequency low-bits82 0xE083 0x18 ;; set frequency-low-bits85 0x7E ;; load duration86 0x2B ;;87 0x2B ;; HL-2 -> HL88 ])90 (defn music-step []91 (flatten92 [(play-note)93 0xF5 ;; push A94 0xF095 0x05 ;; load current ticks96 0xB8 ;; B holds previous sub-ticks, subtract it from A97 ;; if A-B caused a carry, then (B > A) is true, and98 ;; A = current-sub-tics, B = previous-sub-ticks, so99 ;; current-sub-ticks < previous-sub-ticks, which means that the100 ;; timer counter HAS overflowed.101 0x30 ;; increment C only if last result caused carry102 0x01103 0x0C105 0x47 ;; update sub-ticks (A->B)107 0xF1 ;; pop AF, now A contains desired-ticks109 0xB9 ;; compare with current ticks111 ;; if desired-ticks = current ticks112 ;; go to next note ; set current set ticks to 0.114 0x20115 0x05117 0x23118 0x23119 0x23 ;; HL + 3 -> HL121 0x0E122 0x00])) ;; 0->C (current-ticks)124 (defn test-timer []125 (flatten126 [0x3E127 0x01128 0xE0129 0x06 ;; set TMA to 0131 0x3E132 (Integer/parseInt "00000100" 2)133 0xE0134 0x07 ;; set TAC to 16384 Hz and activate timer136 (repeat137 500138 [0xF0139 0x05])]))142 (defn music-kernel []143 (flatten144 [(clear-music-registers)146 0x21147 0x00148 0xD0 ;; set HL to 0xD000 == music-start149 0x0E150 0x00 ;; 0->C151 0x06152 0x00 ;; 0->B154 0x3E155 0x01156 0xE0157 0x06 ;; set TMA to 0159 0x3E160 (Integer/parseInt "00000110" 2)161 0xE0162 0x07 ;; set TAC to 65536 Hz and activate timer164 0xF0165 0x07167 (music-step)168 0x18169 (->signed-8-bit (+ (- (count (music-step)))170 -2))]))172 (def one-note173 [0xA0 0x00 0xFF])175 (def many-notes176 (flatten (repeat 10 one-note)))178 (def increasing-notes179 [0xA0 0x00 0x55180 0xA1 0x00 0x55181 0xA2 0x00 0x55182 0xA3 0x00 0x55183 0xA4 0x00 0x55184 0xA5 0x00 0x55185 0xA6 0x00 0x55186 0xA6 0x55 0xFF187 0xA6 0x55 0xFF188 0xA6 0x55 0xFF189 0x00 0x00 0xFF190 ])193 (defn play-music [music-bytes]194 (let [program-target 0xC000195 music-target 0xD000]196 (-> (set-memory-range (second (music-base))197 program-target (music-kernel))198 (set-memory-range music-target music-bytes)199 (PC! program-target))))202 (defn test-note [music-bytes]203 (-> (set-memory-range (second (music-base))204 0xC000 (concat (clear-music-registers)205 (play-note)206 (infinite-loop)))207 (set-memory-range 0xD000 music-bytes)208 (PC! 0xC000)209 (HL! 0xD000)210 ))213 (defn run-program214 ([program]215 (let [target 0xC000]216 (-> (set-memory-range (second (music-base))217 target program)218 (PC! target)))))220 (defn trippy []221 (run-moves (play-music many-notes ) (repeat 8000 [])))