rlm@170: (ns com.aurellem.exp.item-bridge rlm@179: (:use (com.aurellem.gb saves util constants gb-driver vbm items assembly)) rlm@319: (:use (com.aurellem.run util title save-corruption)) rlm@179: ;;(:use (com.aurellem.exp pokemon)) rlm@154: (:import [com.aurellem.gb.gb_driver SaveState])) rlm@130: rlm@131: (defn corrupt-item-state [] rlm@131: (second (destroy-item-end-of-list-marker))) rlm@131: rlm@131: (defn corrupt-item-state [] rlm@131: (read-state "corrupt-items")) rlm@131: rlm@313: (defn view-memory-range rlm@313: ([start end] rlm@313: (view-memory-range rlm@313: @current-state start end)) rlm@313: ([state start end] rlm@313: (dorun rlm@313: (map (fn [loc val] rlm@313: (println (format "%04X : %02X" loc val))) rlm@313: (range start end) (subvec (vec (memory state)) start end))) rlm@313: state)) rlm@131: rlm@133: (defn almost-broken rlm@133: "if one more memory location is turned into 0x03, the game crashes." rlm@133: [n] rlm@133: (view-memory-range rlm@133: (set-inv-mem (mid-game) rlm@133: (concat [0xFF] (repeat 64 0x03) rlm@133: (subvec (vec (memory (mid-game))) rlm@133: (+ item-list-start 65) rlm@133: (+ item-list-start 65 n)) rlm@170: (repeat (- 255 65 n) 0x03))) rlm@133: item-list-start (+ item-list-start 255))) rlm@131: rlm@133: (defn actually-broken rlm@170: "if this memory location is turned into 0x03, the game crashes." rlm@133: [] rlm@133: (set-memory (mid-game) 0xD35D 0x03)) rlm@131: rlm@131: rlm@133: ;; (almost-broken 20) more or less works rlm@133: rlm@170: rlm@170: (defn loop-program [] rlm@174: [0x00 ;0xD31D ;; disable-interrupts rlm@170: rlm@170: 0xC3 ;; loop forever rlm@170: 0x1D rlm@170: 0xD3]) rlm@170: rlm@170: (def map-function-address-start 0xD36D) rlm@170: rlm@170: (defn test-loop [] rlm@174: (continue! rlm@170: (-> (mid-game) rlm@170: (set-memory-range 0xD31D (loop-program)) rlm@170: (set-memory-range rlm@170: map-function-address-start rlm@174: [0xD3 0x1D])))) rlm@174: rlm@170: (defn-memo corrupt-moves [] rlm@170: (concat rlm@170: (first rlm@170: (->> rlm@170: [[] (mid-game)] rlm@319: (first-difference [:b] [:b :start] AF) rlm@319: (first-difference [] [:d] AF) rlm@170: (play-moves [[] [] [] [:d] [] [] [] [:d] [] [] [:a]]) rlm@319: (do-nothing 200) rlm@319: (play-moves [[:a]]) rlm@170: (play-moves rlm@170: ;; this section is copied from speedrun-2942 rlm@170: ;; and corrupts the save so that the end-of-list marker rlm@170: ;; for the pokemon roster is destroyed, but the save is still rlm@170: ;; playable. rlm@170: [[] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] rlm@170: [] [] [] [] [] [] [] [] [] [] [:select] [:restart]]) rlm@250: (title) rlm@319: (first-difference [] [:start] AF) rlm@319: (first-difference [] [:a] AF) rlm@319: (first-difference [:a] [:a :start] AF))) rlm@170: [[]])) rlm@170: rlm@170: (defn corrupt rlm@170: "enter the codes to destroy the rlm@170: pokemon list using save corruption" rlm@170: ([^SaveState state] rlm@170: (run-moves rlm@170: state rlm@170: (corrupt-moves))) rlm@171: ([] (corrupt @current-state))) rlm@173: rlm@173: (defn mid-game-corrupt [] rlm@173: (read-state "corrupt-mid-game")) rlm@170: rlm@235: (defn gen-start-game-corrupt [] rlm@250: (->> (second (intro)) rlm@319: (first-difference [:b] [:a :b :start] AF) rlm@235: (play-moves (corrupt-moves)))) rlm@212: rlm@235: (defn start-game-corrupt [] rlm@235: (read-state "corrupt-start-game")) rlm@212: rlm@187: (defn test-memory-fun [n] rlm@187: (capture-program-counter rlm@187: (set-memory-range rlm@187: (tick (mid-game)) rlm@187: 0xD36D rlm@187: [0 0]) rlm@187: n)) rlm@170: rlm@187: ;;(def good (test-memory-fun 17000)) rlm@187: rlm@187: ;;(def bad (test-memory-fun 18000)) rlm@187: rlm@187: rlm@212: rlm@212: (defn menu-open-state [] rlm@212: (read-state "menu-open")) rlm@212: rlm@212: (defn prepare-memory rlm@212: ([^SaveState state] rlm@212: (-> state rlm@212: (set-memory-range 0xD31D (loop-program)) rlm@212: (set-memory-range 0xD36D [0x1D 0xD3]))) rlm@212: ([] (prepare-memory @current-state))) rlm@212: rlm@233: (def memory-function-address-start 0xD36D) rlm@233: rlm@233: (defn read-map-function-address rlm@233: ([^SaveState state] rlm@233: (let [mem (memory state)] rlm@233: [(aget mem memory-function-address-start) rlm@233: (aget mem (inc memory-function-address-start))])) rlm@233: ([] (read-map-function-address @current-state))) rlm@212: rlm@212: (defn succesful-PC-capture rlm@212: "This function demonstrates successful PC capturing by rlm@212: setting 0xD36D to the value of the start location of rlm@212: a specially prepared program. rlm@212: rlm@212: You must run the function and then exit the open menu rlm@212: to see the effect." rlm@212: [] rlm@212: (dorun rlm@212: (map #(println (Integer/toHexString %)) rlm@212: (capture-program-counter rlm@212: (prepare-memory (menu-open-state)) rlm@212: 9000000)))) rlm@233: rlm@233: (defn trampoline-assembly [^SaveState state] rlm@233: (flatten rlm@233: [0x3E ;; rlm@233: 0x3E ;; load lemonade into A rlm@233: rlm@233: 0xEA rlm@233: 0x1D rlm@233: 0xD3 ;; set first item to lemonade rlm@233: rlm@238: 0xC3 ;; return control to the game via absolute jump. rlm@233: (read-map-function-address state) rlm@233: ])) rlm@233: rlm@233: (defn test-trampoline rlm@233: "Demonstrates item-program execution via the map-function that rlm@233: returns control to the main pokemon game after one loop." rlm@238: [assembly-fn state] rlm@233: (let [insertion-address 0xD33D rlm@233: insertion-address-bits [0x3D 0xD3]] rlm@233: (-> rlm@238: state rlm@233: (set-memory-range rlm@233: insertion-address rlm@238: (assembly-fn state)) rlm@233: (set-memory-range rlm@233: memory-function-address-start rlm@235: insertion-address-bits)))) rlm@235: rlm@239: (def lemonade-trampoline rlm@239: (partial test-trampoline rlm@239: trampoline-assembly rlm@239: (menu-open-state))) rlm@235: rlm@238: (defn trampoline-assembly-burn-heal [^SaveState state] rlm@238: (flatten rlm@238: [0x3E ;; rlm@238: 0x3E ;; load lemonade into A rlm@238: rlm@238: 0xEA rlm@238: 0x1D rlm@238: 0xD3 ;; set first item to lemonade rlm@238: rlm@239: 0xC3 ;; return control to the game via absolute jump rlm@239: 0x0C ;; to Route 3's map-function rlm@238: 0x55 rlm@238: ])) rlm@235: rlm@247: (def corrupted-items-width 512) rlm@247: rlm@247: (defn items-record rlm@247: ([^SaveState state] rlm@247: (subvec (vec (memory state)) rlm@247: item-list-start rlm@247: (+ item-list-start corrupted-items-width))) rlm@247: ([] (items-record @current-state))) rlm@247: rlm@247: (defn pc-items-record rlm@247: ([^SaveState state] rlm@247: (subvec (vec (memory state)) rlm@247: pc-item-list-start rlm@247: (+ pc-item-list-width pc-item-list-start))) rlm@247: ([] (pc-items-record @current-state))) rlm@247: rlm@247: (defn print-listing-items rlm@247: ([^SaveState state] rlm@247: (print-listing state item-list-start rlm@247: (+ item-list-start corrupted-items-width)) rlm@247: state) rlm@247: ([] (print-listing-items @current-state))) rlm@247: rlm@247: (defn print-listing-pc-items rlm@247: ([^SaveState state] rlm@247: (print-listing rlm@247: state rlm@247: pc-item-list-start rlm@247: (+ pc-item-list-width pc-item-list-start)) rlm@247: state) rlm@247: ([] (print-listing-pc-items @current-state))) rlm@247: rlm@247: rlm@247: