Mercurial > vba-clojure
view clojure/com/aurellem/exp/pokemon.clj @ 162:34b518fc7404
moved important move code out of exp and into gb.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 20 Mar 2012 17:18:22 -0500 |
parents | cd7979aa544e |
children | 76b031d2f586 |
line wrap: on
line source
1 (ns com.aurellem.exp.pokemon2 "Here I find out how pokemon are stored in memory."3 (:use (com.aurellem.gb gb-driver items assembly util4 characters))5 (:import java.io.File)6 (:import [com.aurellem.gb.gb_driver SaveState]))9 (def pidgeot-lvl-36 (mid-game))12 (def pidgeot-lvl-37 (read-state "pidgeot-lvl-37"))15 (def pidgeot-lvl-38 (read-state "pidgeot-lvl-38"))18 (def pidgeot-lvl-39 (read-state "pidgeot-lvl-39"))21 (def pidgeot-lvl-40 (read-state "pidgeot-lvl-40"))24 (defn level-analysis []25 (apply common-differences26 (map (comp vec memory)27 [pidgeot-lvl-3628 pidgeot-lvl-3729 pidgeot-lvl-3830 pidgeot-lvl-3931 pidgeot-lvl-40])))33 ;; inconclusive -- implies that level is calculated from34 ;; some other values.37 (def name-pidgeotto (read-state "name-pidgeotto"))38 (def named-A (read-state "named-A"))39 (def named-B (read-state "named-B"))40 (def named-C (read-state "named-C"))41 (def named-D (read-state "named-D"))42 (def named-E (read-state "named-E"))43 (def named-F (read-state "named-F"))45 (defn name-analysis []46 (apply common-differences47 (map (comp vec memory)48 [named-A49 named-B50 named-C51 named-D52 named-E53 named-F])))55 ;; resluted in 3 separate locations that could56 ;; possibly hold the first letter of the pokemon's name58 0xCF4A59 0xD2EB60 0xCEED62 ;; try changing each of them65 (defn test-cf4a []66 (continue!67 (set-memory named-A 0xCF4A (character->character-code "Z"))))68 ;; result -- pidgeotto named "A"70 (defn test-d2eb []71 (continue!72 (set-memory named-A 0xD2EB (character->character-code "Z"))))73 ;; result -- pidgeotto named "Z"75 (defn test-ceed []76 (continue!77 (set-memory named-A 0xCEED (character->character-code "Z"))))78 ;; result -- pidgeotto named "A"80 (def sixth-pokemon-name-start 0xD2EB)83 (defn set-sixth-pokemon-name-first-character84 ([state character]85 (set-memory state sixth-pokemon-name-start86 (character->character-code character)))87 ([character]88 (set-sixth-pokemon-name-first-character @current-state89 character)))92 (def end-of-name-marker 0x50)93 (def max-name-length 10)94 (def name-width 11)96 (defn read-name [codes]97 (character-codes->str98 (take-while99 (partial not= end-of-name-marker) codes)))102 (defn sixth-pokemon-name [^SaveState state]103 (read-name104 (subvec (vec (memory state))105 sixth-pokemon-name-start106 (+ (inc max-name-length)107 sixth-pokemon-name-start))))109 (defn rename-sixth-pokemon110 ([^SaveState state new-name]111 (assert (< (count new-name) max-name-length))112 (set-memory-range state sixth-pokemon-name-start113 (concat (str->character-codes new-name)114 [end-of-name-marker])))115 ([new-name]116 (rename-sixth-pokemon @current-state new-name)))118 (defn print-text119 ([^SaveState state begin end]120 (dorun121 (map (fn [character-code line]122 (println123 (format "0x%04X: " line)124 (str (character-code->character character-code))))125 (subvec (vec (memory state)) begin end)126 (range begin end)))127 state)128 ([begin end]129 (print-text @current-state begin end)))131 (defn examine-name-memory []132 (print-text133 named-A134 (- sixth-pokemon-name-start 100)135 (+ sixth-pokemon-name-start 100)))137 ;; results:138 ;; 0xD287: end-of-name-sentinel139 ;; 0xD288: R140 ;; 0xD289: L141 ;; 0xD28A: M142 ;; 0xD28B: end-of-pokemon-name-sentinel143 ;; 0xD28C: end-of-name-sentinel144 ;; 0xD28D: end-of-name-sentinel145 ;; 0xD28E: end-of-name-sentinel146 ;; 0xD28F: end-of-name-sentinel147 ;; 0xD290: end-of-name-sentinel148 ;; 0xD291: end-of-name-sentinel149 ;; 0xD292: end-of-name-sentinel150 ;; 0xD293: R151 ;; 0xD294: L152 ;; 0xD295: M153 ;; 0xD296: end-of-pokemon-name-sentinel154 ;; 0xD297: end-of-name-sentinel155 ;; 0xD298: end-of-name-sentinel156 ;; 0xD299: end-of-name-sentinel157 ;; 0xD29A: end-of-name-sentinel158 ;; 0xD29B: end-of-name-sentinel159 ;; 0xD29C: end-of-name-sentinel160 ;; 0xD29D: end-of-name-sentinel161 ;; 0xD29E: R162 ;; 0xD29F: L163 ;; 0xD2A0: M164 ;; 0xD2A1: end-of-pokemon-name-sentinel165 ;; 0xD2A2: end-of-name-sentinel166 ;; 0xD2A3: end-of-name-sentinel167 ;; 0xD2A4: end-of-name-sentinel168 ;; 0xD2A5: end-of-name-sentinel169 ;; 0xD2A6: end-of-name-sentinel170 ;; 0xD2A7: end-of-name-sentinel171 ;; 0xD2A8: end-of-name-sentinel172 ;; 0xD2A9: R173 ;; 0xD2AA: L174 ;; 0xD2AB: M175 ;; 0xD2AC: end-of-pokemon-name-sentinel176 ;; 0xD2AD: end-of-name-sentinel177 ;; 0xD2AE: end-of-name-sentinel178 ;; 0xD2AF: end-of-name-sentinel179 ;; 0xD2B0: end-of-name-sentinel180 ;; 0xD2B1: end-of-name-sentinel181 ;; 0xD2B2: end-of-name-sentinel182 ;; 0xD2B3: end-of-name-sentinel183 ;; 0xD2B4: P184 ;; 0xD2B5: I185 ;; 0xD2B6: D186 ;; 0xD2B7: G187 ;; 0xD2B8: E188 ;; 0xD2B9: O189 ;; 0xD2BA: T190 ;; 0xD2BB: end-of-pokemon-name-sentinel191 ;; 0xD2BC: end-of-pokemon-name-sentinel192 ;; 0xD2BD: end-of-pokemon-name-sentinel193 ;; 0xD2BE: end-of-pokemon-name-sentinel194 ;; 0xD2BF: P195 ;; 0xD2C0: I196 ;; 0xD2C1: K197 ;; 0xD2C2: A198 ;; 0xD2C3: C199 ;; 0xD2C4: H200 ;; 0xD2C5: U201 ;; 0xD2C6: end-of-pokemon-name-sentinel202 ;; 0xD2C7: end-of-pokemon-name-sentinel203 ;; 0xD2C8: end-of-pokemon-name-sentinel204 ;; 0xD2C9: end-of-pokemon-name-sentinel205 ;; 0xD2CA: C206 ;; 0xD2CB: H207 ;; 0xD2CC: A208 ;; 0xD2CD: R209 ;; 0xD2CE: I210 ;; 0xD2CF: Z211 ;; 0xD2D0: A212 ;; 0xD2D1: R213 ;; 0xD2D2: D214 ;; 0xD2D3: end-of-pokemon-name-sentinel215 ;; 0xD2D4: end-of-pokemon-name-sentinel216 ;; 0xD2D5: V217 ;; 0xD2D6: E218 ;; 0xD2D7: N219 ;; 0xD2D8: U220 ;; 0xD2D9: S221 ;; 0xD2DA: A222 ;; 0xD2DB: U223 ;; 0xD2DC: R224 ;; 0xD2DD: end-of-pokemon-name-sentinel225 ;; 0xD2DE: end-of-pokemon-name-sentinel226 ;; 0xD2DF: end-of-pokemon-name-sentinel227 ;; 0xD2E0: P228 ;; 0xD2E1: R229 ;; 0xD2E2: I230 ;; 0xD2E3: M231 ;; 0xD2E4: E232 ;; 0xD2E5: A233 ;; 0xD2E6: P234 ;; 0xD2E7: E235 ;; 0xD2E8: end-of-pokemon-name-sentinel236 ;; 0xD2E9: end-of-pokemon-name-sentinel237 ;; 0xD2EA: end-of-pokemon-name-sentinel238 ;; 0xD2EB: A239 ;; 0xD2EC: end-of-pokemon-name-sentinel240 ;; 0xD2ED: S241 ;; 0xD2EE: T242 ;; 0xD2EF: E243 ;; 0xD2F0: R244 ;; 0xD2F1:245 ;; 0xD2F2: B246 ;; 0xD2F3: A247 ;; 0xD2F4: L248 ;; 0xD2F5: L249 ;; 0xD2F6:250 ;; 0xD2F7: A251 ;; 0xD2F8:252 ;; 0xD2F9:253 ;; 0xD2FA: end-of-name-sentinel254 ;; 0xD2FB: end-of-name-sentinel255 ;; 0xD2FC: A256 ;; 0xD2FD:257 ;; 0xD2FE: end-of-name-sentinel258 ;; 0xD2FF: end-of-name-sentinel259 ;; 0xD300: end-of-name-sentinel260 ;; 0xD301: end-of-name-sentinel261 ;; 0xD302: end-of-name-sentinel262 ;; 0xD303: end-of-name-sentinel263 ;; 0xD304: end-of-name-sentinel264 ;; 0xD305: end-of-name-sentinel265 ;; 0xD306: end-of-name-sentinel266 ;; 0xD307: end-of-name-sentinel267 ;; 0xD308: end-of-name-sentinel268 ;; 0xD309:269 ;; 0xD30A: w270 ;; 0xD30B:271 ;; 0xD30C: V272 ;; 0xD30D:273 ;; 0xD30E:274 ;; 0xD30F: K275 ;; 0xD310:276 ;; 0xD311:277 ;; 0xD312:278 ;; 0xD313: A279 ;; 0xD314:280 ;; 0xD315:281 ;; 0xD316:282 ;; 0xD317: i283 ;; 0xD318:284 ;; 0xD319:285 ;; 0xD31A: end-of-name-sentinel286 ;; 0xD31B: end-of-name-sentinel287 ;; 0xD31C:288 ;; 0xD31D:289 ;; 0xD31E:290 ;; 0xD31F:291 ;; 0xD320:292 ;; 0xD321:293 ;; 0xD322:294 ;; 0xD323:295 ;; 0xD324:296 ;; 0xD325:297 ;; 0xD326:298 ;; 0xD327:299 ;; 0xD328:300 ;; 0xD329:301 ;; 0xD32A:302 ;; 0xD32B:303 ;; 0xD32C:304 ;; 0xD32D:305 ;; 0xD32E:306 ;; 0xD32F:307 ;; 0xD330:308 ;; 0xD331: 9309 ;; 0xD332: end-of-name-sentinel310 ;; 0xD333: 9311 ;; 0xD334:312 ;; 0xD335: 9313 ;; 0xD336:314 ;; 0xD337: 9315 ;; 0xD338: end-of-name-sentinel316 ;; 0xD339: end-of-name-sentinel317 ;; 0xD33A: end-of-name-sentinel318 ;; 0xD33B: end-of-name-sentinel319 ;; 0xD33C: end-of-name-sentinel320 ;; 0xD33D: end-of-name-sentinel321 ;; 0xD33E: end-of-name-sentinel322 ;; 0xD33F: end-of-name-sentinel323 ;; 0xD340: end-of-name-sentinel324 ;; 0xD341: end-of-name-sentinel325 ;; 0xD342: end-of-name-sentinel326 ;; 0xD343: end-of-name-sentinel327 ;; 0xD344: end-of-name-sentinel328 ;; 0xD345: end-of-name-sentinel329 ;; 0xD346:330 ;; 0xD347:331 ;; 0xD348:332 ;; 0xD349: G333 ;; 0xD34A: A334 ;; 0xD34B: R335 ;; 0xD34C: Y336 ;; 0xD34D: end-of-pokemon-name-sentinel337 ;; 0xD34E: J340 ;; from this, it looks like the pokemon names are stored all341 ;; together in one location that begins at 0xD2B4 and342 ;; extends until 0xD2F5, with each name taking up 11 bytes.343 ;;344 ;; rival's name again clearly starts at 0xD349.347 (def pokemon-names-start 0xD2B4)350 ;; determine whether "number of pokemon in party"351 ;; might be kept in RAM and if so, where?353 (def six-pokemon (read-state "6-pokemon"))354 (def five-pokemon (read-state "5-pokemon"))355 (def four-pokemon (read-state "4-pokemon"))356 (def three-pokemon (read-state "3-pokemon"))357 (def two-pokemon (read-state "2-pokemon"))358 (def one-pokemon (read-state "1-pokemon"))361 (defn analyze-num-pokemon []362 (apply common-differences363 (map (comp vec memory)364 [one-pokemon365 two-pokemon366 three-pokemon367 four-pokemon368 five-pokemon369 six-pokemon])))371 ;; ;; results372 ;; ([53602 (1 2 3 4 5 6)]373 ;; [65314 (105 61 93 60 92 34)]374 ;; [55875 (34 36 43 52 7 0)]375 ;; [55876 (18 0 33 52 54 30)]376 ;; [49158 (197 194 77 117 174 134)]377 ;; [49160 (29 26 57 239 15 243)]378 ;; [49736 (74 93 34 89 91 59)]379 ;; [49162 (165 162 182 179 197 109)]380 ;; [49227 (187 105 204 5 90 238)]381 ;; [53067 (128 136 132 145 135 11)]382 ;; [53068 (147 131 141 136 128 7)]383 ;; [53069 (136 134 148 140 145 2)]384 ;; [49904 (2 11 10 3 27 12)]385 ;; [49172 (100 109 213 195 68 104)]386 ;; [65492 (11 103 128 160 19 56)]387 ;; [49173 (80 77 72 75 76 67)]388 ;; [49334 (8 10 11 5 3 1)]389 ;; [49335 (49 10 11 19 17 15)]390 ;; [49336 (8 10 11 5 3 1)]391 ;; [49720 (106 14 118 0 38 11)]392 ;; [65304 (32 88 19 114 106 33)]393 ;; [53561 (59 229 48 17 155 103)]394 ;; [55935 (6 5 4 3 2 1)])397 ;; two canidates : 0xD162 or 0xDA7F398 ;; they seem to always sum to 6...400 ;; try to set both of them when having only one pokemon.402 (defn change-party-number [^SaveState state new-num]403 (set-memory state 0xD162 new-num))405 ;; (continue! (change-party-number one-pokemon 3))406 ;; result -- can scroll down beyone first pokemon, finding407 ;; glitched pokemon in places where there were previously no408 ;; pokemon.411 (defn change-party-number* [^SaveState state new-num]412 (set-memory state 0xDA7F new-num))415 ;; (continue! (change-party-number* one-pokemon 3))416 ;; cannot widthdraw any pokemon from box 1 past the third417 ;; pokemon.419 (def party-number-address 0xD162)421 (defn party-number422 ([^SaveState state]423 (aget (memory state) party-number-address))424 ([] (party-number @current-state)))426 (def pokemon-in-box-1-address 0xDA7F)428 (defn party-names429 ([^SaveState state]430 (let [raw-names431 (subvec (vec (memory state))432 pokemon-names-start433 (+ pokemon-names-start434 (* name-width 6)))]435 (map436 read-name437 (take438 (party-number state)439 (partition name-width440 raw-names)))))441 ([] (party-names @current-state)))444 (defn rename-pokemon445 ([^SaveState state n new-name]446 (assert (<= 0 n (dec (party-number state))))447 (assert (<= (count new-name) max-name-length))448 (set-memory-range449 state450 (+ (* n name-width) pokemon-names-start)451 (concat (str->character-codes new-name) [end-of-name-marker])))452 ([n new-name]453 (rename-pokemon @current-state n new-name)))455 ;; on further analysis, it appears that the original456 ;; trainer info for each pokemon is also stored together,457 ;; starting at 0xD272 and continuing to 0xD2B3, with458 ;; 11 bytes reserved for each OT name.460 (def OT-start 0xD272)462 (defn original-trainers463 ([^SaveState state]464 (let [raw-names465 (subvec (vec (memory state))466 OT-start467 (+ OT-start468 (* name-width 6)))]469 (map read-name470 (take (party-number state)471 (partition name-width raw-names)))))472 ([] (original-trainers @current-state)))474 (defn set-original-trainer475 "Set the OT name for a pokemon.476 Note that a pokemon is still considered 'yours' if477 the OT ID is the same as your own."478 ([^SaveState state n new-name]479 (assert (<= 0 n (dec (party-number state))))480 (assert (<= (count new-name) max-name-length))481 (set-memory-range482 state483 (+ (* n name-width) OT-start)484 (concat (str->character-codes new-name) [end-of-name-marker])))485 ([n new-name]486 (set-original-trainer @current-state n new-name)))488 ;; PIKACHU stops following if you set it's OT to another name489 ;; and then back to you own.490 ;; But not if you set it to your own name, obviously.495 ;; OT ID Numbers.496 ;; My own id is 05195. A quick search of memory between497 ;; 0xD162 and 0xD31B revealed the pattern 0x144B exactly498 ;; six times.500 ;; the locations were:502 (def OT-ID-addresses [0xD176 0xD1A2 0xD1CE 0xD1FA 0xD228 0xD252])505 (defn set-pokemon-id506 ([^SaveState state n new-id]507 (assert (<= 0 n (dec (party-number state))))508 (assert (<= 0 new-id 0xFFFF))509 (set-memory-range510 state511 (OT-ID-addresses n)512 [(bit-shift-right (bit-and new-id 0xFF00) 8)513 (bit-and new-id 0xFF)514 ]))515 ([n new-id]516 (set-pokemon-id @current-state n new-id)))522 (defn get-pokemon-1-info523 ([state]524 (subvec (vec (memory state))525 0xD162 0xD197))526 ([] (get-pokemon-1-info @current-state)))528 (def baseline (File. "/home/r/baseline-poke"))533 (import java.io.File)535 (defn set-baseline [state]536 (clojure.java.io/copy537 (with-out-str (print-listing state 0xD162 0xD197))538 baseline))540 (defn compare-pokemon541 ([state]542 (let [target (File. "/home/r/temp-poke")]543 (clojure.java.io/copy544 (with-out-str (print-listing state 0xD162 0xD197))545 target)546 (println (:out547 (clojure.java.shell/sh "diff"548 (.getCanonicalPath baseline)549 (.getCanonicalPath target))))))550 ([] (compare-pokemon @current-state)))553 (defn crazy-pid []554 (read-state "crazy-pidgeot"))