# HG changeset patch # User Robert McIntyre # Date 1332386023 18000 # Node ID 95b2758dd5170cb1121d555ebe8e44297d139ade # Parent 5d9a7a0ca09ac1d49b38dd4e8f0947959436d6c6 wrote functions to read and write pokemon DV values and status diff -r 5d9a7a0ca09a -r 95b2758dd517 clojure/com/aurellem/exp/item_bridge.clj --- a/clojure/com/aurellem/exp/item_bridge.clj Wed Mar 21 18:17:37 2012 -0500 +++ b/clojure/com/aurellem/exp/item_bridge.clj Wed Mar 21 22:13:43 2012 -0500 @@ -51,11 +51,12 @@ (defn capture-program-counter [^SaveState state ticks] - (set-state! state) + (tick state) + (loop [i 0 pcs []] (if (= i ticks) - pcs + (set pcs) (do (com.aurellem.gb.Gb/tick) (recur (inc i) diff -r 5d9a7a0ca09a -r 95b2758dd517 clojure/com/aurellem/exp/pokemon-layout --- a/clojure/com/aurellem/exp/pokemon-layout Wed Mar 21 18:17:37 2012 -0500 +++ b/clojure/com/aurellem/exp/pokemon-layout Wed Mar 21 22:13:43 2012 -0500 @@ -5,7 +5,7 @@ D166 Pokemon 4 Species D167 Pokemon 5 Species D168 Pokemon 6 Species -D169 +D169 End-of-List Sentinel (0xFF) D16A Pokemon 1 Color Map D16B /h D16C \l Pokemon 1 Current Hit Points diff -r 5d9a7a0ca09a -r 95b2758dd517 clojure/com/aurellem/exp/pokemon.clj --- a/clojure/com/aurellem/exp/pokemon.clj Wed Mar 21 18:17:37 2012 -0500 +++ b/clojure/com/aurellem/exp/pokemon.clj Wed Mar 21 22:13:43 2012 -0500 @@ -116,18 +116,6 @@ ([new-name] (rename-sixth-pokemon @current-state new-name))) -(defn print-text - ([^SaveState state begin end] - (dorun - (map (fn [character-code line] - (println - (format "0x%04X: " line) - (str (character-code->character character-code)))) - (subvec (vec (memory state)) begin end) - (range begin end))) - state) - ([begin end] - (print-text @current-state begin end))) (defn examine-name-memory [] (print-text @@ -517,9 +505,6 @@ (set-pokemon-id @current-state n new-id))) - - - (defn get-pokemon-1-info ([state] (subvec (vec (memory state)) @@ -733,117 +718,33 @@ ;; 10000000 ;; Speed => 210 (+16) -(def pokemon-1-DV-start 0xD185) -(defn pokemon-DV-start-point [poke-num] - (+ (* poke-num pokemon-record-width) - pokemon-1-DV-start)) +;; investigating status effects -(def reverse-4-bit - {0 0 - 1 8 - 2 4 - 3 12 - 5 10 - 6 6 - 7 14 - 9 9 - 15 15 - 13 11 +;; status of pokemon 1 appears to be +;; 0xD16E - 8 1 - 4 2 - 12 3 - 10 5 - 11 13 - 14 7 }) - -(defn read-DV - ([^SaveState state poke-num] - (assert (<= 0 poke-num 5)) - (let [[raw-DV-1 - raw-DV-2] - (subvec (vec (memory state)) - (pokemon-DV-start-point poke-num) - (+ 2 (pokemon-DV-start-point poke-num))) - defense-DV (bit-and raw-DV-1 0x0F) - attack-DV (bit-shift-right - (bit-and raw-DV-1 0xF0) - 4) - special-DV (bit-and raw-DV-2 0x0F) - speed-DV (bit-shift-right - (bit-and raw-DV-2 0xF0) - 4) - HP-DV - (+ - (if (bit-test special-DV 0) 1 0) - (if (bit-test speed-DV 0) 2 0) - (if (bit-test defense-DV 0) 4 0) - (if (bit-test attack-DV 0) 8 0))] - {:attack attack-DV - :defense defense-DV - :speed speed-DV - :special special-DV - :hp HP-DV})) - ([poke-num] - (read-DV @current-state poke-num))) - +;; with pidgeot +;; 00000000 -- normal +;; 00000001 -- sleep (wake-immediately) +;; 00000010 -- sleep +;; 00000100 -- sleep +;; 00001000 -- poisoned +;; 00010000 -- burned +;; 00100000 -- frozen +;; 01000000 -- paralyzed +;; 10000000 -- ball is dark, but no status -(defn give-DV - ([^SaveState state poke-num dv-values] - - (assert (<= 0 poke-num 5)) - (map #(assert (<= 0 % 15)) (vals dv-values)) - (let [raw-dv-1* - (+ (:defense dv-values) - (bit-shift-left (:attack dv-values) 4)) - raw-dv-2* - (+ (:special dv-values) - (bit-shift-left (:speed dv-values) 4)) - hp-dv (:hp dv-values) - hp-masks-1 - [[0 (bit-test hp-dv 2)] - [4 (bit-test hp-dv 3)]] - hp-masks-2 - [[0 (bit-test hp-dv 0)] - [4 (bit-test hp-dv 1)]] - set-hp-bits - (fn [init [index hp?]] - (if hp? - (bit-set init index) - (bit-clear init index))) +;; with pikachu +;; 00000000 -- normal +;; 00000001 -- sleep (1 turn wasted) \ +;; 00000010 -- sleep (2 turns wasted) |-- additive +;; 00000100 -- sleep (3 turns wasted) / +;; 00001000 -- poisoned +;; 00010000 -- burned +;; 00100000 -- frozen +;; 01000000 -- paralyzed +;; 10000000 -- ball is dark, but no status - raw-dv-1 (reduce set-hp-bits raw-dv-1* - hp-masks-1) - - raw-dv-2 (reduce set-hp-bits raw-dv-2* - hp-masks-2) - - dv-start (pokemon-DV-start-point poke-num)] - (if (or (not= raw-dv-1* raw-dv-1) - (not= raw-dv-2* raw-dv-2)) - (println "Warning: inconsistent DV-values." - "Using HP settings.")) - - (set-memory - (set-memory state dv-start raw-dv-1) - (inc dv-start) raw-dv-2))) - ([poke-num dv-values] - (give-DV @current-state poke-num dv-values))) - -(def good-DVs - {:attack 15 - :defense 15 - :speed 15 - :special 15 - :hp 15}) - -(def bad-DVs - {:attack 0 - :defense 0 - :speed 0 - :special 0 - :hp 0}) - - \ No newline at end of file + \ No newline at end of file diff -r 5d9a7a0ca09a -r 95b2758dd517 clojure/com/aurellem/gb/assembly.clj --- a/clojure/com/aurellem/gb/assembly.clj Wed Mar 21 18:17:37 2012 -0500 +++ b/clojure/com/aurellem/gb/assembly.clj Wed Mar 21 22:13:43 2012 -0500 @@ -406,7 +406,6 @@ (set-state! (input-number)) (dotimes [_ 90000] (step (view-memory @current-state 0xD352)))) - (defn write-memory-assembly* "A program for altering in-game memory by pressing buttons." [] diff -r 5d9a7a0ca09a -r 95b2758dd517 clojure/com/aurellem/gb/characters.clj --- a/clojure/com/aurellem/gb/characters.clj Wed Mar 21 18:17:37 2012 -0500 +++ b/clojure/com/aurellem/gb/characters.clj Wed Mar 21 22:13:43 2012 -0500 @@ -1,5 +1,5 @@ (ns com.aurellem.gb.characters - (:use (com.aurellem.gb gb-driver)) + (:use (com.aurellem.gb gb-driver constants)) (:import [com.aurellem.gb.gb_driver SaveState])) (def character-code->character @@ -114,5 +114,21 @@ % (format "[0x%02X]" %)) codes))) - +(defn print-text + ([^SaveState state begin end] + (dorun + (map (fn [character-code line] + (println + (format "0x%04X: " line) + (str (character-code->character character-code)))) + (subvec (vec (memory state)) begin end) + (range begin end))) + state) + ([begin end] + (print-text @current-state begin end))) + +(defn read-name [codes] + (character-codes->str + (take-while + (partial not= end-of-name-marker) codes))) diff -r 5d9a7a0ca09a -r 95b2758dd517 clojure/com/aurellem/gb/constants.clj --- a/clojure/com/aurellem/gb/constants.clj Wed Mar 21 18:17:37 2012 -0500 +++ b/clojure/com/aurellem/gb/constants.clj Wed Mar 21 22:13:43 2012 -0500 @@ -1,3 +1,7 @@ (ns com.aurellem.gb.constants) -(def pokemon-record-width 44) \ No newline at end of file +(def pokemon-record-width 44) + +(def end-of-name-marker 0x50) +(def max-name-length 10) +(def name-width 11) diff -r 5d9a7a0ca09a -r 95b2758dd517 clojure/com/aurellem/gb/dv.clj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clojure/com/aurellem/gb/dv.clj Wed Mar 21 22:13:43 2012 -0500 @@ -0,0 +1,97 @@ +(ns com.aurellem.gb.dv + (:use (com.aurellem.gb gb-driver util constants)) + (:import [com.aurellem.gb.gb_driver SaveState])) + +(def pokemon-1-DV-start 0xD185) + +(defn pokemon-DV-start-point [poke-num] + (+ (* poke-num pokemon-record-width) + pokemon-1-DV-start)) + +(defn read-DV + ([^SaveState state poke-num] + (assert (<= 0 poke-num 5)) + (let [[raw-DV-1 + raw-DV-2] + (subvec (vec (memory state)) + (pokemon-DV-start-point poke-num) + (+ 2 (pokemon-DV-start-point poke-num))) + defense-DV (bit-and raw-DV-1 0x0F) + attack-DV (bit-shift-right + (bit-and raw-DV-1 0xF0) + 4) + special-DV (bit-and raw-DV-2 0x0F) + speed-DV (bit-shift-right + (bit-and raw-DV-2 0xF0) + 4) + HP-DV + (+ + (if (bit-test special-DV 0) 1 0) + (if (bit-test speed-DV 0) 2 0) + (if (bit-test defense-DV 0) 4 0) + (if (bit-test attack-DV 0) 8 0))] + {:attack attack-DV + :defense defense-DV + :speed speed-DV + :special special-DV + :hp HP-DV})) + ([poke-num] + (read-DV @current-state poke-num))) + + +(defn give-DV + ([^SaveState state poke-num dv-values] + + (assert (<= 0 poke-num 5)) + (map #(assert (<= 0 % 15)) (vals dv-values)) + (let [raw-dv-1* + (+ (:defense dv-values) + (bit-shift-left (:attack dv-values) 4)) + raw-dv-2* + (+ (:special dv-values) + (bit-shift-left (:speed dv-values) 4)) + hp-dv (:hp dv-values) + hp-masks-1 + [[0 (bit-test hp-dv 2)] + [4 (bit-test hp-dv 3)]] + hp-masks-2 + [[0 (bit-test hp-dv 0)] + [4 (bit-test hp-dv 1)]] + set-hp-bits + (fn [init [index hp?]] + (if hp? + (bit-set init index) + (bit-clear init index))) + + raw-dv-1 (reduce set-hp-bits raw-dv-1* + hp-masks-1) + + raw-dv-2 (reduce set-hp-bits raw-dv-2* + hp-masks-2) + + dv-start (pokemon-DV-start-point poke-num)] + + (if (or (not= raw-dv-1* raw-dv-1) + (not= raw-dv-2* raw-dv-2)) + (println "Warning: inconsistent DV-values." + "Using HP settings.")) + + (set-memory + (set-memory state dv-start raw-dv-1) + (inc dv-start) raw-dv-2))) + ([poke-num dv-values] + (give-DV @current-state poke-num dv-values))) + +(def good-DVs + {:attack 15 + :defense 15 + :speed 15 + :special 15 + :hp 15}) + +(def bad-DVs + {:attack 0 + :defense 0 + :speed 0 + :special 0 + :hp 0}) diff -r 5d9a7a0ca09a -r 95b2758dd517 clojure/com/aurellem/gb/pokemon.clj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clojure/com/aurellem/gb/pokemon.clj Wed Mar 21 22:13:43 2012 -0500 @@ -0,0 +1,178 @@ +(ns com.aurellem.gb.pokemon + (:use (com.aurellem.gb gb-driver util constants characters)) + (:import [com.aurellem.gb.gb_driver SaveState])) + +(def pokemon-names-start 0xD2B4) + +(defn change-party-number [^SaveState state new-num] + (set-memory state 0xD162 new-num)) + +(def party-number-address 0xD162) + +(defn party-number + ([^SaveState state] + (aget (memory state) party-number-address)) + ([] (party-number @current-state))) + +(defn party-names + ([^SaveState state] + (let [raw-names + (subvec (vec (memory state)) + pokemon-names-start + (+ pokemon-names-start + (* name-width 6)))] + (map + read-name + (take + (party-number state) + (partition name-width + raw-names))))) + ([] (party-names @current-state))) + +(defn rename-pokemon + ([^SaveState state n new-name] + (assert (<= 0 n (dec (party-number state)))) + (assert (<= (count new-name) max-name-length)) + (set-memory-range + state + (+ (* n name-width) pokemon-names-start) + (concat (str->character-codes new-name) [end-of-name-marker]))) + ([n new-name] + (rename-pokemon @current-state n new-name))) + +(def OT-start 0xD272) + +(defn original-trainers + ([^SaveState state] + (let [raw-names + (subvec (vec (memory state)) + OT-start + (+ OT-start + (* name-width 6)))] + (map read-name + (take (party-number state) + (partition name-width raw-names))))) + ([] (original-trainers @current-state))) + +(defn set-original-trainer + "Set the OT name for a pokemon. + Note that a pokemon is still considered 'yours' if + the OT ID is the same as your own." + ([^SaveState state poke-num new-name] + (assert (<= 0 poke-num (dec (party-number state)))) + (assert (<= (count new-name) max-name-length)) + (set-memory-range + state + (+ (* poke-num name-width) OT-start) + (concat (str->character-codes new-name) [end-of-name-marker]))) + ([n new-name] + (set-original-trainer @current-state n new-name))) + +(def OT-ID-addresses [0xD176 0xD1A2 0xD1CE 0xD1FA 0xD228 0xD252]) + +(defn set-pokemon-id + ([^SaveState state n new-id] + (assert (<= 0 n (dec (party-number state)))) + (assert (<= 0 new-id 0xFFFF)) + (set-memory-range + state + (OT-ID-addresses n) + [(bit-shift-right (bit-and new-id 0xFF00) 8) + (bit-and new-id 0xFF) + ])) + ([n new-id] + (set-pokemon-id @current-state n new-id))) + +(def unknown "[[[UNKNOWN]]]") + +(def unknown "") + +(def pokemon-1-info + {0xD16A "Color Map" ;; 0 + 0xD16B "Current-HP (h)" ;; 1 + 0xD16C "Current-HP (l)" ;; 2 + 0XD16D unknown ;; 3 + 0xD16E unknown ;; 4 + 0xD16F unknown ;; 5 + 0xD170 unknown ;; 6 + 0xD171 unknown ;; 7 + 0xD172 "Move 1 ID" ;; 8 + 0xD173 "Move 2 ID" ;; 9 + 0xD174 "Move 3 ID" ;; 10 + 0xD175 "Move 4 ID" ;; 11 + 0xD176 "OT-ID (h)" ;; 12 + 0xD177 "OT-ID (l)" ;; 13 + 0xD178 "Exp. Points (h)" ;; 14 + 0xD179 "Exp. Points (m)" ;; 15 + 0xD17A "Exp. Points (l)" ;; 16 + 0xD17B "HP Exp. (h)" ;; 17 + 0xD17C "HP Exp. (l)" ;; 18 + 0xD17D "Attack Exp. (h)" ;; 19 + 0xD17E "Attack Exp. (l)" ;; 20 + 0xD17F "Defense Exp. (h)" ;; 21 + 0xD180 "Defense Exp. (l)" ;; 22 + 0xD181 "Speed Exp. (h)" ;; 23 + 0xD182 "Speed Exp. (l)" ;; 24 + 0xD183 "Special Exp. (h)" ;; 25 + 0xD184 "Special Exp. (l)" ;; 26 + 0xD185 "DV Atk/Def" ;; 27 + 0xD186 "DV Speed/Spc" ;; 28 + 0xD187 "PP Move 1" ;; 29 + 0xD188 "PP Move 2" ;; 30 + 0xD189 "PP Move 3" ;; 31 + 0xD18A "PP Move 4" ;; 32 + 0xD18B "Current Level" ;; 33 + 0xD18C "HP Total (h)" ;; 34 + 0xD18D "HP Total (l)" ;; 35 + 0xD18E "Attack (h)" ;; 36 + 0xD18F "Attack (l)" ;; 37 + 0xD190 "Defense (h)" ;; 38 + 0xD191 "Defense (l)" ;; 39 + 0xD192 "Speed (h)" ;; 40 + 0xD193 "Speed (l)" ;; 41 + 0xD194 "Special (h)" ;; 42 + 0xD195 "Special (l)" ;; 43 + }) + +(defn pokemon-data + ([^SaveState state pokemon-num] + (assert (<= 0 pokemon-num 5)) + (let [base (+ (* pokemon-num pokemon-record-width) 0xD16A)] + (subvec (vec (memory state)) base + (+ base pokemon-record-width)))) + ([pokemon-num] (pokemon-data @current-state pokemon-num))) + +(defn set-pokemon-data + ([^SaveState state pokemon-num new-data] + (assert (<= 0 pokemon-num 5)) + (let [base (+ (* pokemon-num pokemon-record-width) 0xD16A)] + (set-memory-range state base new-data))) + ([pokemon-num new-data] + (set-pokemon-data @current-state pokemon-num new-data))) + +(defn print-pokemon-data + ([^SaveState state pokemon-num] + (assert (<= 0 pokemon-num 5)) + (let [poke-data (pokemon-data state pokemon-num) + backbone (sort (keys pokemon-1-info))] + (println "Pokemon " pokemon-num " -- " + (nth (party-names state) + pokemon-num) \newline) + + (println " Desc. | Hex | Dec | Binary |") + (println "-------------------+------+-----+----------+") + (dorun + (map + (comp println + (fn [desc data] + (format "%-16s | 0x%02X | %3d | %s |" + desc data data + (let [s (Integer/toBinaryString data)] + (apply + str + (concat (repeat (- 8 (count s)) "0" ) + s)))))) + (map pokemon-1-info backbone) + poke-data)))) + ([pokemon-num] + (print-pokemon-data @current-state pokemon-num))) diff -r 5d9a7a0ca09a -r 95b2758dd517 clojure/com/aurellem/gb/status.clj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clojure/com/aurellem/gb/status.clj Wed Mar 21 22:13:43 2012 -0500 @@ -0,0 +1,50 @@ +(ns com.aurellem.gb.status + (:use (com.aurellem.gb gb-driver util constants)) + (:import [com.aurellem.gb.gb_driver SaveState])) + +(def status-name->status-code + {:normal (Integer/parseInt "00000000" 2) + :sleep-1 (Integer/parseInt "00000001" 2) + :sleep-2 (Integer/parseInt "00000010" 2) + :sleep-3 (Integer/parseInt "00000011" 2) + :sleep-4 (Integer/parseInt "00000100" 2) + :sleep-5 (Integer/parseInt "00000101" 2) + :sleep-6 (Integer/parseInt "00000111" 2) + :poisoned (Integer/parseInt "00001000" 2) + :burned (Integer/parseInt "00010000" 2) + :frozen (Integer/parseInt "00100000" 2) + :paralyzed (Integer/parseInt "01000000" 2)}) + +(def status-code->status-name + (zipmap (vals status-name->status-code) + (keys status-name->status-code))) + + +(def pokemon-1-status-address 0xD16E) + +(defn pokemon-status-address [poke-num] + (+ pokemon-1-status-address + (* poke-num pokemon-record-width))) + +(defn give-stat + ([^SaveState state poke-num status] + (assert (<= 0 poke-num 5)) + (let [status-code + (status-name->status-code status)] + (assert status-code) + (set-memory state + (pokemon-status-address poke-num) + status-code))) + ([poke-num status] + (give-stat @current-state poke-num status)) + ([status] + (give-stat @current-state 0 status))) + +(defn give-stat-all + ([^SaveState state status] + (reduce (fn [state num] + (give-stat state num status)) + state + (range (party-number state)))) + ([status] + (give-stat-all @current-state status))) diff -r 5d9a7a0ca09a -r 95b2758dd517 clojure/com/aurellem/gb/util.clj --- a/clojure/com/aurellem/gb/util.clj Wed Mar 21 18:17:37 2012 -0500 +++ b/clojure/com/aurellem/gb/util.clj Wed Mar 21 22:13:43 2012 -0500 @@ -42,13 +42,16 @@ ([mem] (view-memory @current-state mem))) -(defn print-listing [state begin end] - (dorun (map - (fn [opcode line] - (println (format "0x%04X: 0x%02X" line opcode))) - (subvec (vec (memory state)) begin end) - (range begin end))) - state) +(defn print-listing + ([^SaveState state begin end] + (dorun (map + (fn [opcode line] + (println (format "0x%04X: 0x%02X" line opcode))) + (subvec (vec (memory state)) begin end) + (range begin end))) + state) + ([begin end] + (print-listing @current-state begin end))) (defn print-pc ([^SaveState state] diff -r 5d9a7a0ca09a -r 95b2758dd517 src/sdl/SDL.cpp --- a/src/sdl/SDL.cpp Wed Mar 21 18:17:37 2012 -0500 +++ b/src/sdl/SDL.cpp Wed Mar 21 22:13:43 2012 -0500 @@ -2063,7 +2063,10 @@ } int tick () { - return theEmulator.emuMain(theEmulator.emuCount); + int ret; + ret = theEmulator.emuMain(theEmulator.emuCount); + // enable user input while ticking. + if (ret) { sdlPollEvents(); } } void step () {