rlm@145: (ns com.aurellem.exp.pokemon rlm@145: "Here I find out how pokemon are stored in memory." rlm@145: (:use (com.aurellem.gb gb-driver items assembly util rlm@166: constants rlm@166: characters species moves)) rlm@161: (:import java.io.File) rlm@145: (:import [com.aurellem.gb.gb_driver SaveState])) rlm@145: rlm@145: rlm@145: (def pidgeot-lvl-36 (mid-game)) rlm@145: rlm@145: rlm@145: (def pidgeot-lvl-37 (read-state "pidgeot-lvl-37")) rlm@145: rlm@145: rlm@145: (def pidgeot-lvl-38 (read-state "pidgeot-lvl-38")) rlm@145: rlm@145: rlm@145: (def pidgeot-lvl-39 (read-state "pidgeot-lvl-39")) rlm@145: rlm@145: rlm@145: (def pidgeot-lvl-40 (read-state "pidgeot-lvl-40")) rlm@145: rlm@145: rlm@145: (defn level-analysis [] rlm@145: (apply common-differences rlm@145: (map (comp vec memory) rlm@145: [pidgeot-lvl-36 rlm@145: pidgeot-lvl-37 rlm@145: pidgeot-lvl-38 rlm@145: pidgeot-lvl-39 rlm@145: pidgeot-lvl-40]))) rlm@145: rlm@145: ;; inconclusive -- implies that level is calculated from rlm@145: ;; some other values. rlm@145: rlm@145: rlm@145: (def name-pidgeotto (read-state "name-pidgeotto")) rlm@145: (def named-A (read-state "named-A")) rlm@145: (def named-B (read-state "named-B")) rlm@145: (def named-C (read-state "named-C")) rlm@145: (def named-D (read-state "named-D")) rlm@145: (def named-E (read-state "named-E")) rlm@145: (def named-F (read-state "named-F")) rlm@145: rlm@145: (defn name-analysis [] rlm@145: (apply common-differences rlm@145: (map (comp vec memory) rlm@145: [named-A rlm@145: named-B rlm@145: named-C rlm@145: named-D rlm@145: named-E rlm@145: named-F]))) rlm@145: rlm@145: ;; resluted in 3 separate locations that could rlm@145: ;; possibly hold the first letter of the pokemon's name rlm@145: rlm@145: 0xCF4A rlm@145: 0xD2EB rlm@145: 0xCEED rlm@145: rlm@145: ;; try changing each of them rlm@145: rlm@145: rlm@145: (defn test-cf4a [] rlm@145: (continue! rlm@145: (set-memory named-A 0xCF4A (character->character-code "Z")))) rlm@145: ;; result -- pidgeotto named "A" rlm@145: rlm@145: (defn test-d2eb [] rlm@145: (continue! rlm@145: (set-memory named-A 0xD2EB (character->character-code "Z")))) rlm@145: ;; result -- pidgeotto named "Z" rlm@145: rlm@145: (defn test-ceed [] rlm@145: (continue! rlm@145: (set-memory named-A 0xCEED (character->character-code "Z")))) rlm@145: ;; result -- pidgeotto named "A" rlm@145: rlm@145: (def sixth-pokemon-name-start 0xD2EB) rlm@145: rlm@145: rlm@145: (defn set-sixth-pokemon-name-first-character rlm@145: ([state character] rlm@145: (set-memory state sixth-pokemon-name-start rlm@145: (character->character-code character))) rlm@145: ([character] rlm@145: (set-sixth-pokemon-name-first-character @current-state rlm@145: character))) rlm@145: rlm@145: rlm@146: (def end-of-name-marker 0x50) rlm@147: (def max-name-length 10) rlm@147: (def name-width 11) rlm@147: rlm@148: (defn read-name [codes] rlm@147: (character-codes->str rlm@147: (take-while rlm@147: (partial not= end-of-name-marker) codes))) rlm@147: rlm@145: rlm@146: (defn sixth-pokemon-name [^SaveState state] rlm@148: (read-name rlm@146: (subvec (vec (memory state)) rlm@146: sixth-pokemon-name-start rlm@146: (+ (inc max-name-length) rlm@147: sixth-pokemon-name-start)))) rlm@145: rlm@147: (defn rename-sixth-pokemon rlm@147: ([^SaveState state new-name] rlm@147: (assert (< (count new-name) max-name-length)) rlm@147: (set-memory-range state sixth-pokemon-name-start rlm@147: (concat (str->character-codes new-name) rlm@147: [end-of-name-marker]))) rlm@147: ([new-name] rlm@147: (rename-sixth-pokemon @current-state new-name))) rlm@147: rlm@147: rlm@147: (defn examine-name-memory [] rlm@147: (print-text rlm@147: named-A rlm@147: (- sixth-pokemon-name-start 100) rlm@147: (+ sixth-pokemon-name-start 100))) rlm@147: rlm@147: ;; results: rlm@147: ;; 0xD287: end-of-name-sentinel rlm@147: ;; 0xD288: R rlm@147: ;; 0xD289: L rlm@147: ;; 0xD28A: M rlm@147: ;; 0xD28B: end-of-pokemon-name-sentinel rlm@147: ;; 0xD28C: end-of-name-sentinel rlm@147: ;; 0xD28D: end-of-name-sentinel rlm@147: ;; 0xD28E: end-of-name-sentinel rlm@147: ;; 0xD28F: end-of-name-sentinel rlm@147: ;; 0xD290: end-of-name-sentinel rlm@147: ;; 0xD291: end-of-name-sentinel rlm@147: ;; 0xD292: end-of-name-sentinel rlm@147: ;; 0xD293: R rlm@147: ;; 0xD294: L rlm@147: ;; 0xD295: M rlm@147: ;; 0xD296: end-of-pokemon-name-sentinel rlm@147: ;; 0xD297: end-of-name-sentinel rlm@147: ;; 0xD298: end-of-name-sentinel rlm@147: ;; 0xD299: end-of-name-sentinel rlm@147: ;; 0xD29A: end-of-name-sentinel rlm@147: ;; 0xD29B: end-of-name-sentinel rlm@147: ;; 0xD29C: end-of-name-sentinel rlm@147: ;; 0xD29D: end-of-name-sentinel rlm@147: ;; 0xD29E: R rlm@147: ;; 0xD29F: L rlm@147: ;; 0xD2A0: M rlm@147: ;; 0xD2A1: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2A2: end-of-name-sentinel rlm@147: ;; 0xD2A3: end-of-name-sentinel rlm@147: ;; 0xD2A4: end-of-name-sentinel rlm@147: ;; 0xD2A5: end-of-name-sentinel rlm@147: ;; 0xD2A6: end-of-name-sentinel rlm@147: ;; 0xD2A7: end-of-name-sentinel rlm@147: ;; 0xD2A8: end-of-name-sentinel rlm@147: ;; 0xD2A9: R rlm@147: ;; 0xD2AA: L rlm@147: ;; 0xD2AB: M rlm@147: ;; 0xD2AC: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2AD: end-of-name-sentinel rlm@147: ;; 0xD2AE: end-of-name-sentinel rlm@147: ;; 0xD2AF: end-of-name-sentinel rlm@147: ;; 0xD2B0: end-of-name-sentinel rlm@147: ;; 0xD2B1: end-of-name-sentinel rlm@147: ;; 0xD2B2: end-of-name-sentinel rlm@147: ;; 0xD2B3: end-of-name-sentinel rlm@147: ;; 0xD2B4: P rlm@147: ;; 0xD2B5: I rlm@147: ;; 0xD2B6: D rlm@147: ;; 0xD2B7: G rlm@147: ;; 0xD2B8: E rlm@147: ;; 0xD2B9: O rlm@147: ;; 0xD2BA: T rlm@147: ;; 0xD2BB: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2BC: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2BD: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2BE: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2BF: P rlm@147: ;; 0xD2C0: I rlm@147: ;; 0xD2C1: K rlm@147: ;; 0xD2C2: A rlm@147: ;; 0xD2C3: C rlm@147: ;; 0xD2C4: H rlm@147: ;; 0xD2C5: U rlm@147: ;; 0xD2C6: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2C7: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2C8: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2C9: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2CA: C rlm@147: ;; 0xD2CB: H rlm@147: ;; 0xD2CC: A rlm@147: ;; 0xD2CD: R rlm@147: ;; 0xD2CE: I rlm@147: ;; 0xD2CF: Z rlm@147: ;; 0xD2D0: A rlm@147: ;; 0xD2D1: R rlm@147: ;; 0xD2D2: D rlm@147: ;; 0xD2D3: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2D4: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2D5: V rlm@147: ;; 0xD2D6: E rlm@147: ;; 0xD2D7: N rlm@147: ;; 0xD2D8: U rlm@147: ;; 0xD2D9: S rlm@147: ;; 0xD2DA: A rlm@147: ;; 0xD2DB: U rlm@147: ;; 0xD2DC: R rlm@147: ;; 0xD2DD: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2DE: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2DF: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2E0: P rlm@147: ;; 0xD2E1: R rlm@147: ;; 0xD2E2: I rlm@147: ;; 0xD2E3: M rlm@147: ;; 0xD2E4: E rlm@147: ;; 0xD2E5: A rlm@147: ;; 0xD2E6: P rlm@147: ;; 0xD2E7: E rlm@147: ;; 0xD2E8: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2E9: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2EA: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2EB: A rlm@147: ;; 0xD2EC: end-of-pokemon-name-sentinel rlm@147: ;; 0xD2ED: S rlm@147: ;; 0xD2EE: T rlm@147: ;; 0xD2EF: E rlm@147: ;; 0xD2F0: R rlm@147: ;; 0xD2F1: rlm@147: ;; 0xD2F2: B rlm@147: ;; 0xD2F3: A rlm@147: ;; 0xD2F4: L rlm@147: ;; 0xD2F5: L rlm@147: ;; 0xD2F6: rlm@147: ;; 0xD2F7: A rlm@147: ;; 0xD2F8: rlm@147: ;; 0xD2F9: rlm@147: ;; 0xD2FA: end-of-name-sentinel rlm@147: ;; 0xD2FB: end-of-name-sentinel rlm@147: ;; 0xD2FC: A rlm@147: ;; 0xD2FD: rlm@147: ;; 0xD2FE: end-of-name-sentinel rlm@147: ;; 0xD2FF: end-of-name-sentinel rlm@147: ;; 0xD300: end-of-name-sentinel rlm@147: ;; 0xD301: end-of-name-sentinel rlm@147: ;; 0xD302: end-of-name-sentinel rlm@147: ;; 0xD303: end-of-name-sentinel rlm@147: ;; 0xD304: end-of-name-sentinel rlm@147: ;; 0xD305: end-of-name-sentinel rlm@147: ;; 0xD306: end-of-name-sentinel rlm@147: ;; 0xD307: end-of-name-sentinel rlm@147: ;; 0xD308: end-of-name-sentinel rlm@147: ;; 0xD309: rlm@147: ;; 0xD30A: w rlm@147: ;; 0xD30B: rlm@147: ;; 0xD30C: V rlm@147: ;; 0xD30D: rlm@147: ;; 0xD30E: rlm@147: ;; 0xD30F: K rlm@147: ;; 0xD310: rlm@147: ;; 0xD311: rlm@147: ;; 0xD312: rlm@147: ;; 0xD313: A rlm@147: ;; 0xD314: rlm@147: ;; 0xD315: rlm@147: ;; 0xD316: rlm@147: ;; 0xD317: i rlm@147: ;; 0xD318: rlm@147: ;; 0xD319: rlm@147: ;; 0xD31A: end-of-name-sentinel rlm@147: ;; 0xD31B: end-of-name-sentinel rlm@147: ;; 0xD31C: rlm@147: ;; 0xD31D: rlm@147: ;; 0xD31E: rlm@147: ;; 0xD31F: rlm@147: ;; 0xD320: rlm@147: ;; 0xD321: rlm@147: ;; 0xD322: rlm@147: ;; 0xD323: rlm@147: ;; 0xD324: rlm@147: ;; 0xD325: rlm@147: ;; 0xD326: rlm@147: ;; 0xD327: rlm@147: ;; 0xD328: rlm@147: ;; 0xD329: rlm@147: ;; 0xD32A: rlm@147: ;; 0xD32B: rlm@147: ;; 0xD32C: rlm@147: ;; 0xD32D: rlm@147: ;; 0xD32E: rlm@147: ;; 0xD32F: rlm@147: ;; 0xD330: rlm@147: ;; 0xD331: 9 rlm@147: ;; 0xD332: end-of-name-sentinel rlm@147: ;; 0xD333: 9 rlm@147: ;; 0xD334: rlm@147: ;; 0xD335: 9 rlm@147: ;; 0xD336: rlm@147: ;; 0xD337: 9 rlm@147: ;; 0xD338: end-of-name-sentinel rlm@147: ;; 0xD339: end-of-name-sentinel rlm@147: ;; 0xD33A: end-of-name-sentinel rlm@147: ;; 0xD33B: end-of-name-sentinel rlm@147: ;; 0xD33C: end-of-name-sentinel rlm@147: ;; 0xD33D: end-of-name-sentinel rlm@147: ;; 0xD33E: end-of-name-sentinel rlm@147: ;; 0xD33F: end-of-name-sentinel rlm@147: ;; 0xD340: end-of-name-sentinel rlm@147: ;; 0xD341: end-of-name-sentinel rlm@147: ;; 0xD342: end-of-name-sentinel rlm@147: ;; 0xD343: end-of-name-sentinel rlm@147: ;; 0xD344: end-of-name-sentinel rlm@147: ;; 0xD345: end-of-name-sentinel rlm@147: ;; 0xD346: rlm@147: ;; 0xD347: rlm@147: ;; 0xD348: rlm@147: ;; 0xD349: G rlm@147: ;; 0xD34A: A rlm@147: ;; 0xD34B: R rlm@147: ;; 0xD34C: Y rlm@147: ;; 0xD34D: end-of-pokemon-name-sentinel rlm@147: ;; 0xD34E: J rlm@147: rlm@147: rlm@147: ;; from this, it looks like the pokemon names are stored all rlm@147: ;; together in one location that begins at 0xD2B4 and rlm@147: ;; extends until 0xD2F5, with each name taking up 11 bytes. rlm@147: ;; rlm@147: ;; rival's name again clearly starts at 0xD349. rlm@147: rlm@147: rlm@147: (def pokemon-names-start 0xD2B4) rlm@147: rlm@147: rlm@147: ;; determine whether "number of pokemon in party" rlm@147: ;; might be kept in RAM and if so, where? rlm@147: rlm@147: (def six-pokemon (read-state "6-pokemon")) rlm@147: (def five-pokemon (read-state "5-pokemon")) rlm@147: (def four-pokemon (read-state "4-pokemon")) rlm@147: (def three-pokemon (read-state "3-pokemon")) rlm@147: (def two-pokemon (read-state "2-pokemon")) rlm@147: (def one-pokemon (read-state "1-pokemon")) rlm@147: rlm@147: rlm@147: (defn analyze-num-pokemon [] rlm@147: (apply common-differences rlm@147: (map (comp vec memory) rlm@147: [one-pokemon rlm@147: two-pokemon rlm@147: three-pokemon rlm@147: four-pokemon rlm@147: five-pokemon rlm@147: six-pokemon]))) rlm@147: rlm@147: ;; ;; results rlm@147: ;; ([53602 (1 2 3 4 5 6)] rlm@147: ;; [65314 (105 61 93 60 92 34)] rlm@147: ;; [55875 (34 36 43 52 7 0)] rlm@147: ;; [55876 (18 0 33 52 54 30)] rlm@147: ;; [49158 (197 194 77 117 174 134)] rlm@147: ;; [49160 (29 26 57 239 15 243)] rlm@147: ;; [49736 (74 93 34 89 91 59)] rlm@147: ;; [49162 (165 162 182 179 197 109)] rlm@147: ;; [49227 (187 105 204 5 90 238)] rlm@147: ;; [53067 (128 136 132 145 135 11)] rlm@147: ;; [53068 (147 131 141 136 128 7)] rlm@147: ;; [53069 (136 134 148 140 145 2)] rlm@147: ;; [49904 (2 11 10 3 27 12)] rlm@147: ;; [49172 (100 109 213 195 68 104)] rlm@147: ;; [65492 (11 103 128 160 19 56)] rlm@147: ;; [49173 (80 77 72 75 76 67)] rlm@147: ;; [49334 (8 10 11 5 3 1)] rlm@147: ;; [49335 (49 10 11 19 17 15)] rlm@147: ;; [49336 (8 10 11 5 3 1)] rlm@147: ;; [49720 (106 14 118 0 38 11)] rlm@147: ;; [65304 (32 88 19 114 106 33)] rlm@147: ;; [53561 (59 229 48 17 155 103)] rlm@147: ;; [55935 (6 5 4 3 2 1)]) rlm@147: rlm@147: rlm@147: ;; two canidates : 0xD162 or 0xDA7F rlm@147: ;; they seem to always sum to 6... rlm@147: rlm@147: ;; try to set both of them when having only one pokemon. rlm@147: rlm@147: (defn change-party-number [^SaveState state new-num] rlm@147: (set-memory state 0xD162 new-num)) rlm@147: rlm@147: ;; (continue! (change-party-number one-pokemon 3)) rlm@147: ;; result -- can scroll down beyone first pokemon, finding rlm@147: ;; glitched pokemon in places where there were previously no rlm@147: ;; pokemon. rlm@147: rlm@147: rlm@147: (defn change-party-number* [^SaveState state new-num] rlm@147: (set-memory state 0xDA7F new-num)) rlm@147: rlm@147: rlm@147: ;; (continue! (change-party-number* one-pokemon 3)) rlm@147: ;; cannot widthdraw any pokemon from box 1 past the third rlm@147: ;; pokemon. rlm@147: rlm@147: (def party-number-address 0xD162) rlm@147: rlm@147: (defn party-number rlm@147: ([^SaveState state] rlm@147: (aget (memory state) party-number-address)) rlm@147: ([] (party-number @current-state))) rlm@147: rlm@147: (def pokemon-in-box-1-address 0xDA7F) rlm@147: rlm@147: (defn party-names rlm@147: ([^SaveState state] rlm@147: (let [raw-names rlm@147: (subvec (vec (memory state)) rlm@147: pokemon-names-start rlm@147: (+ pokemon-names-start rlm@148: (* name-width 6)))] rlm@147: (map rlm@148: read-name rlm@147: (take rlm@147: (party-number state) rlm@147: (partition name-width rlm@147: raw-names))))) rlm@147: ([] (party-names @current-state))) rlm@147: rlm@148: rlm@148: (defn rename-pokemon rlm@148: ([^SaveState state n new-name] rlm@148: (assert (<= 0 n (dec (party-number state)))) rlm@148: (assert (<= (count new-name) max-name-length)) rlm@148: (set-memory-range rlm@148: state rlm@148: (+ (* n name-width) pokemon-names-start) rlm@148: (concat (str->character-codes new-name) [end-of-name-marker]))) rlm@148: ([n new-name] rlm@148: (rename-pokemon @current-state n new-name))) rlm@148: rlm@148: ;; on further analysis, it appears that the original rlm@148: ;; trainer info for each pokemon is also stored together, rlm@148: ;; starting at 0xD272 and continuing to 0xD2B3, with rlm@148: ;; 11 bytes reserved for each OT name. rlm@148: rlm@148: (def OT-start 0xD272) rlm@148: rlm@148: (defn original-trainers rlm@148: ([^SaveState state] rlm@148: (let [raw-names rlm@148: (subvec (vec (memory state)) rlm@148: OT-start rlm@148: (+ OT-start rlm@148: (* name-width 6)))] rlm@148: (map read-name rlm@148: (take (party-number state) rlm@148: (partition name-width raw-names))))) rlm@148: ([] (original-trainers @current-state))) rlm@148: rlm@148: (defn set-original-trainer rlm@148: "Set the OT name for a pokemon. rlm@148: Note that a pokemon is still considered 'yours' if rlm@148: the OT ID is the same as your own." rlm@148: ([^SaveState state n new-name] rlm@148: (assert (<= 0 n (dec (party-number state)))) rlm@148: (assert (<= (count new-name) max-name-length)) rlm@148: (set-memory-range rlm@148: state rlm@148: (+ (* n name-width) OT-start) rlm@148: (concat (str->character-codes new-name) [end-of-name-marker]))) rlm@148: ([n new-name] rlm@148: (set-original-trainer @current-state n new-name))) rlm@148: rlm@148: ;; PIKACHU stops following if you set it's OT to another name rlm@148: ;; and then back to you own. rlm@148: ;; But not if you set it to your own name, obviously. rlm@149: rlm@149: rlm@150: rlm@150: rlm@150: ;; OT ID Numbers. rlm@152: ;; My own id is 05195. A quick search of memory between rlm@150: ;; 0xD162 and 0xD31B revealed the pattern 0x144B exactly rlm@150: ;; six times. rlm@150: rlm@150: ;; the locations were: rlm@150: rlm@150: (def OT-ID-addresses [0xD176 0xD1A2 0xD1CE 0xD1FA 0xD228 0xD252]) rlm@150: rlm@150: rlm@150: (defn set-pokemon-id rlm@150: ([^SaveState state n new-id] rlm@150: (assert (<= 0 n (dec (party-number state)))) rlm@150: (assert (<= 0 new-id 0xFFFF)) rlm@150: (set-memory-range rlm@150: state rlm@150: (OT-ID-addresses n) rlm@151: [(bit-shift-right (bit-and new-id 0xFF00) 8) rlm@151: (bit-and new-id 0xFF) rlm@151: ])) rlm@150: ([n new-id] rlm@151: (set-pokemon-id @current-state n new-id))) rlm@152: rlm@152: rlm@160: (defn get-pokemon-1-info rlm@160: ([state] rlm@160: (subvec (vec (memory state)) rlm@160: 0xD162 0xD197)) rlm@160: ([] (get-pokemon-1-info @current-state))) rlm@160: rlm@160: (def baseline (File. "/home/r/baseline-poke")) rlm@160: rlm@160: rlm@160: rlm@160: rlm@160: (import java.io.File) rlm@160: rlm@160: (defn set-baseline [state] rlm@160: (clojure.java.io/copy rlm@160: (with-out-str (print-listing state 0xD162 0xD197)) rlm@160: baseline)) rlm@160: rlm@160: (defn compare-pokemon rlm@160: ([state] rlm@160: (let [target (File. "/home/r/temp-poke")] rlm@160: (clojure.java.io/copy rlm@160: (with-out-str (print-listing state 0xD162 0xD197)) rlm@160: target) rlm@160: (println (:out rlm@160: (clojure.java.shell/sh "diff" rlm@160: (.getCanonicalPath baseline) rlm@160: (.getCanonicalPath target)))))) rlm@161: ([] (compare-pokemon @current-state))) rlm@160: rlm@160: rlm@160: (defn crazy-pid [] rlm@160: (read-state "crazy-pidgeot")) rlm@166: rlm@168: (def unknown "[[[UNKNOWN]]]") rlm@168: rlm@166: (def unknown "") rlm@166: rlm@166: (def pokemon-1-info rlm@166: {0xD16A "Color Map" ;; 0 rlm@166: 0xD16B "Current-HP (h)" ;; 1 rlm@166: 0xD16C "Current-HP (l)" ;; 2 rlm@166: 0XD16D unknown ;; 3 rlm@166: 0xD16E unknown ;; 4 rlm@166: 0xD16F unknown ;; 5 rlm@166: 0xD170 unknown ;; 6 rlm@166: 0xD171 unknown ;; 7 rlm@166: 0xD172 "Move 1 ID" ;; 8 rlm@166: 0xD173 "Move 2 ID" ;; 9 rlm@166: 0xD174 "Move 3 ID" ;; 10 rlm@166: 0xD175 "Move 4 ID" ;; 11 rlm@166: 0xD176 "OT-ID (h)" ;; 12 rlm@166: 0xD177 "OT-ID (l)" ;; 13 rlm@166: 0xD178 "Exp. Points (h)" ;; 14 rlm@166: 0xD179 "Exp. Points (m)" ;; 15 rlm@166: 0xD17A "Exp. Points (l)" ;; 16 rlm@168: 0xD17B "HP Exp. (h)" ;; 17 rlm@168: 0xD17C "HP Exp. (l)" ;; 18 rlm@168: 0xD17D "Attack Exp. (h)" ;; 19 rlm@168: 0xD17E "Attack Exp. (l)" ;; 20 rlm@168: 0xD17F "Defense Exp. (h)" ;; 21 rlm@168: 0xD180 "Defense Exp. (l)" ;; 22 rlm@168: 0xD181 "Speed Exp. (h)" ;; 23 rlm@168: 0xD182 "Speed Exp. (l)" ;; 24 rlm@168: 0xD183 "Special Exp. (h)" ;; 25 rlm@168: 0xD184 "Special Exp. (l)" ;; 26 rlm@172: 0xD185 "DV Atk/Def" ;; 27 rlm@172: 0xD186 "DV Speed/Spc" ;; 28 rlm@166: 0xD187 "PP Move 1" ;; 29 rlm@166: 0xD188 "PP Move 2" ;; 30 rlm@166: 0xD189 "PP Move 3" ;; 31 rlm@166: 0xD18A "PP Move 4" ;; 32 rlm@166: 0xD18B "Current Level" ;; 33 rlm@166: 0xD18C "HP Total (h)" ;; 34 rlm@166: 0xD18D "HP Total (l)" ;; 35 rlm@166: 0xD18E "Attack (h)" ;; 36 rlm@166: 0xD18F "Attack (l)" ;; 37 rlm@166: 0xD190 "Defense (h)" ;; 38 rlm@166: 0xD191 "Defense (l)" ;; 39 rlm@166: 0xD192 "Speed (h)" ;; 40 rlm@166: 0xD193 "Speed (l)" ;; 41 rlm@166: 0xD194 "Special (h)" ;; 42 rlm@168: 0xD195 "Special (l)" ;; 43 rlm@166: }) rlm@166: rlm@166: (defn pokemon-data rlm@166: ([^SaveState state pokemon-num] rlm@166: (assert (<= 0 pokemon-num 5)) rlm@166: (let [base (+ (* pokemon-num pokemon-record-width) 0xD16A)] rlm@166: (subvec (vec (memory state)) base rlm@166: (+ base pokemon-record-width)))) rlm@166: ([pokemon-num] (pokemon-data @current-state pokemon-num))) rlm@166: rlm@166: (defn set-pokemon-data rlm@166: ([^SaveState state pokemon-num new-data] rlm@166: (assert (<= 0 pokemon-num 5)) rlm@166: (let [base (+ (* pokemon-num pokemon-record-width) 0xD16A)] rlm@166: (set-memory-range state base new-data))) rlm@166: ([pokemon-num new-data] rlm@166: (set-pokemon-data @current-state pokemon-num new-data))) rlm@166: rlm@167: (defn print-pokemon-data rlm@167: ([^SaveState state pokemon-num] rlm@167: (assert (<= 0 pokemon-num 5)) rlm@167: (let [poke-data (pokemon-data state pokemon-num) rlm@167: backbone (sort (keys pokemon-1-info))] rlm@168: (println "Pokemon " pokemon-num " -- " rlm@168: (nth (party-names state) rlm@168: pokemon-num) \newline) rlm@168: rlm@168: (println " Desc. | Hex | Dec | Binary |") rlm@168: (println "-------------------+------+-----+----------+") rlm@167: (dorun rlm@167: (map rlm@167: (comp println rlm@167: (fn [desc data] rlm@168: (format "%-16s | 0x%02X | %3d | %s |" rlm@168: desc data data rlm@168: (let [s (Integer/toBinaryString data)] rlm@168: (apply rlm@168: str rlm@168: (concat (repeat (- 8 (count s)) "0" ) rlm@168: s))) rlm@168: rlm@168: rlm@168: ))) rlm@167: rlm@167: (map pokemon-1-info backbone) rlm@167: poke-data)))) rlm@167: ([pokemon-num] rlm@167: (print-pokemon-data @current-state pokemon-num))) rlm@167: rlm@166: rlm@166: rlm@180: rlm@167: rlm@168: rlm@169: (defn pika-lvl-100-DV-0 [] rlm@169: (read-state "at-pc-lv-100-pikachu")) rlm@168: rlm@169: ;; Performed following experiment: rlm@169: ;; Raised Pikachu to Lvl 100 with rare-candies, rlm@169: ;; then put it at the head of the party and rlm@169: ;; set 0xD185 and 0xD186 to zero. rlm@168: rlm@169: ;; then, for each pattern, deposited pikachu into rlm@169: ;; Box 1 and immediately widthdrew it and observed the rlm@169: ;; stats. rlm@168: rlm@169: rlm@169: ;; Pikachu L:100 Base Stats with DVs = 0 rlm@169: ;; HP : 187 rlm@169: ;; Attack : 123 rlm@169: ;; Defense : 73 rlm@169: ;; Speed : 194 rlm@169: ;; Special : 112 rlm@169: rlm@169: ;; 0xD185: rlm@169: rlm@169: ;; 00000001 rlm@169: ;; Defense => 75 (+2) rlm@169: ;; HP => 195 (+8) rlm@169: rlm@169: ;; 00000010 rlm@169: ;; Defense => 77 (+4) rlm@169: rlm@169: ;; 00000100 rlm@169: ;; Defense => 81 (+8) rlm@169: rlm@169: ;; 00001000 rlm@169: ;; Defense => 89 (+16) rlm@169: rlm@169: ;; 00010000 rlm@169: ;; HP => 203 (+16) rlm@169: ;; Attack => 125 (+2) rlm@169: rlm@169: ;; 00100000 rlm@169: ;; Attack => 127 (+4) rlm@169: rlm@169: ;; 01000000 rlm@169: ;; Attack -> 131 (+8) rlm@169: rlm@169: ;; 10000000 rlm@169: ;; Attack -> 139 (+16) rlm@169: rlm@169: ;; 0xD186 rlm@169: rlm@169: ;; 00000001 rlm@169: ;; HP => 189 (+2) rlm@169: ;; Special => (+2) rlm@169: rlm@169: ;; 00000010 rlm@169: ;; Special => 116 (+4) rlm@169: rlm@169: ;; 00000100 rlm@169: ;; Special => 120 (+8) rlm@169: rlm@169: ;; 00001000 rlm@169: ;; Special => 128 (+16) rlm@169: rlm@169: ;; 00010000 rlm@169: ;; HP => 191 (+4) rlm@169: ;; Speed => 196 (+2) rlm@169: rlm@169: ;; 00100000 rlm@169: ;; Speed => 198 (+4) rlm@169: rlm@169: ;; 01000000 rlm@169: ;; Speed => 202 (+8) rlm@169: rlm@169: ;; 10000000 rlm@169: ;; Speed => 210 (+16) rlm@169: rlm@169: rlm@176: ;; investigating status effects rlm@169: rlm@176: ;; status of pokemon 1 appears to be rlm@176: ;; 0xD16E rlm@169: rlm@176: ;; with pidgeot rlm@176: ;; 00000000 -- normal rlm@176: ;; 00000001 -- sleep (wake-immediately) rlm@176: ;; 00000010 -- sleep rlm@176: ;; 00000100 -- sleep rlm@176: ;; 00001000 -- poisoned rlm@176: ;; 00010000 -- burned rlm@176: ;; 00100000 -- frozen rlm@176: ;; 01000000 -- paralyzed rlm@176: ;; 10000000 -- ball is dark, but no status rlm@169: rlm@176: ;; with pikachu rlm@176: ;; 00000000 -- normal rlm@176: ;; 00000001 -- sleep (1 turn wasted) \ rlm@176: ;; 00000010 -- sleep (2 turns wasted) |-- additive rlm@176: ;; 00000100 -- sleep (3 turns wasted) / rlm@176: ;; 00001000 -- poisoned rlm@176: ;; 00010000 -- burned rlm@176: ;; 00100000 -- frozen rlm@176: ;; 01000000 -- paralyzed rlm@176: ;; 10000000 -- ball is dark, but no status rlm@169: rlm@169: rlm@176: