Mercurial > vba-clojure
view clojure/com/aurellem/run/music.clj @ 418:f211cd655ccb
completed basic music playing kernel
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 17 Apr 2012 06:36:17 -0500 |
parents | 0b6624c1291c |
children | 971bd1774eab |
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 "00000111" 2)161 0xE0162 0x07 ;; set TAC to 16384 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 0xA7 0x00 0x55])188 (defn play-music [music-bytes]189 (let [program-target 0xC000190 music-target 0xD000]191 (-> (set-memory-range (second (music-base))192 program-target (music-kernel))193 (set-memory-range music-target music-bytes)194 (PC! program-target))))197 (defn test-note [music-bytes]198 (-> (set-memory-range (second (music-base))199 0xC000 (concat (clear-music-registers)200 (play-note)201 (infinite-loop)))202 (set-memory-range 0xD000 music-bytes)203 (PC! 0xC000)204 (HL! 0xD000)205 ))208 (defn run-program209 ([program]210 (let [target 0xC000]211 (-> (set-memory-range (second (music-base))212 target program)213 (PC! target)))))215 (defn trippy []216 (run-moves (play-music many-notes ) (repeat 8000 [])))