changeset 417:0b6624c1291c

made basic tone player.
author Robert McIntyre <rlm@mit.edu>
date Mon, 16 Apr 2012 14:08:56 -0500
parents 21b8b3350b20
children f211cd655ccb
files .hgignore clojure/com/aurellem/gb/util.clj clojure/com/aurellem/run/bootstrap_1.clj clojure/com/aurellem/run/music.clj moves/new-kernel.vbm save-states/new-kernel.sav
diffstat 6 files changed, 199 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/.hgignore	Sat Apr 14 05:41:55 2012 -0500
     1.2 +++ b/.hgignore	Mon Apr 16 14:08:56 2012 -0500
     1.3 @@ -15,3 +15,4 @@
     1.4  java/dist/*
     1.5  java/headers/*
     1.6  java/.ant-targets-build.xml
     1.7 +html/*
     2.1 --- a/clojure/com/aurellem/gb/util.clj	Sat Apr 14 05:41:55 2012 -0500
     2.2 +++ b/clojure/com/aurellem/gb/util.clj	Mon Apr 16 14:08:56 2012 -0500
     2.3 @@ -3,8 +3,10 @@
     2.4    (:import java.io.File)
     2.5    (:import [com.aurellem.gb.gb_driver SaveState]))
     2.6  
     2.7 -(defn A [state]
     2.8 -  (bit-shift-right (bit-and 0x0000FF00 (AF state)) 8))
     2.9 +(defn A
    2.10 +  ([state]
    2.11 +     (bit-shift-right (bit-and 0x0000FF00 (AF state)) 8))
    2.12 +  ([] (A @current-state)))
    2.13  
    2.14  (defn B [state]
    2.15    (bit-shift-right (bit-and 0x0000FF00 (BC state)) 8))
    2.16 @@ -112,8 +114,12 @@
    2.17    ([] (print-op @current-state)))
    2.18  
    2.19  (defn d-tick
    2.20 -  ([state]
    2.21 -  (-> state print-pc print-op tick)))
    2.22 +  ([] (d-tick 1))
    2.23 +  ([n] (d-tick n @current-state))
    2.24 +  ([n state]
    2.25 +     (reduce (fn [state _]
    2.26 +               (-> state print-pc print-op tick))
    2.27 +             state (range n))))
    2.28  
    2.29  (defn print-interrupt
    2.30    [^SaveState state]
     3.1 --- a/clojure/com/aurellem/run/bootstrap_1.clj	Sat Apr 14 05:41:55 2012 -0500
     3.2 +++ b/clojure/com/aurellem/run/bootstrap_1.clj	Mon Apr 16 14:08:56 2012 -0500
     3.3 @@ -858,6 +858,13 @@
     3.4              (transfer-control target)
     3.5              (do-nothing 1)))))
     3.6  
     3.7 +(defn gen-new-kernel-checkpoint! []
     3.8 +  (write-script! (do-nothing 10 (relocate-main-bootstrap))
     3.9 +                 "new-kernel"))
    3.10 +
    3.11 +(defn new-kernel [] (read-script "new-kernel"))
    3.12 +
    3.13 +
    3.14  (def mid-game-data
    3.15    (subvec (vec (memory (mid-game)))
    3.16            pokemon-list-start
    3.17 @@ -865,7 +872,7 @@
    3.18  
    3.19  (def mid-game-map-address 0x46BC)
    3.20  
    3.21 -(defn set-mid-game-data
    3.22 +(defn-memo set-mid-game-data
    3.23    ([] (set-mid-game-data (relocate-main-bootstrap)))
    3.24    ([script]
    3.25       (->> script
    3.26 @@ -888,7 +895,7 @@
    3.27               pokemon-list-start
    3.28               (+ pokemon-list-start 500))))
    3.29  
    3.30 -(defn return-to-pokemon-kernel
    3.31 +(defn-memo return-to-pokemon-kernel
    3.32    ([] (return-to-pokemon-kernel (set-mid-game-data)))
    3.33    ([script]
    3.34       (let [scratch (+ 200 pokemon-box-1-address)
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/clojure/com/aurellem/run/music.clj	Mon Apr 16 14:08:56 2012 -0500
     4.3 @@ -0,0 +1,179 @@
     4.4 +(ns com.aurellem.run.music
     4.5 +  (:use (com.aurellem.gb saves gb-driver util constants
     4.6 +                         items vbm characters money
     4.7 +                         rlm-assembly))
     4.8 +  (:use (com.aurellem.run util title save-corruption
     4.9 +                          bootstrap-0 bootstrap-1))
    4.10 +  (:import [com.aurellem.gb.gb_driver SaveState]))
    4.11 +
    4.12 +
    4.13 +(def music-base new-kernel)
    4.14 +
    4.15 +
    4.16 +
    4.17 +
    4.18 +(defn store [n address]
    4.19 +  (flatten
    4.20 +   [0xF5
    4.21 +    0xE5
    4.22 +    
    4.23 +    0x3E
    4.24 +    n
    4.25 +    
    4.26 +    0x21
    4.27 +    (reverse (disect-bytes-2 address))
    4.28 +
    4.29 +    0x77
    4.30 +    
    4.31 +    0xE1
    4.32 +    0xF1]))
    4.33 +
    4.34 +(defn infinite-loop []
    4.35 +  [0x18 0xFE])
    4.36 +
    4.37 +
    4.38 +
    4.39 +(def divider-register 0xFF04)
    4.40 +
    4.41 +
    4.42 +(defrecord Bit-Note [frequency volume duration duty])
    4.43 +
    4.44 +(defn clear-music-registers []
    4.45 +  (flatten
    4.46 +   [(store (Integer/parseInt "00000000" 2) 0xFF10)
    4.47 +    (store (Integer/parseInt "00000000" 2) 0xFF11)
    4.48 +    (store (Integer/parseInt "00000000" 2) 0xFF12)
    4.49 +    (store (Integer/parseInt "00000000" 2) 0xFF13)
    4.50 +    (store (Integer/parseInt "00000000" 2) 0xFF14)
    4.51 +
    4.52 +    (store (Integer/parseInt "00000000" 2) 0xFF16) ;; pattern duty 000000
    4.53 +    (store (Integer/parseInt "00000000" 2) 0xFF17) ;; volume 0000
    4.54 +    (store (Integer/parseInt "00000000" 2) 0xFF18) ;; frequency-low
    4.55 +    (store (Integer/parseInt "00000000" 2) 0xFF19) ;; 00000 frequency-high
    4.56 +
    4.57 +    (store (Integer/parseInt "00000000" 2) 0xFF1A)
    4.58 +    (store (Integer/parseInt "00000000" 2) 0xFF1B)
    4.59 +    (store (Integer/parseInt "00000000" 2) 0xFF1C)
    4.60 +    (store (Integer/parseInt "00000000" 2) 0xFF1D)
    4.61 +    (store (Integer/parseInt "00000000" 2) 0xFF1E)
    4.62 +
    4.63 +    (store (Integer/parseInt "00000000" 2) 0xFF20)
    4.64 +    (store (Integer/parseInt "00000000" 2) 0xFF21)
    4.65 +    (store (Integer/parseInt "00000000" 2) 0xFF22)
    4.66 +    (store (Integer/parseInt "00000000" 2) 0xFF23)]))
    4.67 +
    4.68 +(defn play-note
    4.69 +  "Play the note referenced by HL in the appropiate channel.
    4.70 +   Leaves desired-duration in A."
    4.71 +  []
    4.72 +  [0x2A   ;; load volume/frequency-high info
    4.73 +   0xF5   ;; push A
    4.74 +   0xE6
    4.75 +   (Integer/parseInt "11110000" 2) ;; volume mask
    4.76 +   0xE0
    4.77 +   0x17   ;; set volume
    4.78 +   0xF1   ;; pop A
    4.79 +   0xE6
    4.80 +   (Integer/parseInt "00000111" 2) ;; frequency-high mask
    4.81 +   0xE0   
    4.82 +   0x19   ;; set frequency-high
    4.83 +   
    4.84 +   0x2A   ;; load frequency low-bits
    4.85 +   0xE0
    4.86 +   0x18   ;; set frequency-low-bits
    4.87 +
    4.88 +   0x7E   ;; load duration
    4.89 +   ;;0x2B   ;; 
    4.90 +   ;;0x2B
    4.91 +   ]) ;; HL-2 -> HL
    4.92 +
    4.93 +(defn music-step []
    4.94 +  (flatten
    4.95 +   [(play-note)
    4.96 +    0xF5 ;; push A
    4.97 +    0xF0
    4.98 +    0x05 ;; load current ticks
    4.99 +    0x90 ;; B holds previous sub-ticks, subtract it from A
   4.100 +    ;; if A-B caused a carry, then (B > A) is true, and
   4.101 +    ;; A = current-sub-tics, B = previous-sub-ticks, so
   4.102 +    ;; current-sub-ticks < previous-sub-ticks, which means that the
   4.103 +    ;; timer counter HAS overflowed.
   4.104 +    0x30 ;; increment C only if last result caused carry
   4.105 +    0x01
   4.106 +    0x00;;0x0C
   4.107 +
   4.108 +    0x47 ;; update sub-ticks (A->B)
   4.109 +
   4.110 +    0xF1 ;; pop AF, now A contains desired-ticks
   4.111 +
   4.112 +    0xB9 ;; compare with current ticks
   4.113 +
   4.114 +    ;; if desired-ticks = current ticks
   4.115 +    ;;   go to next note ; set current set ticks to 0.
   4.116 +
   4.117 +    0x20
   4.118 +    0x05
   4.119 +
   4.120 +    0x23
   4.121 +    0x23
   4.122 +    0x23 ;; HL + 3 -> HL
   4.123 +    
   4.124 +    0x0E
   4.125 +    0x00])) ;; 0->C (current-ticks)
   4.126 +
   4.127 +(defn music-kernel []
   4.128 +  (flatten
   4.129 +   [(clear-music-registers)
   4.130 +    0x21
   4.131 +    0x00
   4.132 +    0xD0 ;; set HL to 0xD000 == music-start
   4.133 +    0x0E
   4.134 +    0x00 ;; 0->C
   4.135 +    0x06
   4.136 +    0x00 ;; 0->B
   4.137 +
   4.138 +    0x3E
   4.139 +    0x00
   4.140 +    0xE0
   4.141 +    0x06 ;; set TMA to 0
   4.142 +    
   4.143 +    0x3E
   4.144 +    (Integer/parseInt "00000111" 2)
   4.145 +    0xE0
   4.146 +    0x07 ;; set TAC to 16384 Hz
   4.147 +
   4.148 +    (music-step)
   4.149 +    0x18
   4.150 +    (->signed-8-bit (+ (- (count (music-step)))
   4.151 +                       -2))]))
   4.152 +
   4.153 +
   4.154 +(defn play-music [steps music-bytes]
   4.155 +  (let [program-target 0xC000
   4.156 +        music-target 0xD000]
   4.157 +    (-> (set-memory-range (second (music-base))
   4.158 +                          program-target (music-kernel))
   4.159 +        (set-memory-range music-target music-bytes)
   4.160 +        (PC! program-target))))
   4.161 +
   4.162 +
   4.163 +(defn test-note [music-bytes]
   4.164 +  (-> (set-memory-range (second (music-base))
   4.165 +                        0xC000 (concat (clear-music-registers)
   4.166 +                                       (play-note)
   4.167 +                                       (infinite-loop)))
   4.168 +      (set-memory-range 0xD000 music-bytes)
   4.169 +      (PC! 0xC000)
   4.170 +      (HL! 0xD000)
   4.171 +      ))
   4.172 +
   4.173 +
   4.174 +(defn run-program
   4.175 +  ([program] (run-program program 90))
   4.176 +  ([program steps]
   4.177 +     (let [target 0xC000]
   4.178 +       (-> (set-memory-range (second (music-base))
   4.179 +                             target program)
   4.180 +           (PC! target)))))
   4.181 +
   4.182 +
     5.1 Binary file moves/new-kernel.vbm has changed
     6.1 Binary file save-states/new-kernel.sav has changed