annotate clojure/com/aurellem/exp/item_bridge.clj @ 378:5c4a30521d09

created efficient frame-metronome program
author Robert McIntyre <rlm@mit.edu>
date Wed, 11 Apr 2012 11:43:51 -0500
parents 1f14c1b8af7e
children
rev   line source
rlm@170 1 (ns com.aurellem.exp.item-bridge
rlm@179 2 (:use (com.aurellem.gb saves util constants gb-driver vbm items assembly))
rlm@319 3 (:use (com.aurellem.run util title save-corruption))
rlm@179 4 ;;(:use (com.aurellem.exp pokemon))
rlm@154 5 (:import [com.aurellem.gb.gb_driver SaveState]))
rlm@130 6
rlm@131 7 (defn corrupt-item-state []
rlm@131 8 (second (destroy-item-end-of-list-marker)))
rlm@131 9
rlm@131 10 (defn corrupt-item-state []
rlm@131 11 (read-state "corrupt-items"))
rlm@131 12
rlm@313 13 (defn view-memory-range
rlm@313 14 ([start end]
rlm@313 15 (view-memory-range
rlm@313 16 @current-state start end))
rlm@313 17 ([state start end]
rlm@313 18 (dorun
rlm@313 19 (map (fn [loc val]
rlm@313 20 (println (format "%04X : %02X" loc val)))
rlm@313 21 (range start end) (subvec (vec (memory state)) start end)))
rlm@313 22 state))
rlm@131 23
rlm@133 24 (defn almost-broken
rlm@133 25 "if one more memory location is turned into 0x03, the game crashes."
rlm@133 26 [n]
rlm@133 27 (view-memory-range
rlm@133 28 (set-inv-mem (mid-game)
rlm@133 29 (concat [0xFF] (repeat 64 0x03)
rlm@133 30 (subvec (vec (memory (mid-game)))
rlm@133 31 (+ item-list-start 65)
rlm@133 32 (+ item-list-start 65 n))
rlm@170 33 (repeat (- 255 65 n) 0x03)))
rlm@133 34 item-list-start (+ item-list-start 255)))
rlm@131 35
rlm@133 36 (defn actually-broken
rlm@170 37 "if this memory location is turned into 0x03, the game crashes."
rlm@133 38 []
rlm@133 39 (set-memory (mid-game) 0xD35D 0x03))
rlm@131 40
rlm@131 41
rlm@133 42 ;; (almost-broken 20) more or less works
rlm@133 43
rlm@170 44
rlm@170 45 (defn loop-program []
rlm@174 46 [0x00 ;0xD31D ;; disable-interrupts
rlm@170 47
rlm@170 48 0xC3 ;; loop forever
rlm@170 49 0x1D
rlm@170 50 0xD3])
rlm@170 51
rlm@170 52 (def map-function-address-start 0xD36D)
rlm@170 53
rlm@170 54 (defn test-loop []
rlm@174 55 (continue!
rlm@170 56 (-> (mid-game)
rlm@170 57 (set-memory-range 0xD31D (loop-program))
rlm@170 58 (set-memory-range
rlm@170 59 map-function-address-start
rlm@174 60 [0xD3 0x1D]))))
rlm@174 61
rlm@170 62 (defn-memo corrupt-moves []
rlm@170 63 (concat
rlm@170 64 (first
rlm@170 65 (->>
rlm@170 66 [[] (mid-game)]
rlm@319 67 (first-difference [:b] [:b :start] AF)
rlm@319 68 (first-difference [] [:d] AF)
rlm@170 69 (play-moves [[] [] [] [:d] [] [] [] [:d] [] [] [:a]])
rlm@319 70 (do-nothing 200)
rlm@319 71 (play-moves [[:a]])
rlm@170 72 (play-moves
rlm@170 73 ;; this section is copied from speedrun-2942
rlm@170 74 ;; and corrupts the save so that the end-of-list marker
rlm@170 75 ;; for the pokemon roster is destroyed, but the save is still
rlm@170 76 ;; playable.
rlm@170 77 [[] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] []
rlm@170 78 [] [] [] [] [] [] [] [] [] [] [:select] [:restart]])
rlm@250 79 (title)
rlm@319 80 (first-difference [] [:start] AF)
rlm@319 81 (first-difference [] [:a] AF)
rlm@319 82 (first-difference [:a] [:a :start] AF)))
rlm@170 83 [[]]))
rlm@170 84
rlm@170 85 (defn corrupt
rlm@170 86 "enter the codes to destroy the
rlm@170 87 pokemon list using save corruption"
rlm@170 88 ([^SaveState state]
rlm@170 89 (run-moves
rlm@170 90 state
rlm@170 91 (corrupt-moves)))
rlm@171 92 ([] (corrupt @current-state)))
rlm@173 93
rlm@173 94 (defn mid-game-corrupt []
rlm@173 95 (read-state "corrupt-mid-game"))
rlm@170 96
rlm@235 97 (defn gen-start-game-corrupt []
rlm@250 98 (->> (second (intro))
rlm@319 99 (first-difference [:b] [:a :b :start] AF)
rlm@235 100 (play-moves (corrupt-moves))))
rlm@212 101
rlm@235 102 (defn start-game-corrupt []
rlm@235 103 (read-state "corrupt-start-game"))
rlm@212 104
rlm@187 105 (defn test-memory-fun [n]
rlm@187 106 (capture-program-counter
rlm@187 107 (set-memory-range
rlm@187 108 (tick (mid-game))
rlm@187 109 0xD36D
rlm@187 110 [0 0])
rlm@187 111 n))
rlm@170 112
rlm@187 113 ;;(def good (test-memory-fun 17000))
rlm@187 114
rlm@187 115 ;;(def bad (test-memory-fun 18000))
rlm@187 116
rlm@187 117
rlm@212 118
rlm@212 119 (defn menu-open-state []
rlm@212 120 (read-state "menu-open"))
rlm@212 121
rlm@212 122 (defn prepare-memory
rlm@212 123 ([^SaveState state]
rlm@212 124 (-> state
rlm@212 125 (set-memory-range 0xD31D (loop-program))
rlm@212 126 (set-memory-range 0xD36D [0x1D 0xD3])))
rlm@212 127 ([] (prepare-memory @current-state)))
rlm@212 128
rlm@233 129 (def memory-function-address-start 0xD36D)
rlm@233 130
rlm@233 131 (defn read-map-function-address
rlm@233 132 ([^SaveState state]
rlm@233 133 (let [mem (memory state)]
rlm@233 134 [(aget mem memory-function-address-start)
rlm@233 135 (aget mem (inc memory-function-address-start))]))
rlm@233 136 ([] (read-map-function-address @current-state)))
rlm@212 137
rlm@212 138 (defn succesful-PC-capture
rlm@212 139 "This function demonstrates successful PC capturing by
rlm@212 140 setting 0xD36D to the value of the start location of
rlm@212 141 a specially prepared program.
rlm@212 142
rlm@212 143 You must run the function and then exit the open menu
rlm@212 144 to see the effect."
rlm@212 145 []
rlm@212 146 (dorun
rlm@212 147 (map #(println (Integer/toHexString %))
rlm@212 148 (capture-program-counter
rlm@212 149 (prepare-memory (menu-open-state))
rlm@212 150 9000000))))
rlm@233 151
rlm@233 152 (defn trampoline-assembly [^SaveState state]
rlm@233 153 (flatten
rlm@233 154 [0x3E ;;
rlm@233 155 0x3E ;; load lemonade into A
rlm@233 156
rlm@233 157 0xEA
rlm@233 158 0x1D
rlm@233 159 0xD3 ;; set first item to lemonade
rlm@233 160
rlm@238 161 0xC3 ;; return control to the game via absolute jump.
rlm@233 162 (read-map-function-address state)
rlm@233 163 ]))
rlm@233 164
rlm@233 165 (defn test-trampoline
rlm@233 166 "Demonstrates item-program execution via the map-function that
rlm@233 167 returns control to the main pokemon game after one loop."
rlm@238 168 [assembly-fn state]
rlm@233 169 (let [insertion-address 0xD33D
rlm@233 170 insertion-address-bits [0x3D 0xD3]]
rlm@233 171 (->
rlm@238 172 state
rlm@233 173 (set-memory-range
rlm@233 174 insertion-address
rlm@238 175 (assembly-fn state))
rlm@233 176 (set-memory-range
rlm@233 177 memory-function-address-start
rlm@235 178 insertion-address-bits))))
rlm@235 179
rlm@239 180 (def lemonade-trampoline
rlm@239 181 (partial test-trampoline
rlm@239 182 trampoline-assembly
rlm@239 183 (menu-open-state)))
rlm@235 184
rlm@238 185 (defn trampoline-assembly-burn-heal [^SaveState state]
rlm@238 186 (flatten
rlm@238 187 [0x3E ;;
rlm@238 188 0x3E ;; load lemonade into A
rlm@238 189
rlm@238 190 0xEA
rlm@238 191 0x1D
rlm@238 192 0xD3 ;; set first item to lemonade
rlm@238 193
rlm@239 194 0xC3 ;; return control to the game via absolute jump
rlm@239 195 0x0C ;; to Route 3's map-function
rlm@238 196 0x55
rlm@238 197 ]))
rlm@235 198
rlm@247 199 (def corrupted-items-width 512)
rlm@247 200
rlm@247 201 (defn items-record
rlm@247 202 ([^SaveState state]
rlm@247 203 (subvec (vec (memory state))
rlm@247 204 item-list-start
rlm@247 205 (+ item-list-start corrupted-items-width)))
rlm@247 206 ([] (items-record @current-state)))
rlm@247 207
rlm@247 208 (defn pc-items-record
rlm@247 209 ([^SaveState state]
rlm@247 210 (subvec (vec (memory state))
rlm@247 211 pc-item-list-start
rlm@247 212 (+ pc-item-list-width pc-item-list-start)))
rlm@247 213 ([] (pc-items-record @current-state)))
rlm@247 214
rlm@247 215 (defn print-listing-items
rlm@247 216 ([^SaveState state]
rlm@247 217 (print-listing state item-list-start
rlm@247 218 (+ item-list-start corrupted-items-width))
rlm@247 219 state)
rlm@247 220 ([] (print-listing-items @current-state)))
rlm@247 221
rlm@247 222 (defn print-listing-pc-items
rlm@247 223 ([^SaveState state]
rlm@247 224 (print-listing
rlm@247 225 state
rlm@247 226 pc-item-list-start
rlm@247 227 (+ pc-item-list-width pc-item-list-start))
rlm@247 228 state)
rlm@247 229 ([] (print-listing-pc-items @current-state)))
rlm@247 230
rlm@247 231
rlm@247 232