annotate org/rom.org @ 499:8b8053ccb33c

generated graphical representation of the gb color map.
author Robert McIntyre <rlm@mit.edu>
date Tue, 12 Jun 2012 03:36:47 -0500
parents 9a7fae5afd8f
children
rev   line source
ocsenave@311 1 #+title: Notes on Deconstructing Pokemon Yellow
ocsenave@311 2 #+author: Dylan Holmes
ocsenave@311 3 #+email: rlm@mit.edu
ocsenave@419 4 #+description: A detailed explication of Pok\eacute{}mon Yellow, helped by Clojure.
ocsenave@419 5 #+keywords: pokemon, pokemon yellow, rom, gameboy, assembly, hex, pointers, clojure
ocsenave@311 6 #+SETUPFILE: ../../aurellem/org/setup.org
ocsenave@311 7 #+INCLUDE: ../../aurellem/org/level-0.org
ocsenave@311 8 #+BABEL: :exports both :noweb yes :cache no :mkdirp yes
ocsenave@471 9 #+OPTIONS: num:2
ocsenave@471 10
ocsenave@311 11
ocsenave@346 12 # about map headers http://datacrystal.romhacking.net/wiki/Pokemon_Red/Blue:Notes
ocsenave@346 13 # map headers Yellow http://www.pokecommunity.com/archive/index.php/t-235311.html
ocsenave@312 14 # pokedollar: U+20B1
ocsenave@347 15 * Introduction
ocsenave@470 16 This article contains the results of my investigations with
ocsenave@470 17 Pok\eacute{}mon Yellow as I searched for interesting
ocsenave@470 18 data in the ROM. By using the Clojure language interface
ocsenave@470 19 written by Robert[fn::This Clojure interface will be published to aurellem.org soon.], I
ocsenave@470 20 was able to interact with the game in real-time, sending commands and
ocsenave@470 21 gathering data. The result is a manifestly accurate map of
ocsenave@470 22 Pok\eacute{}mon Yellow; every result
ocsenave@470 23 comes with runnable code that /works/. You can see the code and the output of
ocsenave@470 24 every function and confirm for yourself that they are all correct. I
ocsenave@470 25 hope you like the result!
ocsenave@470 26
ocsenave@470 27 To orient yourself, you can look for a specific topic in the table of contents
ocsenave@470 28 above, or browse the [[#sec-9-1][map of the ROM]], below.
ocsenave@470 29
ocsenave@470 30
ocsenave@471 31 If you have any questions or comments, please e-mail =rlm@mit.edu=.
ocsenave@470 32
ocsenave@347 33
ocsenave@348 34 ** COMMENT Getting linguistic data: names, words, etc.
ocsenave@348 35
ocsenave@348 36 Some of the simplest data
ocsenave@348 37
ocsenave@348 38
ocsenave@348 39 One of the simplest data structures in the Pok\eacute{} ROM is an
ocsenave@348 40 unbroken list of strings that either (a) all have a specific length,
ocsenave@348 41 or (b) are all separated by the same character.
ocsenave@348 42
ocsenave@348 43 Because lots of good data has this format, we'll start by writing a
ocsenave@348 44 template function to extract it:
ocsenave@348 45
ocsenave@348 46 #+name: hxc-thunks
ocsenave@348 47 #+begin_src clojure :results silent
ocsenave@348 48 (defn hxc-thunk
ocsenave@348 49 "Creates a thunk (nullary fn) that grabs data in a certain region of rom and
ocsenave@348 50 splits it into a collection by 0x50. If rom is not supplied, uses the
ocsenave@348 51 original rom data."
ocsenave@348 52 [start length]
ocsenave@348 53 (fn self
ocsenave@348 54 ([rom]
ocsenave@348 55 (take-nth 2
ocsenave@348 56 (partition-by #(= % 0x50)
ocsenave@348 57 (take length
ocsenave@348 58 (drop start rom)))))
ocsenave@348 59 ([]
ocsenave@348 60 (self com.aurellem.gb.gb-driver/original-rom))))
ocsenave@348 61
ocsenave@348 62 (def hxc-thunk-words
ocsenave@348 63 "Same as hxc-thunk, except it interprets the rom data as characters,
ocsenave@348 64 returning a collection of strings."
ocsenave@348 65 (comp
ocsenave@348 66 (partial comp (partial map character-codes->str))
ocsenave@348 67 hxc-thunk))
ocsenave@348 68
ocsenave@348 69 #+end_src
ocsenave@348 70
ocsenave@348 71
ocsenave@348 72 * Pok\eacute{}mon I
ocsenave@348 73 ** Names of each species
ocsenave@348 74 The names of the Pok\eacute{}mon species are stored in
ocsenave@348 75 ROM@E8000. This name list is interesting, for a number of reasons:
ocsenave@348 76 - The names are stored in [[ ][internal order]] rather than in the familiar
ocsenave@348 77 Pok\eacute{}dex order. This seemingly random order probably represents the order in which the authors created or
ocsenave@348 78 programmed in the Pok\eacute{}mon; it's used throughout the game.
ocsenave@348 79 - There is enough space allocated for 190 Pok\eacute{}mon. As I
ocsenave@348 80 understand it, there were originally going to be 190 Pok\eacute{}mon
ocsenave@348 81 in Generation I, but the creators decided to defer some to
ocsenave@348 82 Generation II. This explains why many Gen I and Gen II Pok\eacute{}mon
ocsenave@348 83 have the same aesthetic feel.
ocsenave@348 84 - The list is pockmarked with random gaps, due to the strange internal
ocsenave@348 85 ordering
ocsenave@348 86 and the 39 unused spaces [fn::190 allocated spaces minus 151 true Pok\eacute{}mon]. These missing spaces are filled with the
ocsenave@348 87 placeholder name =MISSINGNO.= (\ldquo{}Missing number\rdquo{}).
ocsenave@348 88
ocsenave@348 89 Each name is exactly ten letters long; whenever a name would be too short, the extra
ocsenave@348 90 space is padded with the character 0x50.
ocsenave@348 91
ocsenave@348 92 *** See the data
ocsenave@348 93
ocsenave@348 94 Here you can see the raw data in three stages: in the first stage, we
ocsenave@348 95 just grab the first few bytes starting from position 0xE8000. In the
ocsenave@371 96 second stage, we partition the bytes into ten-letter chunks to show you
ocsenave@348 97 where the names begin and end. In the final stage, we convert each
ocsenave@348 98 byte into the letter it represents using the =character-codes->str=
ocsenave@348 99 function. (0x50 is rendered as the symbol \ldquo{} =#= \rdquo{} for
ocsenave@348 100 ease of reading).
ocsenave@348 101
ocsenave@348 102 #+begin_src clojure :exports both :cache no :results output
ocsenave@348 103 (ns com.aurellem.gb.hxc
ocsenave@348 104 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@348 105 constants))
ocsenave@348 106 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@348 107
ocsenave@371 108
ocsenave@348 109 (println (take 100 (drop 0xE8000 (rom))))
ocsenave@348 110
ocsenave@348 111 (println (partition 10 (take 100 (drop 0xE8000 (rom)))))
ocsenave@348 112
ocsenave@348 113 (println (character-codes->str (take 100 (drop 0xE8000 (rom)))))
ocsenave@348 114
ocsenave@348 115
ocsenave@348 116 #+end_src
ocsenave@348 117
ocsenave@348 118 #+results:
ocsenave@348 119 : (145 135 152 131 142 141 80 80 80 80 138 128 141 134 128 146 138 135 128 141 141 136 131 142 145 128 141 239 80 80 130 139 132 133 128 136 145 152 80 80 146 143 132 128 145 142 150 80 80 80 149 142 139 147 142 145 129 80 80 80 141 136 131 142 138 136 141 134 80 80 146 139 142 150 129 145 142 80 80 80 136 149 152 146 128 148 145 80 80 80 132 151 132 134 134 148 147 142 145 80)
ocsenave@348 120 : ((145 135 152 131 142 141 80 80 80 80) (138 128 141 134 128 146 138 135 128 141) (141 136 131 142 145 128 141 239 80 80) (130 139 132 133 128 136 145 152 80 80) (146 143 132 128 145 142 150 80 80 80) (149 142 139 147 142 145 129 80 80 80) (141 136 131 142 138 136 141 134 80 80) (146 139 142 150 129 145 142 80 80 80) (136 149 152 146 128 148 145 80 80 80) (132 151 132 134 134 148 147 142 145 80))
ocsenave@348 121 : RHYDON####KANGASKHANNIDORAN♂##CLEFAIRY##SPEAROW###VOLTORB###NIDOKING##SLOWBRO###IVYSAUR###EXEGGUTOR#
ocsenave@348 122
ocsenave@348 123
ocsenave@348 124 *** Automatically grab the data.
ocsenave@348 125
ocsenave@348 126 #+name: pokenames
ocsenave@348 127 #+begin_src clojure
ocsenave@348 128
ocsenave@348 129 (defn hxc-pokenames-raw
ocsenave@348 130 "The hardcoded names of the 190 species in memory. List begins at
ocsenave@348 131 ROM@E8000. Although names in memory are padded with 0x50 to be 10 characters
ocsenave@348 132 long, these names are stripped of padding. See also, hxc-pokedex-names"
ocsenave@348 133 ([]
ocsenave@348 134 (hxc-pokenames-raw com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 135 ([rom]
ocsenave@348 136 (let [count-species 190
ocsenave@348 137 name-length 10]
ocsenave@348 138 (map character-codes->str
ocsenave@348 139 (partition name-length
ocsenave@348 140 (map #(if (= 0x50 %) 0x00 %)
ocsenave@348 141 (take (* count-species name-length)
ocsenave@348 142 (drop 0xE8000
ocsenave@348 143 rom))))))))
ocsenave@348 144 (def hxc-pokenames
ocsenave@348 145 (comp
ocsenave@348 146 (partial map format-name)
ocsenave@348 147 hxc-pokenames-raw))
ocsenave@348 148
ocsenave@348 149
ocsenave@348 150
ocsenave@348 151
ocsenave@348 152 (defn hxc-pokedex-names
ocsenave@411 153 "The names of the pokemon in hardcoded pokedex order. List of the
ocsenave@411 154 pokedex numbers of each pokemon (in internal order) begins at
ocsenave@348 155 ROM@410B1. See also, hxc-pokenames."
ocsenave@348 156 ([] (hxc-pokedex-names
ocsenave@348 157 com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 158 ([rom]
ocsenave@348 159 (let [names (hxc-pokenames rom)]
ocsenave@348 160 (#(mapv %
ocsenave@348 161 ((comp range count keys) %))
ocsenave@348 162 (zipmap
ocsenave@348 163 (take (count names)
ocsenave@348 164 (drop 0x410b1 rom))
ocsenave@348 165
ocsenave@348 166 names)))))
ocsenave@348 167
ocsenave@348 168 #+end_src
ocsenave@348 169
ocsenave@348 170
ocsenave@348 171
ocsenave@348 172 ** Generic species information
ocsenave@348 173
ocsenave@348 174 #+name: pokebase
ocsenave@348 175 #+begin_src clojure
ocsenave@348 176 (defn hxc-pokemon-base
ocsenave@348 177 ([] (hxc-pokemon-base com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 178 ([rom]
ocsenave@348 179 (let [entry-size 28
ocsenave@371 180
ocsenave@348 181 pokemon (rest (hxc-pokedex-names))
ocsenave@371 182 pkmn-count (inc(count pokemon))
ocsenave@348 183 types (apply assoc {}
ocsenave@348 184 (interleave
ocsenave@348 185 (range)
ocsenave@348 186 pkmn-types)) ;;!! softcoded
ocsenave@348 187 moves (apply assoc {}
ocsenave@348 188 (interleave
ocsenave@348 189 (range)
ocsenave@348 190 (map format-name
ocsenave@348 191 (hxc-move-names rom))))
ocsenave@348 192 machines (hxc-machines)
ocsenave@348 193 ]
ocsenave@348 194 (zipmap
ocsenave@348 195 pokemon
ocsenave@348 196 (map
ocsenave@348 197 (fn [[n
ocsenave@348 198 rating-hp
ocsenave@348 199 rating-atk
ocsenave@348 200 rating-def
ocsenave@348 201 rating-speed
ocsenave@348 202 rating-special
ocsenave@348 203 type-1
ocsenave@348 204 type-2
ocsenave@473 205 rarity ;; catch rate
ocsenave@473 206 rating-xp ;; base exp yield
ocsenave@348 207 pic-dimensions ;; tile_width|tile_height (8px/tile)
ocsenave@348 208 ptr-pic-obverse-1
ocsenave@348 209 ptr-pic-obverse-2
ocsenave@348 210 ptr-pic-reverse-1
ocsenave@348 211 ptr-pic-reverse-2
ocsenave@473 212 move-1 ;; attacks known at level 0 [i.e. by default]
ocsenave@473 213 move-2 ;; (0 for none)
ocsenave@348 214 move-3
ocsenave@348 215 move-4
ocsenave@348 216 growth-rate
ocsenave@348 217 &
ocsenave@348 218 TMs|HMs]]
ocsenave@348 219 (let
ocsenave@348 220 [base-moves
ocsenave@348 221 (mapv moves
ocsenave@348 222 ((comp
ocsenave@348 223 ;; since the game uses zero as a delimiter,
ocsenave@348 224 ;; it must also increment all move indices by 1.
ocsenave@348 225 ;; heren we decrement to correct this.
ocsenave@348 226 (partial map dec)
ocsenave@348 227 (partial take-while (comp not zero?)))
ocsenave@348 228 [move-1 move-2 move-3 move-4]))
ocsenave@348 229
ocsenave@348 230 types
ocsenave@348 231 (set (list (types type-1)
ocsenave@348 232 (types type-2)))
ocsenave@348 233 TMs|HMs
ocsenave@348 234 (map
ocsenave@348 235 (comp
ocsenave@348 236 (partial map first)
ocsenave@348 237 (partial remove (comp zero? second)))
ocsenave@348 238 (split-at
ocsenave@348 239 50
ocsenave@348 240 (map vector
ocsenave@348 241 (rest(range))
ocsenave@348 242 (reduce concat
ocsenave@348 243 (map
ocsenave@348 244 #(take 8
ocsenave@348 245 (concat (bit-list %)
ocsenave@348 246 (repeat 0)))
ocsenave@348 247
ocsenave@348 248 TMs|HMs)))))
ocsenave@348 249
ocsenave@348 250 TMs (vec (first TMs|HMs))
ocsenave@348 251 HMs (take 5 (map (partial + -50) (vec (second TMs|HMs))))
ocsenave@348 252
ocsenave@348 253
ocsenave@348 254 ]
ocsenave@348 255
ocsenave@348 256
ocsenave@348 257 {:dex# n
ocsenave@348 258 :base-moves base-moves
ocsenave@348 259 :types types
ocsenave@348 260 :TMs TMs
ocsenave@348 261 :HMs HMs
ocsenave@348 262 :base-hp rating-hp
ocsenave@348 263 :base-atk rating-atk
ocsenave@348 264 :base-def rating-def
ocsenave@348 265 :base-speed rating-speed
ocsenave@348 266 :base-special rating-special
ocsenave@348 267 :o0 pic-dimensions
ocsenave@348 268 :o1 ptr-pic-obverse-1
ocsenave@348 269 :o2 ptr-pic-obverse-2
ocsenave@348 270 }))
ocsenave@348 271
ocsenave@348 272 (partition entry-size
ocsenave@348 273 (take (* entry-size pkmn-count)
ocsenave@348 274 (drop 0x383DE
ocsenave@348 275 rom))))))))
ocsenave@348 276
ocsenave@348 277 #+end_src
ocsenave@348 278
ocsenave@348 279
ocsenave@348 280 ** Pok\eacute{}mon evolutions
ocsenave@348 281 #+name: evolution-header
ocsenave@348 282 #+begin_src clojure
ocsenave@348 283 (defn format-evo
ocsenave@348 284 "Parse a sequence of evolution data, returning a map. First is the
ocsenave@348 285 method: 0 = end-evolution-data. 1 = level-up, 2 = item, 3 = trade. Next is an item id, if the
ocsenave@348 286 method of evolution is by item (only stones will actually make pokemon
ocsenave@348 287 evolve, for some auxillary reason.) Finally, the minimum level for
ocsenave@348 288 evolution to occur (level 1 means no limit, which is used for trade
ocsenave@348 289 and item evolutions), followed by the internal id of the pokemon
ocsenave@348 290 into which to evolve. Hence, level up and trade evolutions are
ocsenave@348 291 described with 3
ocsenave@348 292 bytes; item evolutions with four."
ocsenave@348 293 [coll]
ocsenave@348 294 (let [method (first coll)]
ocsenave@348 295 (cond (empty? coll) []
ocsenave@348 296 (= 0 method) [] ;; just in case
ocsenave@348 297 (= 1 method) ;; level-up evolution
ocsenave@348 298 (conj (format-evo (drop 3 coll))
ocsenave@348 299 {:method :level-up
ocsenave@348 300 :min-level (nth coll 1)
ocsenave@348 301 :into (dec (nth coll 2))})
ocsenave@348 302
ocsenave@348 303 (= 2 method) ;; item evolution
ocsenave@348 304 (conj (format-evo (drop 4 coll))
ocsenave@348 305 {:method :item
ocsenave@348 306 :item (dec (nth coll 1))
ocsenave@348 307 :min-level (nth coll 2)
ocsenave@348 308 :into (dec (nth coll 3))})
ocsenave@348 309
ocsenave@348 310 (= 3 method) ;; trade evolution
ocsenave@348 311 (conj (format-evo (drop 3 coll))
ocsenave@348 312 {:method :trade
ocsenave@348 313 :min-level (nth coll 1) ;; always 1 for trade.
ocsenave@348 314 :into (dec (nth coll 2))}))))
ocsenave@348 315
ocsenave@348 316
ocsenave@348 317 (defn hxc-ptrs-evolve
ocsenave@348 318 "A hardcoded collection of 190 pointers to alternating evolution/learnset data,
ocsenave@348 319 in internal order."
ocsenave@348 320 ([]
ocsenave@348 321 (hxc-ptrs-evolve com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 322 ([rom]
ocsenave@348 323 (let [
ocsenave@348 324 pkmn-count (count (hxc-pokenames-raw)) ;; 190
ocsenave@348 325 ptrs
ocsenave@348 326 (map (fn [[a b]] (low-high a b))
ocsenave@348 327 (partition 2
ocsenave@348 328 (take (* 2 pkmn-count)
ocsenave@348 329 (drop 0x3b1e5 rom))))]
ocsenave@348 330 (map (partial + 0x34000) ptrs)
ocsenave@348 331
ocsenave@348 332 )))
ocsenave@348 333 #+end_src
ocsenave@348 334
ocsenave@348 335 #+name:evolution
ocsenave@348 336 #+begin_src clojure
ocsenave@348 337
ocsenave@348 338 (defn hxc-evolution
ocsenave@348 339 "Hardcoded evolution data in memory. The data exists at ROM@34000,
ocsenave@348 340 sorted by internal order. Pointers to the data exist at ROM@3B1E5; see also, hxc-ptrs-evolve."
ocsenave@348 341 ([] (hxc-evolution com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 342 ([rom]
ocsenave@348 343 (apply assoc {}
ocsenave@348 344 (interleave
ocsenave@348 345 (hxc-pokenames rom)
ocsenave@348 346 (map
ocsenave@348 347 (comp
ocsenave@348 348 format-evo
ocsenave@348 349 (partial take-while (comp not zero?))
ocsenave@348 350 #(drop % rom))
ocsenave@348 351 (hxc-ptrs-evolve rom)
ocsenave@348 352 )))))
ocsenave@348 353
ocsenave@348 354 (defn hxc-evolution-pretty
ocsenave@348 355 "Like hxc-evolution, except it uses the names of items and pokemon
ocsenave@348 356 --- grabbed from ROM --- rather than their numerical identifiers."
ocsenave@348 357 ([] (hxc-evolution-pretty com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 358 ([rom]
ocsenave@348 359 (let
ocsenave@348 360 [poke-names (vec (hxc-pokenames rom))
ocsenave@348 361 item-names (vec (hxc-items rom))
ocsenave@348 362 use-names
ocsenave@348 363 (fn [m]
ocsenave@348 364 (loop [ks (keys m) new-map m]
ocsenave@348 365 (let [k (first ks)]
ocsenave@348 366 (cond (nil? ks) new-map
ocsenave@348 367 (= k :into)
ocsenave@348 368 (recur
ocsenave@348 369 (next ks)
ocsenave@348 370 (assoc new-map
ocsenave@348 371 :into
ocsenave@348 372 (poke-names
ocsenave@348 373 (:into
ocsenave@348 374 new-map))))
ocsenave@348 375 (= k :item)
ocsenave@348 376 (recur
ocsenave@348 377 (next ks)
ocsenave@348 378 (assoc new-map
ocsenave@348 379 :item
ocsenave@348 380 (item-names
ocsenave@348 381 (:item new-map))))
ocsenave@348 382 :else
ocsenave@348 383 (recur
ocsenave@348 384 (next ks)
ocsenave@348 385 new-map)
ocsenave@348 386 ))))]
ocsenave@348 387
ocsenave@348 388 (into {}
ocsenave@348 389 (map (fn [[pkmn evo-coll]]
ocsenave@348 390 [pkmn (map use-names evo-coll)])
ocsenave@348 391 (hxc-evolution rom))))))
ocsenave@348 392
ocsenave@348 393
ocsenave@348 394 #+end_src
ocsenave@348 395
ocsenave@348 396
ocsenave@348 397 ** Level-up moves (learnsets)
ocsenave@348 398 #+name: learnsets
ocsenave@348 399 #+begin_src clojure
ocsenave@348 400
ocsenave@348 401
ocsenave@348 402 (defn hxc-learnsets
ocsenave@348 403 "Hardcoded map associating pokemon names to lists of pairs [lvl
ocsenave@348 404 move] of abilities they learn as they level up. The data
ocsenave@348 405 exists at ROM@34000, sorted by internal order. Pointers to the data
ocsenave@348 406 exist at ROM@3B1E5; see also, hxc-ptrs-evolve"
ocsenave@348 407 ([] (hxc-learnsets com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 408 ([rom]
ocsenave@348 409 (apply assoc
ocsenave@348 410 {}
ocsenave@348 411 (interleave
ocsenave@348 412 (hxc-pokenames rom)
ocsenave@348 413 (map (comp
ocsenave@348 414 (partial map
ocsenave@348 415 (fn [[lvl mv]] [lvl (dec mv)]))
ocsenave@348 416 (partial partition 2)
ocsenave@348 417 ;; keep the learnset data
ocsenave@348 418 (partial take-while (comp not zero?))
ocsenave@348 419 ;; skip the evolution data
ocsenave@348 420 rest
ocsenave@348 421 (partial drop-while (comp not zero?)))
ocsenave@348 422 (map #(drop % rom)
ocsenave@348 423 (hxc-ptrs-evolve rom)))))))
ocsenave@348 424
ocsenave@348 425 (defn hxc-learnsets-pretty
ocsenave@348 426 "Live hxc-learnsets except it reports the name of each move --- as
ocsenave@348 427 it appears in rom --- rather than the move index."
ocsenave@348 428 ([] (hxc-learnsets-pretty com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 429 ([rom]
ocsenave@348 430 (let [moves (vec(map format-name (hxc-move-names)))]
ocsenave@348 431 (into {}
ocsenave@348 432 (map (fn [[pkmn learnset]]
ocsenave@348 433 [pkmn (map (fn [[lvl mv]] [lvl (moves mv)])
ocsenave@348 434 learnset)])
ocsenave@348 435 (hxc-learnsets rom))))))
ocsenave@348 436
ocsenave@348 437
ocsenave@348 438
ocsenave@348 439 #+end_src
ocsenave@348 440
ocsenave@348 441
ocsenave@348 442
ocsenave@348 443 * Pok\eacute{}mon II : the Pok\eacute{}dex
ocsenave@348 444 ** Species vital stats
ocsenave@348 445 #+name: dex-stats
ocsenave@348 446 #+begin_src clojure
ocsenave@348 447 (defn hxc-pokedex-stats
ocsenave@348 448 "The hardcoded pokedex stats (species height weight) in memory. List
ocsenave@348 449 begins at ROM@40687"
ocsenave@348 450 ([] (hxc-pokedex-stats com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 451 ([rom]
ocsenave@348 452 (let [pokedex-names (zipmap (range) (hxc-pokedex-names rom))
ocsenave@348 453 pkmn-count (count pokedex-names)
ocsenave@348 454 ]
ocsenave@348 455 ((fn capture-stats
ocsenave@348 456 [n stats data]
ocsenave@348 457 (if (zero? n) stats
ocsenave@348 458 (let [[species
ocsenave@348 459 [_
ocsenave@348 460 height-ft
ocsenave@348 461 height-in
ocsenave@348 462 weight-1
ocsenave@348 463 weight-2
ocsenave@348 464 _
ocsenave@348 465 dex-ptr-1
ocsenave@348 466 dex-ptr-2
ocsenave@348 467 dex-bank
ocsenave@348 468 _
ocsenave@348 469 & data]]
ocsenave@348 470 (split-with (partial not= 0x50) data)]
ocsenave@348 471 (recur (dec n)
ocsenave@348 472 (assoc stats
ocsenave@348 473 (pokedex-names (- pkmn-count (dec n)))
ocsenave@348 474 {:species
ocsenave@348 475 (format-name (character-codes->str species))
ocsenave@348 476 :height-ft
ocsenave@348 477 height-ft
ocsenave@348 478 :height-in
ocsenave@348 479 height-in
ocsenave@348 480 :weight
ocsenave@348 481 (/ (low-high weight-1 weight-2) 10.)
ocsenave@348 482
ocsenave@348 483 ;; :text
ocsenave@348 484 ;; (character-codes->str
ocsenave@348 485 ;; (take-while
ocsenave@348 486 ;; (partial not= 0x50)
ocsenave@348 487 ;; (drop
ocsenave@348 488 ;; (+ 0xB8000
ocsenave@348 489 ;; -0x4000
ocsenave@348 490 ;; (low-high dex-ptr-1 dex-ptr-2))
ocsenave@348 491 ;; rom)))
ocsenave@348 492 })
ocsenave@348 493
ocsenave@348 494 data)
ocsenave@348 495
ocsenave@348 496
ocsenave@348 497 )))
ocsenave@348 498
ocsenave@348 499 pkmn-count
ocsenave@348 500 {}
ocsenave@348 501 (drop 0x40687 rom))) ))
ocsenave@348 502 #+end_src
ocsenave@348 503
ocsenave@411 504 #+results: dex-stats
ocsenave@411 505 : #'com.aurellem.gb.hxc/hxc-pokedex-stats
ocsenave@411 506
ocsenave@348 507 ** Species synopses
ocsenave@348 508
ocsenave@348 509 #+name: dex-text
ocsenave@348 510 #+begin_src clojure
ocsenave@348 511 (def hxc-pokedex-text-raw
ocsenave@348 512 "The hardcoded pokedex entries in memory. List begins at
ocsenave@348 513 ROM@B8000, shortly before move names."
ocsenave@348 514 (hxc-thunk-words 0xB8000 14754))
ocsenave@348 515
ocsenave@348 516
ocsenave@348 517
ocsenave@348 518
ocsenave@348 519 (defn hxc-pokedex-text
ocsenave@348 520 "The hardcoded pokedex entries in memory, presented as an
ocsenave@348 521 associative hash map. List begins at ROM@B8000."
ocsenave@348 522 ([] (hxc-pokedex-text com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 523 ([rom]
ocsenave@348 524 (zipmap
ocsenave@348 525 (hxc-pokedex-names rom)
ocsenave@348 526 (cons nil ;; for missingno.
ocsenave@348 527 (hxc-pokedex-text-raw rom)))))
ocsenave@348 528 #+end_src
ocsenave@348 529
ocsenave@348 530
ocsenave@348 531 ** Pok\eacute{}mon cries
ocsenave@471 532 *** See the data
ocsenave@471 533
ocsenave@471 534 Here, you can see that each Pok\eacute{}mon's cry data consists of
ocsenave@471 535 three bytes: the =cry-id=, which is the basic sound byte to use, the
ocsenave@471 536 =pitch=, which determines how high or low to make the sound byte, and
ocsenave@471 537 the =length=, which is the amount of the sound byte to play.
ocsenave@471 538
ocsenave@471 539 Even though there are only a few different basic sound bytes (cry
ocsenave@471 540 ids) to build from, by varying the pitch and length,
ocsenave@471 541 you can create a wide variety of different Pok\eacute{}mon cries.
ocsenave@471 542
ocsenave@471 543 #+begin_src clojure :exports both :cache no :results output
ocsenave@471 544 (ns com.aurellem.gb.hxc
ocsenave@471 545 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@471 546 constants))
ocsenave@471 547 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@471 548
ocsenave@471 549 (->>
ocsenave@471 550 (rom)
ocsenave@471 551 (drop 0x39462)
ocsenave@471 552 (take 12)
ocsenave@471 553 (println))
ocsenave@471 554
ocsenave@471 555 (->>
ocsenave@471 556 (rom)
ocsenave@471 557 (drop 0x39462)
ocsenave@471 558 (take 12)
ocsenave@471 559 (partition 3)
ocsenave@471 560 (map vec)
ocsenave@471 561 (println))
ocsenave@471 562
ocsenave@471 563 (->>
ocsenave@471 564 (rom)
ocsenave@471 565 (drop 0x39462)
ocsenave@471 566 (take 12)
ocsenave@471 567 (partition 3)
ocsenave@471 568 (map
ocsenave@471 569 (fn [[id pitch length]]
ocsenave@471 570 {:cry-id id :pitch pitch :length length}))
ocsenave@471 571 (println))
ocsenave@471 572
ocsenave@471 573 #+end_src
ocsenave@471 574
ocsenave@471 575 #+results:
ocsenave@471 576 : (17 0 128 3 0 128 0 0 128 25 204 1)
ocsenave@471 577 : ([17 0 128] [3 0 128] [0 0 128] [25 204 1])
ocsenave@471 578 : ({:cry-id 17, :pitch 0, :length 128} {:cry-id 3, :pitch 0, :length 128} {:cry-id 0, :pitch 0, :length 128} {:cry-id 25, :pitch 204, :length 1})
ocsenave@471 579
ocsenave@471 580
ocsenave@471 581 It is interesting to note which Pok\eacute{}mon use the same basic
ocsenave@471 582 =cry-id= --- I call these /cry groups/. Here, you can see which
ocsenave@471 583 Pok\eacute{}mon belong to the same cry group.
ocsenave@471 584
ocsenave@471 585 #+begin_src clojure :exports both :cache no :results output
ocsenave@471 586 (ns com.aurellem.gb.hxc
ocsenave@471 587 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@471 588 constants))
ocsenave@471 589 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@471 590
ocsenave@471 591 (println "POKEMON CRY GROUPS")
ocsenave@471 592 (doall
ocsenave@471 593 (map println
ocsenave@471 594 (let [cry-id
ocsenave@471 595 (->>
ocsenave@471 596 (rom)
ocsenave@471 597 (drop 0x39462) ;; get the cry data
ocsenave@471 598 (partition 3) ;; partition it into groups of three
ocsenave@471 599 (map first) ;; keep only the first item, the cry-id
ocsenave@471 600 (zipmap (hxc-pokenames)) ;; associate each pokemon with its cry-id
ocsenave@471 601 )]
ocsenave@471 602
ocsenave@471 603 (->> (hxc-pokenames) ;; start with the list of pokemon
ocsenave@471 604 (remove (partial = :missingno.)) ;; remove missingnos
ocsenave@471 605 (sort-by cry-id)
ocsenave@471 606 (partition-by cry-id)
ocsenave@471 607 (map vec)))))
ocsenave@471 608
ocsenave@471 609 #+end_src
ocsenave@471 610
ocsenave@471 611 #+results:
ocsenave@471 612 #+begin_example
ocsenave@471 613 POKEMON CRY GROUPS
ocsenave@471 614 [:nidoran♂ :sandshrew :sandslash :nidorino]
ocsenave@471 615 [:nidoran♀ :nidorina]
ocsenave@471 616 [:slowpoke]
ocsenave@471 617 [:kangaskhan]
ocsenave@471 618 [:rhyhorn :magmar :charmander :charmeleon :charizard]
ocsenave@471 619 [:grimer :snorlax]
ocsenave@471 620 [:voltorb :electabuzz :electrode]
ocsenave@471 621 [:gengar :muk]
ocsenave@471 622 [:marowak :oddish :gloom]
ocsenave@471 623 [:nidoking :moltres :articuno :raichu]
ocsenave@471 624 [:nidoqueen :mankey :primeape]
ocsenave@471 625 [:exeggcute :diglett :doduo :dodrio :dugtrio]
ocsenave@471 626 [:lickitung :hitmonchan :seel :dewgong]
ocsenave@471 627 [:exeggutor :drowzee :jynx :hypno]
ocsenave@471 628 [:pidgey :poliwag :ditto :jigglypuff :wigglytuff :poliwhirl :poliwrath]
ocsenave@471 629 [:ivysaur :dragonite :pikachu :dratini :dragonair :bulbasaur :venusaur]
ocsenave@471 630 [:spearow :farfetch'd]
ocsenave@471 631 [:rhydon]
ocsenave@471 632 [:tangela :hitmonlee :golem :koffing :weezing]
ocsenave@471 633 [:blastoise :kakuna :beedrill]
ocsenave@471 634 [:pinsir :chansey :pidgeotto :pidgeot]
ocsenave@471 635 [:arcanine :weedle]
ocsenave@471 636 [:scyther :kabuto :caterpie :butterfree :goldeen :seaking]
ocsenave@471 637 [:gyarados :onix :arbok :ekans :magikarp]
ocsenave@471 638 [:shellder :fearow :zapdos :kabutops :cloyster]
ocsenave@471 639 [:clefairy :cubone :meowth :horsea :seadra :clefable :persian]
ocsenave@471 640 [:tentacool :venonat :eevee :flareon :jolteon :vaporeon :venomoth :tentacruel]
ocsenave@471 641 [:lapras]
ocsenave@471 642 [:gastly :kadabra :magneton :metapod :haunter :abra :alakazam :magnemite]
ocsenave@471 643 [:tauros :zubat :golbat :squirtle :wartortle]
ocsenave@471 644 [:mew :staryu :parasect :paras :mewtwo :starmie]
ocsenave@471 645 [:slowbro :growlithe :machoke :omanyte :omastar :machop :machamp]
ocsenave@471 646 [:mr.mime :krabby :kingler]
ocsenave@471 647 [:psyduck :golduck :bellsprout]
ocsenave@471 648 [:rattata :raticate]
ocsenave@471 649 [:aerodactyl :vileplume]
ocsenave@471 650 [:graveler :vulpix :ninetales :geodude]
ocsenave@471 651 [:ponyta :rapidash :porygon :weepinbell :victreebel]
ocsenave@471 652 #+end_example
ocsenave@471 653
ocsenave@471 654
ocsenave@471 655
ocsenave@471 656
ocsenave@471 657
ocsenave@471 658
ocsenave@471 659 *** Automatically grab the data
ocsenave@348 660 #+name: pokecry
ocsenave@348 661 #+begin_src clojure
ocsenave@348 662 (defn hxc-cry
ocsenave@348 663 "The pokemon cry data in internal order. List begins at ROM@39462"
ocsenave@348 664 ([](hxc-cry com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 665 ([rom]
ocsenave@348 666 (zipmap
ocsenave@348 667 (hxc-pokenames rom)
ocsenave@348 668 (map
ocsenave@348 669 (fn [[cry-id pitch length]]
ocsenave@348 670 {:cry-id cry-id
ocsenave@348 671 :pitch pitch
ocsenave@348 672 :length length}
ocsenave@348 673 )
ocsenave@348 674 (partition 3
ocsenave@348 675 (drop 0x39462 rom))))))
ocsenave@348 676
ocsenave@348 677 (defn hxc-cry-groups
ocsenave@348 678 ([] (hxc-cry-groups com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 679 ([rom]
ocsenave@348 680 (map #(mapv first
ocsenave@348 681 (filter
ocsenave@348 682 (fn [[k v]]
ocsenave@348 683 (= % (:cry-id v)))
ocsenave@348 684 (hxc-cry)))
ocsenave@348 685 ((comp
ocsenave@348 686 range
ocsenave@348 687 count
ocsenave@348 688 set
ocsenave@348 689 (partial map :cry-id)
ocsenave@348 690 vals
ocsenave@348 691 hxc-cry)
ocsenave@348 692 rom))))
ocsenave@348 693
ocsenave@348 694
ocsenave@348 695 (defn cry-conversion!
ocsenave@348 696 "Convert Porygon's cry in ROM to be the cry of the given pokemon."
ocsenave@348 697 [pkmn]
ocsenave@348 698 (write-rom!
ocsenave@348 699 (rewrite-memory
ocsenave@348 700 (vec(rom))
ocsenave@348 701 0x3965D
ocsenave@348 702 (map second
ocsenave@348 703 ((hxc-cry) pkmn)))))
ocsenave@348 704
ocsenave@348 705 #+end_src
ocsenave@348 706
ocsenave@348 707 ** COMMENT Names of permanent stats
ocsenave@348 708 0DD4D-DD72
ocsenave@348 709
ocsenave@348 710 * Items
ocsenave@348 711 ** Item names
ocsenave@371 712
ocsenave@371 713 *** See the data
ocsenave@371 714 #+begin_src clojure :exports both :results output
ocsenave@371 715 (ns com.aurellem.gb.hxc
ocsenave@371 716 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@371 717 constants))
ocsenave@371 718 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@371 719
ocsenave@371 720 (println (take 100 (drop 0x045B7 (rom))))
ocsenave@371 721
ocsenave@371 722 (println
ocsenave@371 723 (partition-by
ocsenave@371 724 (partial = 0x50)
ocsenave@371 725 (take 100 (drop 0x045B7 (rom)))))
ocsenave@371 726
ocsenave@371 727 (println
ocsenave@371 728 (map character-codes->str
ocsenave@371 729 (partition-by
ocsenave@371 730 (partial = 0x50)
ocsenave@371 731 (take 100 (drop 0x045B7 (rom))))))
ocsenave@371 732
ocsenave@371 733
ocsenave@371 734 #+end_src
ocsenave@371 735
ocsenave@371 736 #+results:
ocsenave@371 737 : (140 128 146 147 132 145 127 129 128 139 139 80 148 139 147 145 128 127 129 128 139 139 80 134 145 132 128 147 127 129 128 139 139 80 143 142 138 186 127 129 128 139 139 80 147 142 150 141 127 140 128 143 80 129 136 130 152 130 139 132 80 230 230 230 230 230 80 146 128 133 128 145 136 127 129 128 139 139 80 143 142 138 186 131 132 151 80 140 142 142 141 127 146 147 142 141 132 80 128 141)
ocsenave@371 738 : ((140 128 146 147 132 145 127 129 128 139 139) (80) (148 139 147 145 128 127 129 128 139 139) (80) (134 145 132 128 147 127 129 128 139 139) (80) (143 142 138 186 127 129 128 139 139) (80) (147 142 150 141 127 140 128 143) (80) (129 136 130 152 130 139 132) (80) (230 230 230 230 230) (80) (146 128 133 128 145 136 127 129 128 139 139) (80) (143 142 138 186 131 132 151) (80) (140 142 142 141 127 146 147 142 141 132) (80) (128 141))
ocsenave@371 739 : (MASTER BALL # ULTRA BALL # GREAT BALL # POKĂ© BALL # TOWN MAP # BICYCLE # ????? # SAFARI BALL # POKĂ©DEX # MOON STONE # AN)
ocsenave@371 740
ocsenave@371 741 *** Automatically grab the data
ocsenave@348 742 #+name: item-names
ocsenave@348 743 #+begin_src clojure
ocsenave@348 744
ocsenave@348 745 (def hxc-items-raw
ocsenave@348 746 "The hardcoded names of the items in memory. List begins at
ocsenave@348 747 ROM@045B7"
ocsenave@348 748 (hxc-thunk-words 0x45B7 870))
ocsenave@348 749
ocsenave@348 750 (def hxc-items
ocsenave@348 751 "The hardcoded names of the items in memory, presented as
ocsenave@348 752 keywords. List begins at ROM@045B7. See also, hxc-items-raw."
ocsenave@348 753 (comp (partial map format-name) hxc-items-raw))
ocsenave@348 754 #+end_src
ocsenave@348 755
ocsenave@348 756 ** Item prices
ocsenave@371 757
ocsenave@371 758 ***
ocsenave@371 759 #+begin_src clojure :exports both :results output
ocsenave@371 760 (ns com.aurellem.gb.hxc
ocsenave@371 761 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@371 762 constants))
ocsenave@371 763 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@371 764
ocsenave@371 765 (println (take 90 (drop 0x4495 (rom))))
ocsenave@371 766
ocsenave@371 767 (println
ocsenave@371 768 (partition 3
ocsenave@371 769 (take 90 (drop 0x4495 (rom)))))
ocsenave@371 770
ocsenave@371 771 (println
ocsenave@371 772 (partition 3
ocsenave@371 773 (map hex
ocsenave@371 774 (take 90 (drop 0x4495 (rom))))))
ocsenave@371 775
ocsenave@371 776 (println
ocsenave@371 777 (map decode-bcd
ocsenave@371 778 (map butlast
ocsenave@371 779 (partition 3
ocsenave@371 780 (take 90 (drop 0x4495 (rom)))))))
ocsenave@371 781
ocsenave@371 782 (println
ocsenave@371 783 (map
ocsenave@371 784 vector
ocsenave@371 785 (hxc-items (rom))
ocsenave@371 786 (map decode-bcd
ocsenave@371 787 (map butlast
ocsenave@371 788 (partition 3
ocsenave@371 789 (take 90 (drop 0x4495 (rom))))))))
ocsenave@371 790
ocsenave@371 791
ocsenave@371 792
ocsenave@371 793
ocsenave@371 794
ocsenave@371 795 #+end_src
ocsenave@371 796
ocsenave@371 797 #+results:
ocsenave@371 798 : (0 0 0 18 0 0 6 0 0 2 0 0 0 0 0 0 0 0 0 0 0 16 0 0 0 0 0 0 0 0 1 0 0 2 80 0 2 80 0 2 0 0 2 0 0 48 0 0 37 0 0 21 0 0 7 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 80 0 3 80 0)
ocsenave@371 799 : ((0 0 0) (18 0 0) (6 0 0) (2 0 0) (0 0 0) (0 0 0) (0 0 0) (16 0 0) (0 0 0) (0 0 0) (1 0 0) (2 80 0) (2 80 0) (2 0 0) (2 0 0) (48 0 0) (37 0 0) (21 0 0) (7 0 0) (3 0 0) (0 0 0) (0 0 0) (0 0 0) (0 0 0) (0 0 0) (0 0 0) (0 0 0) (0 0 0) (5 80 0) (3 80 0))
ocsenave@371 800 : ((0x0 0x0 0x0) (0x12 0x0 0x0) (0x6 0x0 0x0) (0x2 0x0 0x0) (0x0 0x0 0x0) (0x0 0x0 0x0) (0x0 0x0 0x0) (0x10 0x0 0x0) (0x0 0x0 0x0) (0x0 0x0 0x0) (0x1 0x0 0x0) (0x2 0x50 0x0) (0x2 0x50 0x0) (0x2 0x0 0x0) (0x2 0x0 0x0) (0x30 0x0 0x0) (0x25 0x0 0x0) (0x15 0x0 0x0) (0x7 0x0 0x0) (0x3 0x0 0x0) (0x0 0x0 0x0) (0x0 0x0 0x0) (0x0 0x0 0x0) (0x0 0x0 0x0) (0x0 0x0 0x0) (0x0 0x0 0x0) (0x0 0x0 0x0) (0x0 0x0 0x0) (0x5 0x50 0x0) (0x3 0x50 0x0))
ocsenave@371 801 : (0 1200 600 200 0 0 0 1000 0 0 100 250 250 200 200 3000 2500 1500 700 300 0 0 0 0 0 0 0 0 550 350)
ocsenave@371 802 : ([:master-ball 0] [:ultra-ball 1200] [:great-ball 600] [:poké-ball 200] [:town-map 0] [:bicycle 0] [:????? 0] [:safari-ball 1000] [:pokédex 0] [:moon-stone 0] [:antidote 100] [:burn-heal 250] [:ice-heal 250] [:awakening 200] [:parlyz-heal 200] [:full-restore 3000] [:max-potion 2500] [:hyper-potion 1500] [:super-potion 700] [:potion 300] [:boulderbadge 0] [:cascadebadge 0] [:thunderbadge 0] [:rainbowbadge 0] [:soulbadge 0] [:marshbadge 0] [:volcanobadge 0] [:earthbadge 0] [:escape-rope 550] [:repel 350])
ocsenave@371 803
ocsenave@371 804
ocsenave@371 805 ***
ocsenave@348 806 #+name: item-prices
ocsenave@348 807 #+begin_src clojure
ocsenave@348 808 (defn hxc-item-prices
ocsenave@348 809 "The hardcoded list of item prices in memory. List begins at ROM@4495"
ocsenave@348 810 ([] (hxc-item-prices com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 811 ([rom]
ocsenave@348 812 (let [items (hxc-items rom)
ocsenave@348 813 price-size 3]
ocsenave@348 814 (zipmap items
ocsenave@348 815 (map (comp
ocsenave@348 816 ;; zero-cost items are "priceless"
ocsenave@348 817 #(if (zero? %) :priceless %)
ocsenave@348 818 decode-bcd butlast)
ocsenave@348 819 (partition price-size
ocsenave@348 820 (take (* price-size (count items))
ocsenave@348 821 (drop 0x4495 rom))))))))
ocsenave@348 822 #+end_src
ocsenave@348 823 ** Vendor inventories
ocsenave@348 824
ocsenave@348 825 #+name: item-vendors
ocsenave@348 826 #+begin_src clojure
ocsenave@348 827 (defn hxc-shops
ocsenave@348 828 ([] (hxc-shops com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 829 ([rom]
ocsenave@348 830 (let [items (zipmap (range) (hxc-items rom))
ocsenave@348 831
ocsenave@348 832 ;; temporarily softcode the TM items
ocsenave@348 833 items (into
ocsenave@348 834 items
ocsenave@348 835 (map (juxt identity
ocsenave@348 836 (comp keyword
ocsenave@348 837 (partial str "tm-")
ocsenave@348 838 (partial + 1 -200)
ocsenave@348 839 ))
ocsenave@348 840 (take 200 (drop 200 (range)))))
ocsenave@348 841
ocsenave@348 842 ]
ocsenave@348 843
ocsenave@348 844 ((fn parse-shop [coll [num-items & items-etc]]
ocsenave@348 845 (let [inventory (take-while
ocsenave@348 846 (partial not= 0xFF)
ocsenave@348 847 items-etc)
ocsenave@348 848 [separator & items-etc] (drop num-items (rest items-etc))]
ocsenave@348 849 (if (= separator 0x50)
ocsenave@348 850 (map (partial mapv (comp items dec)) (conj coll inventory))
ocsenave@348 851 (recur (conj coll inventory) items-etc)
ocsenave@348 852 )
ocsenave@348 853 ))
ocsenave@348 854
ocsenave@348 855 '()
ocsenave@348 856 (drop 0x233C rom))
ocsenave@348 857
ocsenave@348 858
ocsenave@348 859 )))
ocsenave@348 860 #+end_src
ocsenave@348 861
ocsenave@348 862 #+results: item-vendors
ocsenave@348 863 : #'com.aurellem.gb.hxc/hxc-shops
ocsenave@348 864
ocsenave@348 865
ocsenave@348 866
ocsenave@348 867 * Types
ocsenave@348 868 ** Names of types
ocsenave@406 869
ocsenave@406 870 *** COMMENT Pointers to type names
ocsenave@406 871 #+begin_src clojure :exports both :results output
ocsenave@406 872 (map (comp character-codes->str #(take-while (partial not= 80) (drop % (rom))) (partial + 0x20000) (partial apply low-high)) (partition 2 (take 54 (drop 0x27D63 (rom)))))
ocsenave@406 873 #+end_src
ocsenave@406 874
ocsenave@406 875
ocsenave@371 876 ***
ocsenave@371 877 #+begin_src clojure :exports both :results output
ocsenave@371 878 (ns com.aurellem.gb.hxc
ocsenave@371 879 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@371 880 constants))
ocsenave@371 881 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@371 882
ocsenave@371 883 (println (take 90 (drop 0x27D99 (rom))))
ocsenave@371 884
ocsenave@371 885 (println
ocsenave@371 886 (partition-by (partial = 0x50)
ocsenave@371 887 (take 90 (drop 0x27D99 (rom)))))
ocsenave@371 888
ocsenave@371 889 (println
ocsenave@371 890 (map character-codes->str
ocsenave@371 891 (partition-by (partial = 0x50)
ocsenave@371 892 (take 90 (drop 0x27D99 (rom))))))
ocsenave@371 893
ocsenave@371 894 #+end_src
ocsenave@371 895
ocsenave@371 896 #+results:
ocsenave@371 897 : (141 142 145 140 128 139 80 133 136 134 135 147 136 141 134 80 133 139 152 136 141 134 80 143 142 136 146 142 141 80 133 136 145 132 80 150 128 147 132 145 80 134 145 128 146 146 80 132 139 132 130 147 145 136 130 80 143 146 152 130 135 136 130 80 136 130 132 80 134 145 142 148 141 131 80 145 142 130 138 80 129 136 145 131 80 129 148 134 80 134)
ocsenave@371 898 : ((141 142 145 140 128 139) (80) (133 136 134 135 147 136 141 134) (80) (133 139 152 136 141 134) (80) (143 142 136 146 142 141) (80) (133 136 145 132) (80) (150 128 147 132 145) (80) (134 145 128 146 146) (80) (132 139 132 130 147 145 136 130) (80) (143 146 152 130 135 136 130) (80) (136 130 132) (80) (134 145 142 148 141 131) (80) (145 142 130 138) (80) (129 136 145 131) (80) (129 148 134) (80) (134))
ocsenave@371 899 : (NORMAL # FIGHTING # FLYING # POISON # FIRE # WATER # GRASS # ELECTRIC # PSYCHIC # ICE # GROUND # ROCK # BIRD # BUG # G)
ocsenave@371 900
ocsenave@371 901
ocsenave@371 902 ***
ocsenave@348 903 #+name: type-names
ocsenave@348 904 #+begin_src clojure
ocsenave@348 905 (def hxc-types
ocsenave@348 906 "The hardcoded type names in memory. List begins at ROM@27D99,
ocsenave@348 907 shortly before hxc-titles."
ocsenave@348 908 (hxc-thunk-words 0x27D99 102))
ocsenave@348 909
ocsenave@348 910 #+end_src
ocsenave@348 911
ocsenave@348 912 ** Type effectiveness
ocsenave@371 913 ***
ocsenave@371 914 #+begin_src clojure :exports both :results output
ocsenave@371 915 (ns com.aurellem.gb.hxc
ocsenave@371 916 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@371 917 constants))
ocsenave@371 918 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@371 919
ocsenave@371 920
ocsenave@371 921 ;; POKEMON TYPES
ocsenave@371 922
ocsenave@371 923 (println pkmn-types) ;; these are the pokemon types
ocsenave@371 924 (println (map vector (range) pkmn-types)) ;; each type has an id number.
ocsenave@371 925
ocsenave@371 926 (newline)
ocsenave@371 927
ocsenave@371 928
ocsenave@371 929
ocsenave@371 930
ocsenave@371 931 ;;; TYPE EFFECTIVENESS
ocsenave@371 932
ocsenave@472 933 (println (take 15 (drop 0x3E5FA (rom))))
ocsenave@472 934 (println (partition 3 (take 15 (drop 0x3E5FA (rom)))))
ocsenave@371 935
ocsenave@371 936 (println
ocsenave@371 937 (map
ocsenave@371 938 (fn [[atk-type def-type multiplier]]
ocsenave@371 939 (list atk-type def-type (/ multiplier 10.)))
ocsenave@371 940
ocsenave@371 941 (partition 3
ocsenave@472 942 (take 15 (drop 0x3E5FA (rom))))))
ocsenave@371 943
ocsenave@371 944
ocsenave@371 945 (println
ocsenave@371 946 (map
ocsenave@371 947 (fn [[atk-type def-type multiplier]]
ocsenave@371 948 [
ocsenave@371 949 (get pkmn-types atk-type)
ocsenave@371 950 (get pkmn-types def-type)
ocsenave@371 951 (/ multiplier 10.)
ocsenave@371 952 ])
ocsenave@371 953
ocsenave@371 954 (partition 3
ocsenave@472 955 (take 15 (drop 0x3E5FA (rom))))))
ocsenave@371 956
ocsenave@371 957 #+end_src
ocsenave@371 958
ocsenave@371 959 #+results:
ocsenave@371 960 : [:normal :fighting :flying :poison :ground :rock :bird :bug :ghost :A :B :C :D :E :F :G :H :I :J :K :fire :water :grass :electric :psychic :ice :dragon]
ocsenave@371 961 : ([0 :normal] [1 :fighting] [2 :flying] [3 :poison] [4 :ground] [5 :rock] [6 :bird] [7 :bug] [8 :ghost] [9 :A] [10 :B] [11 :C] [12 :D] [13 :E] [14 :F] [15 :G] [16 :H] [17 :I] [18 :J] [19 :K] [20 :fire] [21 :water] [22 :grass] [23 :electric] [24 :psychic] [25 :ice] [26 :dragon])
ocsenave@371 962 :
ocsenave@472 963 : (21 20 20 20 22 20 20 25 20 22 21 20 23 21 20)
ocsenave@472 964 : ((21 20 20) (20 22 20) (20 25 20) (22 21 20) (23 21 20))
ocsenave@472 965 : ((21 20 2.0) (20 22 2.0) (20 25 2.0) (22 21 2.0) (23 21 2.0))
ocsenave@472 966 : ([:water :fire 2.0] [:fire :grass 2.0] [:fire :ice 2.0] [:grass :water 2.0] [:electric :water 2.0])
ocsenave@371 967
ocsenave@371 968
ocsenave@371 969 ***
ocsenave@372 970
ocsenave@349 971 #+name: type-advantage
ocsenave@348 972 #+begin_src clojure
ocsenave@348 973 (defn hxc-advantage
ocsenave@348 974 ;; in-game multipliers are stored as 10x their effective value
ocsenave@348 975 ;; to allow for fractional multipliers like 1/2
ocsenave@348 976
ocsenave@348 977 "The hardcoded type advantages in memory, returned as tuples of
ocsenave@348 978 atk-type def-type multiplier. By default (i.e. if not listed here),
ocsenave@348 979 the multiplier is 1. List begins at 0x3E62D."
ocsenave@348 980 ([] (hxc-advantage com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 981 ([rom]
ocsenave@348 982 (map
ocsenave@348 983 (fn [[atk def mult]] [(get pkmn-types atk (hex atk))
ocsenave@348 984 (get pkmn-types def (hex def))
ocsenave@348 985 (/ mult 10)])
ocsenave@348 986 (partition 3
ocsenave@348 987 (take-while (partial not= 0xFF)
ocsenave@472 988 (drop 0x3E5FA rom))))))
ocsenave@348 989 #+end_src
ocsenave@348 990
ocsenave@348 991
ocsenave@348 992
ocsenave@472 993
ocsenave@348 994 * Moves
ocsenave@348 995 ** Names of moves
ocsenave@371 996 *** See the data
ocsenave@371 997 #+begin_src clojure :exports both :results output
ocsenave@371 998 (ns com.aurellem.gb.hxc
ocsenave@371 999 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@371 1000 constants))
ocsenave@371 1001 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@371 1002
ocsenave@371 1003 (println (take 100 (drop 0xBC000 (rom))))
ocsenave@371 1004
ocsenave@371 1005 (println
ocsenave@371 1006 (partition-by
ocsenave@371 1007 (partial = 0x50)
ocsenave@371 1008 (take 100 (drop 0xBC000 (rom)))))
ocsenave@371 1009
ocsenave@371 1010 (println
ocsenave@371 1011 (map character-codes->str
ocsenave@371 1012 (partition-by
ocsenave@371 1013 (partial = 0x50)
ocsenave@371 1014 (take 100 (drop 0xBC000 (rom))))))
ocsenave@371 1015
ocsenave@371 1016
ocsenave@371 1017 #+end_src
ocsenave@371 1018
ocsenave@371 1019 #+results:
ocsenave@371 1020 : (143 142 148 141 131 80 138 128 145 128 147 132 127 130 135 142 143 80 131 142 148 129 139 132 146 139 128 143 80 130 142 140 132 147 127 143 148 141 130 135 80 140 132 134 128 127 143 148 141 130 135 80 143 128 152 127 131 128 152 80 133 136 145 132 127 143 148 141 130 135 80 136 130 132 127 143 148 141 130 135 80 147 135 148 141 131 132 145 143 148 141 130 135 80 146 130 145 128 147 130)
ocsenave@371 1021 : ((143 142 148 141 131) (80) (138 128 145 128 147 132 127 130 135 142 143) (80) (131 142 148 129 139 132 146 139 128 143) (80) (130 142 140 132 147 127 143 148 141 130 135) (80) (140 132 134 128 127 143 148 141 130 135) (80) (143 128 152 127 131 128 152) (80) (133 136 145 132 127 143 148 141 130 135) (80) (136 130 132 127 143 148 141 130 135) (80) (147 135 148 141 131 132 145 143 148 141 130 135) (80) (146 130 145 128 147 130))
ocsenave@371 1022 : (POUND # KARATE CHOP # DOUBLESLAP # COMET PUNCH # MEGA PUNCH # PAY DAY # FIRE PUNCH # ICE PUNCH # THUNDERPUNCH # SCRATC)
ocsenave@371 1023
ocsenave@371 1024 *** Automatically grab the data
ocsenave@371 1025
ocsenave@348 1026 #+name: move-names
ocsenave@348 1027 #+begin_src clojure
ocsenave@348 1028 (def hxc-move-names
ocsenave@348 1029 "The hardcoded move names in memory. List begins at ROM@BC000"
ocsenave@348 1030 (hxc-thunk-words 0xBC000 1551))
ocsenave@348 1031 #+end_src
ocsenave@348 1032
ocsenave@348 1033 ** Properties of moves
ocsenave@348 1034
ocsenave@348 1035 #+name: move-data
ocsenave@348 1036 #+begin_src clojure
ocsenave@348 1037 (defn hxc-move-data
ocsenave@348 1038 "The hardcoded (basic (move effects)) in memory. List begins at
ocsenave@348 1039 0x38000. Returns a map of {:name :power :accuracy :pp :fx-id
ocsenave@348 1040 :fx-txt}. The move descriptions are handwritten, not hardcoded."
ocsenave@348 1041 ([]
ocsenave@348 1042 (hxc-move-data com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 1043 ([rom]
ocsenave@348 1044 (let [names (vec (hxc-move-names rom))
ocsenave@348 1045 move-count (count names)
ocsenave@348 1046 move-size 6
ocsenave@348 1047 types pkmn-types ;;; !! hardcoded types
ocsenave@348 1048 ]
ocsenave@348 1049 (zipmap (map format-name names)
ocsenave@348 1050 (map
ocsenave@348 1051 (fn [[idx effect power type-id accuracy pp]]
ocsenave@348 1052 {:name (names (dec idx))
ocsenave@348 1053 :power power
ocsenave@348 1054 :accuracy accuracy
ocsenave@348 1055 :pp pp
ocsenave@348 1056 :type (types type-id)
ocsenave@348 1057 :fx-id effect
ocsenave@348 1058 :fx-txt (get move-effects effect)
ocsenave@348 1059 }
ocsenave@348 1060 )
ocsenave@348 1061
ocsenave@348 1062 (partition move-size
ocsenave@348 1063 (take (* move-size move-count)
ocsenave@348 1064 (drop 0x38000 rom))))))))
ocsenave@348 1065
ocsenave@348 1066
ocsenave@348 1067
ocsenave@348 1068 (defn hxc-move-data*
ocsenave@348 1069 "Like hxc-move-data, but reports numbers as hexadecimal symbols instead."
ocsenave@348 1070 ([]
ocsenave@348 1071 (hxc-move-data* com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 1072 ([rom]
ocsenave@348 1073 (let [names (vec (hxc-move-names rom))
ocsenave@348 1074 move-count (count names)
ocsenave@348 1075 move-size 6
ocsenave@348 1076 format-name (fn [s]
ocsenave@348 1077 (keyword (.toLowerCase
ocsenave@348 1078 (apply str
ocsenave@348 1079 (map #(if (= % \space) "-" %) s)))))
ocsenave@348 1080 ]
ocsenave@348 1081 (zipmap (map format-name names)
ocsenave@348 1082 (map
ocsenave@348 1083 (fn [[idx effect power type accuracy pp]]
ocsenave@348 1084 {:name (names (dec idx))
ocsenave@348 1085 :power power
ocsenave@348 1086 :accuracy (hex accuracy)
ocsenave@348 1087 :pp pp
ocsenave@348 1088 :fx-id (hex effect)
ocsenave@348 1089 :fx-txt (get move-effects effect)
ocsenave@348 1090 }
ocsenave@348 1091 )
ocsenave@348 1092
ocsenave@348 1093 (partition move-size
ocsenave@348 1094 (take (* move-size move-count)
ocsenave@348 1095 (drop 0x38000 rom))))))))
ocsenave@348 1096
ocsenave@348 1097 #+end_src
ocsenave@348 1098
ocsenave@348 1099 ** TM and HM moves
ocsenave@371 1100 ***
ocsenave@371 1101 #+begin_src clojure :exports both :results output
ocsenave@371 1102 (ns com.aurellem.gb.hxc
ocsenave@371 1103 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@371 1104 constants))
ocsenave@371 1105 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@348 1106
ocsenave@371 1107
ocsenave@371 1108 (println (hxc-move-names))
ocsenave@371 1109 (println (map vector (rest(range)) (hxc-move-names)))
ocsenave@371 1110
ocsenave@371 1111 (newline)
ocsenave@371 1112
ocsenave@371 1113 (println (take 55 (drop 0x1232D (rom))))
ocsenave@371 1114
ocsenave@371 1115 (println
ocsenave@371 1116 (interpose "."
ocsenave@371 1117 (map
ocsenave@371 1118 (zipmap (rest (range)) (hxc-move-names))
ocsenave@371 1119 (take 55 (drop 0x1232D (rom))))))
ocsenave@371 1120
ocsenave@371 1121 #+end_src
ocsenave@371 1122
ocsenave@371 1123 #+results:
ocsenave@371 1124 : (POUND KARATE CHOP DOUBLESLAP COMET PUNCH MEGA PUNCH PAY DAY FIRE PUNCH ICE PUNCH THUNDERPUNCH SCRATCH VICEGRIP GUILLOTINE RAZOR WIND SWORDS DANCE CUT GUST WING ATTACK WHIRLWIND FLY BIND SLAM VINE WHIP STOMP DOUBLE KICK MEGA KICK JUMP KICK ROLLING KICK SAND-ATTACK HEADBUTT HORN ATTACK FURY ATTACK HORN DRILL TACKLE BODY SLAM WRAP TAKE DOWN THRASH DOUBLE-EDGE TAIL WHIP POISON STING TWINEEDLE PIN MISSILE LEER BITE GROWL ROAR SING SUPERSONIC SONICBOOM DISABLE ACID EMBER FLAMETHROWER MIST WATER GUN HYDRO PUMP SURF ICE BEAM BLIZZARD PSYBEAM BUBBLEBEAM AURORA BEAM HYPER BEAM PECK DRILL PECK SUBMISSION LOW KICK COUNTER SEISMIC TOSS STRENGTH ABSORB MEGA DRAIN LEECH SEED GROWTH RAZOR LEAF SOLARBEAM POISONPOWDER STUN SPORE SLEEP POWDER PETAL DANCE STRING SHOT DRAGON RAGE FIRE SPIN THUNDERSHOCK THUNDERBOLT THUNDER WAVE THUNDER ROCK THROW EARTHQUAKE FISSURE DIG TOXIC CONFUSION PSYCHIC HYPNOSIS MEDITATE AGILITY QUICK ATTACK RAGE TELEPORT NIGHT SHADE MIMIC SCREECH DOUBLE TEAM RECOVER HARDEN MINIMIZE SMOKESCREEN CONFUSE RAY WITHDRAW DEFENSE CURL BARRIER LIGHT SCREEN HAZE REFLECT FOCUS ENERGY BIDE METRONOME MIRROR MOVE SELFDESTRUCT EGG BOMB LICK SMOG SLUDGE BONE CLUB FIRE BLAST WATERFALL CLAMP SWIFT SKULL BASH SPIKE CANNON CONSTRICT AMNESIA KINESIS SOFTBOILED HI JUMP KICK GLARE DREAM EATER POISON GAS BARRAGE LEECH LIFE LOVELY KISS SKY ATTACK TRANSFORM BUBBLE DIZZY PUNCH SPORE FLASH PSYWAVE SPLASH ACID ARMOR CRABHAMMER EXPLOSION FURY SWIPES BONEMERANG REST ROCK SLIDE HYPER FANG SHARPEN CONVERSION TRI ATTACK SUPER FANG SLASH SUBSTITUTE STRUGGLE)
ocsenave@371 1125 : ([1 POUND] [2 KARATE CHOP] [3 DOUBLESLAP] [4 COMET PUNCH] [5 MEGA PUNCH] [6 PAY DAY] [7 FIRE PUNCH] [8 ICE PUNCH] [9 THUNDERPUNCH] [10 SCRATCH] [11 VICEGRIP] [12 GUILLOTINE] [13 RAZOR WIND] [14 SWORDS DANCE] [15 CUT] [16 GUST] [17 WING ATTACK] [18 WHIRLWIND] [19 FLY] [20 BIND] [21 SLAM] [22 VINE WHIP] [23 STOMP] [24 DOUBLE KICK] [25 MEGA KICK] [26 JUMP KICK] [27 ROLLING KICK] [28 SAND-ATTACK] [29 HEADBUTT] [30 HORN ATTACK] [31 FURY ATTACK] [32 HORN DRILL] [33 TACKLE] [34 BODY SLAM] [35 WRAP] [36 TAKE DOWN] [37 THRASH] [38 DOUBLE-EDGE] [39 TAIL WHIP] [40 POISON STING] [41 TWINEEDLE] [42 PIN MISSILE] [43 LEER] [44 BITE] [45 GROWL] [46 ROAR] [47 SING] [48 SUPERSONIC] [49 SONICBOOM] [50 DISABLE] [51 ACID] [52 EMBER] [53 FLAMETHROWER] [54 MIST] [55 WATER GUN] [56 HYDRO PUMP] [57 SURF] [58 ICE BEAM] [59 BLIZZARD] [60 PSYBEAM] [61 BUBBLEBEAM] [62 AURORA BEAM] [63 HYPER BEAM] [64 PECK] [65 DRILL PECK] [66 SUBMISSION] [67 LOW KICK] [68 COUNTER] [69 SEISMIC TOSS] [70 STRENGTH] [71 ABSORB] [72 MEGA DRAIN] [73 LEECH SEED] [74 GROWTH] [75 RAZOR LEAF] [76 SOLARBEAM] [77 POISONPOWDER] [78 STUN SPORE] [79 SLEEP POWDER] [80 PETAL DANCE] [81 STRING SHOT] [82 DRAGON RAGE] [83 FIRE SPIN] [84 THUNDERSHOCK] [85 THUNDERBOLT] [86 THUNDER WAVE] [87 THUNDER] [88 ROCK THROW] [89 EARTHQUAKE] [90 FISSURE] [91 DIG] [92 TOXIC] [93 CONFUSION] [94 PSYCHIC] [95 HYPNOSIS] [96 MEDITATE] [97 AGILITY] [98 QUICK ATTACK] [99 RAGE] [100 TELEPORT] [101 NIGHT SHADE] [102 MIMIC] [103 SCREECH] [104 DOUBLE TEAM] [105 RECOVER] [106 HARDEN] [107 MINIMIZE] [108 SMOKESCREEN] [109 CONFUSE RAY] [110 WITHDRAW] [111 DEFENSE CURL] [112 BARRIER] [113 LIGHT SCREEN] [114 HAZE] [115 REFLECT] [116 FOCUS ENERGY] [117 BIDE] [118 METRONOME] [119 MIRROR MOVE] [120 SELFDESTRUCT] [121 EGG BOMB] [122 LICK] [123 SMOG] [124 SLUDGE] [125 BONE CLUB] [126 FIRE BLAST] [127 WATERFALL] [128 CLAMP] [129 SWIFT] [130 SKULL BASH] [131 SPIKE CANNON] [132 CONSTRICT] [133 AMNESIA] [134 KINESIS] [135 SOFTBOILED] [136 HI JUMP KICK] [137 GLARE] [138 DREAM EATER] [139 POISON GAS] [140 BARRAGE] [141 LEECH LIFE] [142 LOVELY KISS] [143 SKY ATTACK] [144 TRANSFORM] [145 BUBBLE] [146 DIZZY PUNCH] [147 SPORE] [148 FLASH] [149 PSYWAVE] [150 SPLASH] [151 ACID ARMOR] [152 CRABHAMMER] [153 EXPLOSION] [154 FURY SWIPES] [155 BONEMERANG] [156 REST] [157 ROCK SLIDE] [158 HYPER FANG] [159 SHARPEN] [160 CONVERSION] [161 TRI ATTACK] [162 SUPER FANG] [163 SLASH] [164 SUBSTITUTE] [165 STRUGGLE])
ocsenave@371 1126 :
ocsenave@371 1127 : (5 13 14 18 25 92 32 34 36 38 61 55 58 59 63 6 66 68 69 99 72 76 82 85 87 89 90 91 94 100 102 104 115 117 118 120 121 126 129 130 135 138 143 156 86 149 153 157 161 164 15 19 57 70 148)
ocsenave@371 1128 : (MEGA PUNCH . RAZOR WIND . SWORDS DANCE . WHIRLWIND . MEGA KICK . TOXIC . HORN DRILL . BODY SLAM . TAKE DOWN . DOUBLE-EDGE . BUBBLEBEAM . WATER GUN . ICE BEAM . BLIZZARD . HYPER BEAM . PAY DAY . SUBMISSION . COUNTER . SEISMIC TOSS . RAGE . MEGA DRAIN . SOLARBEAM . DRAGON RAGE . THUNDERBOLT . THUNDER . EARTHQUAKE . FISSURE . DIG . PSYCHIC . TELEPORT . MIMIC . DOUBLE TEAM . REFLECT . BIDE . METRONOME . SELFDESTRUCT . EGG BOMB . FIRE BLAST . SWIFT . SKULL BASH . SOFTBOILED . DREAM EATER . SKY ATTACK . REST . THUNDER WAVE . PSYWAVE . EXPLOSION . ROCK SLIDE . TRI ATTACK . SUBSTITUTE . CUT . FLY . SURF . STRENGTH . FLASH)
ocsenave@371 1129
ocsenave@371 1130
ocsenave@371 1131 ***
ocsenave@348 1132 #+name: machines
ocsenave@348 1133 #+begin_src clojure
ocsenave@348 1134 (defn hxc-machines
ocsenave@348 1135 "The hardcoded moves taught by TMs and HMs. List begins at ROM@1232D."
ocsenave@348 1136 ([] (hxc-machines
ocsenave@348 1137 com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 1138 ([rom]
ocsenave@348 1139 (let [moves (hxc-move-names rom)]
ocsenave@348 1140 (zipmap
ocsenave@348 1141 (range)
ocsenave@348 1142 (take-while
ocsenave@348 1143 (comp not nil?)
ocsenave@348 1144 (map (comp
ocsenave@348 1145 format-name
ocsenave@348 1146 (zipmap
ocsenave@348 1147 (range)
ocsenave@348 1148 moves)
ocsenave@348 1149 dec)
ocsenave@348 1150 (take 100
ocsenave@348 1151 (drop 0x1232D rom))))))))
ocsenave@348 1152
ocsenave@348 1153 #+end_src
ocsenave@348 1154
ocsenave@348 1155
ocsenave@348 1156
ocsenave@348 1157
ocsenave@348 1158
ocsenave@348 1159 ** COMMENT Status ailments
ocsenave@348 1160
ocsenave@419 1161
ocsenave@419 1162 * NPC Trainers
ocsenave@419 1163
ocsenave@419 1164 ** Trainer Pok\eacute{}mon
ocsenave@419 1165 # http://hax.iimarck.us/topic/103/
ocsenave@419 1166 There are two formats for specifying lists of NPC PPok\eacute{}mon:
ocsenave@419 1167 - If all the Pok\eacute{}mon will have the same level, the format is
ocsenave@419 1168 - Level (used for all the Pok\eacute{}mon)
ocsenave@419 1169 - Any number of Pok\eacute{}mon internal ids.
ocsenave@419 1170 - 0x00, to indicate end-of-list.
ocsenave@419 1171 - Otherwise, all the Pok\eacute{}mon will have their level
ocsenave@419 1172 specified. The format is
ocsenave@419 1173 - 0xFF, to indicate that we will be specifying the levels individually[fn::Because 0xFF is a
ocsenave@419 1174 forbidden level within the usual gameplay discipline, the game
ocsenave@419 1175 makers could safely use 0xFF as a mode indicator.].
ocsenave@419 1176 - Any number of alternating Level/Pokemon pairs
ocsenave@419 1177 - 0x00, to indicate end-of-list.
ocsenave@419 1178
ocsenave@419 1179 *** Get the pointers
ocsenave@419 1180 *** See the data
ocsenave@419 1181 #+begin_src clojure :exports both :results output
ocsenave@419 1182 (ns com.aurellem.gb.hxc
ocsenave@419 1183 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@419 1184 constants))
ocsenave@419 1185 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@419 1186
ocsenave@419 1187 (->>
ocsenave@419 1188 (rom)
ocsenave@419 1189 (drop 0x39E2F)
ocsenave@419 1190 (take 21)
ocsenave@419 1191 (println))
ocsenave@419 1192
ocsenave@419 1193
ocsenave@419 1194 (->>
ocsenave@419 1195 (rom)
ocsenave@419 1196 (drop 0x39E2F)
ocsenave@419 1197 (take 21)
ocsenave@419 1198 (partition-by zero?)
ocsenave@419 1199 (take-nth 2)
ocsenave@419 1200 (println))
ocsenave@419 1201
ocsenave@419 1202
ocsenave@419 1203
ocsenave@419 1204 (let
ocsenave@419 1205 [pokenames
ocsenave@419 1206 (zipmap
ocsenave@419 1207 (rest (range))
ocsenave@419 1208 (hxc-pokenames-raw))]
ocsenave@419 1209
ocsenave@419 1210 (->>
ocsenave@419 1211 (rom)
ocsenave@419 1212 (drop 0x39E2F)
ocsenave@419 1213 (take 21) ;; (1922 in all)
ocsenave@419 1214 (partition-by zero?)
ocsenave@419 1215 (take-nth 2)
ocsenave@419 1216 (map
ocsenave@419 1217 (fn parse-team [[mode & team]]
ocsenave@419 1218 (if (not= 0xFF mode)
ocsenave@419 1219 (mapv
ocsenave@419 1220 #(hash-map :level mode :species (pokenames %))
ocsenave@419 1221 team)
ocsenave@419 1222
ocsenave@419 1223 (mapv
ocsenave@419 1224 (fn [[lvl id]] (hash-map :level lvl :species (pokenames id)))
ocsenave@419 1225 (partition 2 team)))))
ocsenave@419 1226
ocsenave@419 1227 (println)))
ocsenave@419 1228
ocsenave@419 1229
ocsenave@419 1230
ocsenave@419 1231 #+end_src
ocsenave@419 1232
ocsenave@419 1233 #+results:
ocsenave@419 1234 : (11 165 108 0 14 5 0 10 165 165 107 0 14 165 108 107 0 15 165 5 0)
ocsenave@419 1235 : ((11 165 108) (14 5) (10 165 165 107) (14 165 108 107) (15 165 5))
ocsenave@419 1236 : ([{:species RATTATA, :level 11} {:species EKANS, :level 11}] [{:species SPEAROW, :level 14}] [{:species RATTATA, :level 10} {:species RATTATA, :level 10} {:species ZUBAT, :level 10}] [{:species RATTATA, :level 14} {:species EKANS, :level 14} {:species ZUBAT, :level 14}] [{:species RATTATA, :level 15} {:species SPEAROW, :level 15}])
ocsenave@419 1237
ocsenave@348 1238 * Places
ocsenave@348 1239 ** Names of places
ocsenave@348 1240
ocsenave@348 1241 #+name: places
ocsenave@348 1242 #+begin_src clojure
ocsenave@348 1243 (def hxc-places
ocsenave@348 1244 "The hardcoded place names in memory. List begins at
ocsenave@420 1245 ROM@71500. [Cinnabar/Celadon] Mansion seems to be dynamically calculated."
ocsenave@348 1246 (hxc-thunk-words 0x71500 560))
ocsenave@419 1247 #+end_src
ocsenave@348 1248
ocsenave@419 1249 *** See it work
ocsenave@419 1250 #+begin_src clojure :exports both :results output
ocsenave@419 1251 (println (hxc-places))
ocsenave@348 1252 #+end_src
ocsenave@348 1253
ocsenave@419 1254 #+results:
ocsenave@419 1255 : (PALLET TOWN VIRIDIAN CITY PEWTER CITY CERULEAN CITY LAVENDER TOWN VERMILION CITY CELADON CITY FUCHSIA CITY CINNABAR ISLAND INDIGO PLATEAU SAFFRON CITY ROUTE 1 ROUTE 2 ROUTE 3 ROUTE 4 ROUTE 5 ROUTE 6 ROUTE 7 ROUTE 8 ROUTE 9 ROUTE 10 ROUTE 11 ROUTE 12 ROUTE 13 ROUTE 14 ROUTE 15 ROUTE 16 ROUTE 17 ROUTE 18 SEA ROUTE 19 SEA ROUTE 20 SEA ROUTE 21 ROUTE 22 ROUTE 23 ROUTE 24 ROUTE 25 VIRIDIAN FOREST MT.MOON ROCK TUNNEL SEA COTTAGE S.S.ANNE [POKE]MON LEAGUE UNDERGROUND PATH [POKE]MON TOWER SEAFOAM ISLANDS VICTORY ROAD DIGLETT's CAVE ROCKET HQ SILPH CO. [0x4A] MANSION SAFARI ZONE)
ocsenave@419 1256
ocsenave@348 1257 ** Wild Pok\eacute{}mon demographics
ocsenave@348 1258 #+name: wilds
ocsenave@348 1259 #+begin_src clojure
ocsenave@348 1260
ocsenave@473 1261 ;; 0x0489, relative to 0xCB95, points to 0xCD89.
ocsenave@348 1262 (defn hxc-ptrs-wild
ocsenave@348 1263 "A list of the hardcoded wild encounter data in memory. Pointers
ocsenave@473 1264 begin at ROM@0CB95; data begins at ROM@0x0CD89"
ocsenave@348 1265 ([] (hxc-ptrs-wild com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 1266 ([rom]
ocsenave@348 1267 (let [ptrs
ocsenave@348 1268 (map (fn [[a b]] (+ a (* 0x100 b)))
ocsenave@348 1269 (take-while (partial not= (list 0xFF 0xFF))
ocsenave@348 1270 (partition 2 (drop 0xCB95 rom))))]
ocsenave@348 1271 ptrs)))
ocsenave@348 1272
ocsenave@348 1273
ocsenave@348 1274
ocsenave@348 1275 (defn hxc-wilds
ocsenave@348 1276 "A list of the hardcoded wild encounter data in memory. Pointers
ocsenave@473 1277 begin at ROM@0CB95; data begins at ROM@0x0CD89"
ocsenave@348 1278 ([] (hxc-wilds com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 1279 ([rom]
ocsenave@348 1280 (let [pokenames (zipmap (range) (hxc-pokenames rom))]
ocsenave@348 1281 (map
ocsenave@473 1282 (partial map
ocsenave@473 1283 (fn [[a b]]
ocsenave@473 1284 {:species (pokenames (dec b))
ocsenave@473 1285 :level a}))
ocsenave@473 1286 (partition 10
ocsenave@473 1287 (take-while
ocsenave@473 1288 (comp (partial not= 1) first)
ocsenave@473 1289 (partition 2
ocsenave@473 1290 (drop 0xCD8C rom))
ocsenave@348 1291
ocsenave@348 1292 ))))))
ocsenave@348 1293
ocsenave@348 1294 #+end_src
ocsenave@348 1295
ocsenave@348 1296
ocsenave@348 1297
ocsenave@348 1298
ocsenave@420 1299 ** Map data
ocsenave@420 1300
ocsenave@420 1301 # http://www.pokecommunity.com/showthread.php?t=235311
ocsenave@420 1302 # http://datacrystal.romhacking.net/wiki/Pokemon_Red/Blue:Notes
ocsenave@420 1303
ocsenave@420 1304 #+name map
ocsenave@420 1305 #+begin_src clojure :exports both :results output
ocsenave@420 1306 (ns com.aurellem.gb.hxc
ocsenave@420 1307 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@420 1308 constants))
ocsenave@420 1309 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@420 1310
ocsenave@420 1311
ocsenave@420 1312 (defn parse-header-tileset
ocsenave@420 1313 [[bank# ;; memory bank for blocks & tileset
ocsenave@420 1314
ocsenave@420 1315 blocks-lo ;; structure
ocsenave@420 1316 blocks-hi
ocsenave@420 1317
ocsenave@420 1318 tileset-lo ;; style
ocsenave@420 1319 tileset-hi
ocsenave@420 1320
ocsenave@420 1321 collision-lo ;; collision info
ocsenave@420 1322 collision-hi
ocsenave@420 1323
ocsenave@420 1324 talk-here-1 ;; positions of up to three
ocsenave@420 1325 talk-here-2 ;; talk-over-countertop tiles
ocsenave@420 1326 talk-here-3 ;; --- 0xFF if unused.
ocsenave@420 1327
ocsenave@420 1328 grass ;; grass tile --- 0xFF if unused
ocsenave@420 1329
ocsenave@420 1330 animation-flags ;; settings for animation
ocsenave@420 1331 & _]]
ocsenave@420 1332
ocsenave@420 1333 [bank#
ocsenave@420 1334
ocsenave@420 1335 blocks-lo ;; structure
ocsenave@420 1336 blocks-hi
ocsenave@420 1337
ocsenave@420 1338 tileset-lo ;; style
ocsenave@420 1339 tileset-hi
ocsenave@420 1340
ocsenave@420 1341 collision-lo ;; collision info
ocsenave@420 1342 collision-hi
ocsenave@420 1343
ocsenave@420 1344 talk-here-1 ;; positions of up to three
ocsenave@420 1345 talk-here-2 ;; talk-over-countertop tiles
ocsenave@420 1346 talk-here-3 ;; --- 0xFF if unused.
ocsenave@420 1347
ocsenave@420 1348 grass ;; grass tile --- 0xFF if unused
ocsenave@420 1349
ocsenave@420 1350 animation-flags ;; settings for animation
ocsenave@420 1351 ])
ocsenave@420 1352
ocsenave@420 1353
ocsenave@420 1354
ocsenave@420 1355 (defn parse-header-map
ocsenave@420 1356 [start]
ocsenave@420 1357
ocsenave@420 1358 (let [connection-size 11
ocsenave@420 1359
ocsenave@420 1360 [tileset-index
ocsenave@420 1361 map-height
ocsenave@420 1362 map-width
ocsenave@420 1363 layout-lo
ocsenave@420 1364 layout-hi
ocsenave@420 1365 text-lo
ocsenave@420 1366 text-hi
ocsenave@420 1367 script-lo
ocsenave@420 1368 script-hi
ocsenave@420 1369 adjacency-flags ;; x x x x N S W E
ocsenave@420 1370 & etc]
ocsenave@420 1371 (drop start (rom))
ocsenave@420 1372
ocsenave@420 1373 [east? west? south? north?]
ocsenave@420 1374 (bit-list adjacency-flags)
ocsenave@420 1375
ocsenave@420 1376 [connections object-data]
ocsenave@420 1377 (split-at
ocsenave@420 1378 (* connection-size (+ east? west? south? north?))
ocsenave@420 1379 etc)
ocsenave@420 1380
ocsenave@420 1381 connections
ocsenave@420 1382 (partition connection-size connections)
ocsenave@420 1383
ocsenave@420 1384
ocsenave@420 1385
ocsenave@420 1386
ocsenave@420 1387 ]
ocsenave@420 1388 (ptr->offset
ocsenave@420 1389 3
ocsenave@420 1390 (low-high layout-lo layout-hi))
ocsenave@420 1391
ocsenave@420 1392
ocsenave@420 1393 ))
ocsenave@420 1394 #+end_src
ocsenave@420 1395
ocsenave@420 1396 #+results:
ocsenave@420 1397 :
ocsenave@420 1398
ocsenave@420 1399
ocsenave@348 1400
ocsenave@348 1401 * Appendices
ocsenave@347 1402 ** Mapping the ROM
ocsenave@420 1403 # D3AD: Script:Use Pokeball?
ocsenave@311 1404
ocsenave@411 1405 | ROM address (hex) | Description | Format | Example |
ocsenave@411 1406 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1407 | | <15> | <15> | <15> |
ocsenave@411 1408 | 01823-0184A | Important prefix strings. | Variable-length strings, separated by 0x50. | TM#TRAINER#PC#ROCKET#POK\eacute{}#... |
ocsenave@411 1409 | 0233C- | Shop inventories. | | |
ocsenave@412 1410 | 02F47- | (?) Move ids of some HM moves. | One byte per move id | 0x0F 0x13 0x39 0x46 0x94 0xFF, the move ids of CUT, FLY, SURF, STRENGTH, FLASH, then cancel. |
ocsenave@421 1411 | 03E59- | Start of the Give-Pok\eacute{}mon script. | Assembly. When called, converts the contents of register BC into a Pok\eacute{}mon: (B) is the level; (C) is the species. | |
ocsenave@421 1412 | 03E3F- | Start of the give-item script. | Assembly. When called, converts the contents of register BC into an item: (B) is the item type; (C) is the quantity. | |
ocsenave@411 1413 | 04495- | Prices of items. | Each price is two bytes of binary-coded decimal. Prices are separated by zeroes. Priceless items[fn::Like the Pok\eacute{}dex and other unsellable items.] are given a price of zero. | The cost of lemonade is 0x03 0x50, which translates to a price of ₱350. |
ocsenave@412 1414 | 04524-04527 | (unconfirmed) possibly the bike price in Cerulean. | | |
ocsenave@411 1415 | 045B7-0491E | Names of the items in memory. | Variable-length item names (strings of character codes). Names are separated by a single 0x50 character. | MASTER BALL#ULTRA BALL#... |
ocsenave@412 1416 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@412 1417 | 05DD2-05DF2 | Menu text for player info. | | PLAYER [newline] BADGES [nelwine] POK\Eacute{}DEX [newline] TIME [0x50] |
ocsenave@411 1418 | 05EDB. | Which Pok\eacute{}mon to show during Prof. Oak's introduction. | A single byte, the Pok\eacute{}mon's internal id. | In Pok\eacute{}mon Yellow, it shows Pikachu during the introduction; Pikachu's internal id is 0x54. |
ocsenave@411 1419 | 06698- | ? Background music. | | |
ocsenave@421 1420 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@412 1421 | 7550-7570 | Menu options for map directions[fn:unused:According to [[http://tcrf.net/Pok%C3%A9mon_Red_and_Blue#NORTH.2FWEST.2FSOUTH.2FEAST][The Cutting Room Floor]], this data is unused. ]. | Variable-length strings. | NORTH [newline] WEST [0x50] SOUTH [newline] EAST [0x50] NORTH [newline] EAST[0x50] |
ocsenave@412 1422 | 7570-757D | Menu options for trading Pok\eacute{}mon | | TRADE [newline] CANCEL [0x50] |
ocsenave@412 1423 | 757D-758A | Menu options for healing Pok\eacute{}mon | | HEAL [newline] CANCEL [0x50] |
ocsenave@412 1424 | 7635- | Menu options for selected Pok\eacute{}mon (Includes names of out-of-battle moves). | Variable-length strings separated by 0x50. | CUT [0x50] FLY [0x50] SURF [0x50] STRENGTH [0x50] FLASH [0x50] DIG [0x50] TELEPORT [0x50] SOFTBOILED [0x50] STATS [newline] SWITCH [newline] CANCEL [0x50] |
ocsenave@412 1425 | 7AF0-8000 | (empty space) | | 0 0 0 0 0 ... |
ocsenave@411 1426 | 0822E-082F? | Pointers to background music, part I. | | |
ocsenave@473 1427 | 0CB95- | Pointers to lists of wild pokemon to encounter in each region. These lists begin at 04D89, see above. | Each pointer is a low-byte, high-byte pair. | The first entry is 0x89 0x4D, corresponding to the address 0x4D89 relative to this memory bank, i.e. absolute address 0xCD89, the location of the first list of wild Pok\eacute{}mon. (For details on pointer addresses, see the relevant appendix.) |
ocsenave@473 1428 | 0CD89- | Lists of wild Pok\eacute{}mon to encounter in each region. | Lists of 12 bytes. First, an encounter rate[fn::I suspect this is an amount out of 256.]. Next, ten alternating Pok\eacute{}mon/level pairs. Each list ends with 0x00. If the encounter rate is zero, the list ends immediately. | The first nonempty list (located at ROM@0CD8B) is (25; 3 36 4 36 2 165 3 165 2 36 3 36 5 36 4 165 6 36 7 36; 0), i.e. 25 encounter rate; level 3 pidgey, level 4 pidgey, level 2 rattata, level 3 rattata, level 2 pidgey, level 3 pidgey, level 5 pidgey, level 4 rattata, level 6 pidgey, level 7 pidgey, 0 (i.e., end-of-list). |
ocsenave@411 1429 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@420 1430 | 0DACB. | Amount of HP restored by Soda Pop | The HP consists of a single numerical byte. | 60 |
ocsenave@420 1431 | 0DACF. | Amount of HP restored by Lemonade | " | 80 |
ocsenave@420 1432 | 0DAD5. | Amount of HP restored by Fresh Water | " | 50 |
ocsenave@420 1433 | 0DADB. | Amount of HP restored by Hyper Potion. | " | 200 |
ocsenave@411 1434 | 0DAE0. | Amount of HP restored by Super Potion. | " | 50 |
ocsenave@411 1435 | 0DAE3. | Amount of HP restored by Potion. | " | 20 |
ocsenave@411 1436 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1437 | 0DD4D-DD72 | Names of permanent stats. | Variable-length strings separated by 0x50. | #HEALTH#ATTACK#DEFENSE#SPEED#SPECIAL# |
ocsenave@420 1438 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@421 1439 | 0DE2F. | Duration of Repel. | A single byte, representing the number of steps you can take before the effect wears off. | 100 |
ocsenave@420 1440 | 0DF39. | Duration of Super Repel. | " | 200 |
ocsenave@420 1441 | 0DF3E. | Duration of Max Repel. | " | 250 |
ocsenave@420 1442 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@412 1443 | 1164B- | Terminology for the Pok\eacute{}mon menu. | Contiguous, variable-length strings. | TYPE1[newline]TYPE2[newline] *â„–*,[newline]OT,[newline][0x50]STATUS,[0x50]OK |
ocsenave@412 1444 | 116DE- | Terminology for permanent stats in the Pok\eacute{}mon menu. | Contiguous, variable-length strings. | ATTACK[newline]DEFENSE[newline]SPEED[newline]SPECIAL[0x50] |
ocsenave@412 1445 | 11852- | Terminology for current stats in the Pok\eacute{}mon menu. | Contiguous, variable-length strings. | EXP POINTS[newline]LEVEL UP[0x50] |
ocsenave@411 1446 | 1195C-1196A | The two terms for being able/unable to learn a TM/HM. | Variable-length strings separated by 0x50. | ABLE#NOT ABLE# |
ocsenave@411 1447 | 119C0-119CE | The two terms for being able/unable to evolve using the current stone. | Variable-length strings separated by 0x50. | ABLE#NOT ABLE# |
ocsenave@421 1448 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@421 1449 | 11D53. | Which badge is a prerequisite for CUT? | op code: which bit of A to test? | When this script is called, the bits of A contain your badges, and this op code will check a certain bit of A. The op codes for the badges are, in order, [0x47 0x4F 0x57 0x5F 0x67 0x6F 0x77 0x7F]. |
ocsenave@421 1450 | 11D67. | Which badge is a prerequisite for SURF? | " | 0x67 (test for Soul Badge) |
ocsenave@421 1451 | 11DAC. | Which badge is a prerequisite for STRENGTH? | " | 0x5F (test for Rainbow Badge) |
ocsenave@421 1452 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1453 | 1232D-12364 | Which moves are taught by the TMs and HMs | A list of 55 move ids (50 TMs, plus 5 HMs). First, the move that will be taught by TM01; second, the move that will be taught by TM02; and so on. The last five entries are the moves taught by HMs 1-5. (See also, BC000 below) | The first few entries are (5 13 14 18 ...) corresponding to Mega Punch (TM01), Razor Wind (TM02), Swords Dance (TM03), Whirlwind (TM04), ... |
ocsenave@411 1454 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@421 1455 | 1CF8B-1CF8C | Which Pok\eacute{}mon does Melanie give you in Cerulean City? | A level/internal-id pair. | (10 153), corresponding to a level 10 Bulbasaur. |
ocsenave@421 1456 | 1D651-1D652 | Which Pok\eacute{}mon do you find at the top of Celadon Mansion? | A level/internal-id pair. | (25 102), corresponding to a level 25 Eevee. |
ocsenave@421 1457 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1458 | 27D56 & 27D57. | Pointer to the pointers to type names. | A single low-byte, high-byte pair. | 0x63 0x7D, corresponding to location 27D63\mdash{} the start of the next entry. |
ocsenave@411 1459 | 27D63-27D99 | Pointers to type names. | Each point is a low-byte, high-byte pair. The type names follows immediately after this section; see below. | The first pointer is [0x99 0x7D], corresponding to the location 27D99 ("NORMAL"). |
ocsenave@411 1460 | 27D99-27DFF | Names of the Pok\eacute{}mon types. | Variable-length type names (strings of character codes). Names are separated by a single 0x50 character. | NORMAL#FIGHTING#... |
ocsenave@411 1461 | 27DFF-27E77 | ? | 120 bytes of unknown data. | |
ocsenave@411 1462 | 27E77- | Trainer title names. | Variable-length names separated by 0x50. | YOUNGSTER#BUG CATCHER#LASS#... |
ocsenave@411 1463 | 34000- | | | |
ocsenave@411 1464 | 38000-383DE | The basic properties and effects of moves. (165 moves total) | Fixed-length (6 byte) continguous descriptions (no separating character): move-index, move-effect, power, move-type, accuracy, pp. | The entry for Pound, the first attack in the list, is (1 0 40 0 255 35). See below for more explanation. |
ocsenave@411 1465 | 383DE- | Species data for the Pokemon, listed in Pokedex order: Pokedex number; base moves; types; learnable TMs and HMs; base HP, attack, defense, speed, special; sprite data. | | |
ocsenave@411 1466 | 39462- | The Pok\eacute{}mon cry data. | Fixed-length (3 byte) descriptions of cries. | |
ocsenave@411 1467 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1468 | 3997D-39B05 | Trainer titles (extended; see 27E77). This list includes strictly more trainers, seemingly at random inserted into the list from 27E77.[fn::The names added are in bold: YOUNGSTER, BUG CATCHER, LASS, *SAILOR*, JR TRAINER(m), JR TRAINER(f), POK\eacute{}MANIAC, SUPER NERD, *HIKER*, *BIKER*, BURGLAR, ENGINEER, JUGGLER, *FISHERMAN*, SWIMMER, *CUE BALL*, *GAMBLER*, BEAUTY, *PSYCHIC*, ROCKER, JUGGLER (again), *TAMER*, *BIRDKEEPER*, BLACKBELT, *RIVAL1*, PROF OAK, CHIEF, SCIENTIST, *GIOVANNI*, ROCKET, COOLTRAINER(m), COOLTRAINER(f), *BRUNO*, *BROCK*, *MISTY*, *LT. SURGE*, *ERIKA*, *KOGA*, *BLAINE*, *SABRINA*, *GENTLEMAN*, *RIVAL2*, *RIVAL3*, *LORELEI*, *CHANNELER*, *AGATHA*, *LANCE*.] | | |
ocsenave@412 1469 | 39B05-39DD0. | unknown | | |
ocsenave@419 1470 | 39DD1-39E2E | Pointers to trainer Pok\eacute{}mon | Pairs of low-high bits. | The first pair is 0x2F 0x5E, which corresponds to memory location 5E2F relative to this 38000-3C000 bank, i.e.[fn::For details about how relative bank pointers work, see the relevant Appendix.] position 39E2F overall. |
ocsenave@419 1471 | 39E2F-3A5B2 | Trainer Pok\eacute{}mon | Specially-formatted lists of various length, separated by 0x00. If the list starts with 0xFF, the rest of the list will alternate between levels and internal-ids. Otherwise, start of the list is the level of the whole team, and the rest of the list is internal-ids. | The first entry is (11 165 108 0), which means a level 11 team consisting of Rattata and Ekans. The entry for MISTY is (255 18 27 21 152 0), which means a team of various levels consisting of level 18 Staryu and level 21 Starmie. [fn::Incidentally, if you want to change your rival's starter Pok\eacute{}mon, it's enough just to change its species in all of your battles with him.].) |
ocsenave@411 1472 | 3B1E5-3B361 | Pointers to evolution/learnset data. | One high-low byte pair for each of the 190 Pok\eacute{}mon in internal order. | |
ocsenave@411 1473 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@472 1474 | 3B361-3BBAA | *Evolution and learnset data*. [fn::Evolution data consists of how to make Pok\eacute{}mon evolve, and what they evolve into. Learnset data consists of the moves that Pok\eacute{}mon learn as they level up.] | Variable-length evolution information (see below), followed by a list of level/move-id learnset pairs. | |
ocsenave@411 1475 | 3BBAA-3C000 | (empty) | | 0 0 0 0 ... |
ocsenave@411 1476 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@412 1477 | 3D131-3D133 | The inventory of both OLD MAN and PROF. OAK when they battle for you. | Pairs of [item-id quantity], terminated by 0xFF. | (0x04 0x01 0xFF) They only have one Pok\eacute{}ball [fn::If you give them any ball, OAK will catch the enemy Pok\eacute{}mon and OLD MAN will miss. (OLD MAN misses even if he throws a MASTER BALL, which is a sight to see!) If you give them some other item first in the list, you'll be able to use that item normally but then you'll trigger the Safari Zone message: Pa will claim you're out of SAFARI BALLs and the battle will end. If you engage in either an OLD MAN or OAK battle with a Gym Leader, you will [1] get reprimanded if you try to throw a ball [2] incur the Safari Zone message [3] automatically win no matter which item you use [4] earn whichever reward they give you as usual [5] permanently retain the name OLD MAN / PROF. OAK.]. |
ocsenave@411 1478 | 3D6C7-3D6D6 | Two miscellaneous strings. | Variable length, separated by 0x50 | Disabled!#TYPE |
ocsenave@421 1479 | 3E190-3E194 | Which moves have an increased critical-hit ratio? | List of move ids, terminated by 0xFF. | (0x02 0x4B 0x98 0xA3 0xFF) corresponding to karate-chop, razor-leaf, crabhammer, slash, end-of-list. |
ocsenave@421 1480 | 3E200-3E204 | " (???) | " | " |
ocsenave@421 1481 | 3E231. | Besides normal-type, which type of move can COUNTER counter? | A single byte representing a type id. | This is set to 1, the id of the FIGHTING type. |
ocsenave@472 1482 | 3E5FA-3E6F0. | *Type effectiveness* | Triples of bytes: =atk-type=, =def-type=, =multiplier=. The multiplier is stored as 10x its actual value to allow for fractions; so, 20 means 2.0x effective, 5 means 0.5x effective. Unlisted type combinations have 1.0x effectiveness by default. | The first few entries are (21 20 20) (20 22 20) (20 25 20) (22 21 20) (23 21 20), corresponding to [:water :fire 2.0] [:fire :grass 2.0] [:fire :ice 2.0] |
ocsenave@411 1483 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1484 | 40252-4027B | Pok\eacute{}dex menu text | Variable-length strings separated by 0x50. | SEEN#OWN#CONTENTS#... |
ocsenave@411 1485 | 40370-40386 | Important constants for Pok\eacute{}dex entries | | HT _ _ *?′??″* [newline] WT _ _ _ *???* lb [0x50] *POK\Eacute{}* [0x50] |
ocsenave@411 1486 | 40687-41072 | Species data from the Pok\eacute{}dex: species name, height, weight, etc. | Variable-length species names, followed by 0x50, followed by fixed-length height/weight/etc. data. | The first entry is (*146 132 132 131*, 80, *2 4*, *150 0*, 23, 0 64 46, 80), which are the the stats of Bulbasaur: the first entry spells "SEED", then 0x80, then the height (2' 4"), then the weight (formatted as a low-high byte pair), then various Pokédex pointer data (see elsewhere). |
ocsenave@411 1487 | 41072- | Pok\eacute{} placeholder species, "???" | | |
ocsenave@411 1488 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1489 | 410B1-4116F | A conversion table between internal order and Pokedex order. | 190 bytes, corresponding to the Pok\eacute{}dex numbers of the 190 Pok\eacute{}mon listed in internal order. All =MISSINGNO.= are assigned a Pok\eacute{}dex number of 0. | The first few entries are (112 115 32 35 21 100 34 80 2 ...), which are the Pok\eacute{}dex numbers of Rhydon, Kangaskhan, Nidoran(m), Clefairy, Spearow, Voltorb, Nidoking, Slobrow, and Ivysaur. |
ocsenave@420 1490 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@420 1491 | 509B4-509E0 | Saffron City's adjacency info. | Four adjacency lists, each 11 bytes long. (For more info on adjacency lists a.k.a. connection data, see [[http://datacrystal.romhacking.net/wiki/Pokemon_Red/Blue:Notes][here]]) | The first adjacency list is (0x10 0x70 0x46 0xF0 0xC6 0x0A 0x0A 0x23 0xF6 0x09 0xC8) |
ocsenave@420 1492 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@421 1493 | 515AE-515AF | Which Pok\eacute{}mon does the trainer near Route 25 give you? | A level/internal-id pair. | (10 176) corresponding to a level 10 Charmander. |
ocsenave@421 1494 | 51DD5-51DD6 | Which Pok\eacute{}mon does the Silph Co. trainer give you? | A level/internal-id pair. | (15 19) corresponding to a level 15 Lapras. |
ocsenave@421 1495 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@412 1496 | 527BA-527DB | The costs and kinds of prizes from Celadon Game Corner. | The following pattern repeats three times, once per window[fn::For the first two prize lists, ids are interpreted as Pok\eacute{}mon ids. For the last prize list, ids are (somehow) interpreted as item ids.]: Internal ids / 0x50 / Prices (two bytes of BCD)/ 0x50. | (0x94 0x52 0x65 0x50) Abra Vulpix Wigglytuff (0x02 0x30 0x10 0x00 0x26 0x80) 230C, 1000C, 2680C |
ocsenave@411 1497 | 5DE10-5DE30 | Abbreviations for status ailments. | Fixed-length strings, probably[fn::Here's something strange: all of the status messages start with 0x7F and end with 0x4F \mdash{}except PAR, which ends with 0x50.]. The last entry is QUIT##. | [0x7F] *SLP* [0x4E][0x7F] *PSN* [0x4E][0x7F] *PAR* [0x50][0x7F]... |
ocsenave@412 1498 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@412 1499 | 70295- | Hall of fame | The text "HALL OF FAME" | |
ocsenave@412 1500 | 70442- | Play time/money | The text "PLAY TIME [0x50] MONEY" | |
ocsenave@411 1501 | 71500-7174B | Names of places. | Variable-length place names (strings), separated by 0x50. | PALLET TOWN#VIRIDIAN CITY#PEWTER CITY#CERULEAN CITY#... |
ocsenave@411 1502 | 71C1E-71CAA (approx.) | Tradeable NPC Pok\eacute{}mon. | Internal ID, followed by nickname (11 chars; extra space padded by 0x50). Some of the Pokemon have unknown extra data around the id. | The first entry is [0x76] "GURIO######", corresponding to a Dugtrio named "GURIO". |
ocsenave@411 1503 | 7C249-7C2?? | Pointers to background music, pt II. | | |
ocsenave@412 1504 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@419 1505 | 98000-B7190 | Dialogue and other messsages. | Variable-length strings. | |
ocsenave@419 1506 | B7190-B8000 | (empty space) | | 0 0 0 0 0 ... |
ocsenave@411 1507 | B8000-BC000 | The text of each Pok\eacute{}mon's Pok\eacute{}dex entry. | Variable-length descriptions (strings) in Pok\eacute{}dex order, separated by 0x50. These entries use the special characters *0x49* (new page), *0x4E* (new line), and *0x5F* (end entry). | The first entry (Bulbasaur's) is: "It can go for days [0x4E] without eating a [0x4E] single morsel. [0x49] In the bulb on [0x4E] its back, it [0x4E] stores energy [0x5F] [0x50]." |
ocsenave@419 1508 | BC000-BC60F | Move names. | Variable-length move names, separated by 0x50. The moves are in internal order. | POUND#KARATE CHOP#DOUBLESLAP#COMET PUNCH#... |
ocsenave@419 1509 | BC610-BD000 | (empty space) | | 0 0 0 0 0 ... |
ocsenave@411 1510 | E8000-E876C | Names of the \ldquo{}190\rdquo{} species of Pok\eacute{}mon in memory. | Fixed length (10-letter) Pok\eacute{}mon names. Any extra space is padded with the character 0x50. The names are in \ldquo{}internal order\rdquo{}. | RHYDON####KANGASKHANNIDORAN♂#... |
ocsenave@412 1511 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@412 1512 | E9BD5- | The text PLAY TIME (see above, 70442) | | |
ocsenave@421 1513 | F1A44-F1A45 | Which Pok\eacute{}mon does Officer Jenny give you? | A level/internal-id pair. | (10 177), corresponding to a level 10 Squirtle. |
ocsenave@421 1514 | F21BF-F21C0 | Which Pok\eacute{}mon does the salesman at the Mt. Moon Pok\eacute{}mon center give you? | A level/internal-id pair | (5 133), corresponding to a level 5 Magikarp. |
ocsenave@472 1515 | | | | |
ocsenave@410 1516 #+TBLFM:
ocsenave@312 1517
ocsenave@421 1518 ** COMMENT
ocsenave@421 1519 Locations where Give Pokemon is used in a nonstraightforward way
ocsenave@421 1520 0x5287C
ocsenave@421 1521 0x5CE23
ocsenave@421 1522 0x5C36B
ocsenave@421 1523 0x7562E
ocsenave@421 1524
ocsenave@470 1525 Find GivePokemon
ocsenave@470 1526 (search-memory* (vec(rom)) [120 234 \_ \_ 121 234 \_ \_ 175 234 \_ \_ 6] 10)
ocsenave@470 1527
ocsenave@470 1528 F4011 : ASM script for asking if it's oak battle
ocsenave@470 1529
ocsenave@347 1530
ocsenave@419 1531 ** Understanding memory banks and pointers
ocsenave@419 1532 #+begin_src clojure
ocsenave@419 1533
ocsenave@419 1534 (defn endian-flip
ocsenave@419 1535 "Flip the bytes of the two-byte number."
ocsenave@419 1536 [n]
ocsenave@419 1537 (assert (< n 0xFFFF))
ocsenave@419 1538 (+ (* 0x100 (rem n 0x100))
ocsenave@419 1539 (int (/ n 0x100))))
ocsenave@419 1540
ocsenave@419 1541
ocsenave@419 1542 (defn offset->ptr
ocsenave@419 1543 "Convert an offset into a little-endian pointer."
ocsenave@419 1544 [n]
ocsenave@419 1545 (->
ocsenave@419 1546 n
ocsenave@419 1547 (rem 0x10000) ;; take last four bytes
ocsenave@419 1548 (rem 0x4000) ;; get relative offset from the start of the bank
ocsenave@419 1549 (+ 0x4000)
ocsenave@419 1550 endian-flip))
ocsenave@419 1551
ocsenave@419 1552 (defn offset->bank
ocsenave@419 1553 "Get the bank of the offset."
ocsenave@419 1554 [n]
ocsenave@419 1555 (int (/ n 0x4000)))
ocsenave@419 1556
ocsenave@419 1557 (defn ptr->offset
ocsenave@419 1558 "Convert a two-byte little-endian pointer into an offset."
ocsenave@419 1559 [bank ptr]
ocsenave@419 1560 (->
ocsenave@419 1561 ptr
ocsenave@419 1562 endian-flip
ocsenave@419 1563 (- 0x4000)
ocsenave@419 1564 (+ (* 0x4000 bank))
ocsenave@419 1565 ))
ocsenave@419 1566
ocsenave@419 1567 (defn same-bank-offset
ocsenave@419 1568 "Convert a ptr into an absolute offset by using the bank of the reference."
ocsenave@419 1569 [reference ptr]
ocsenave@419 1570 (ptr->offset
ocsenave@419 1571 (offset->bank reference)
ocsenave@419 1572 ptr))
ocsenave@419 1573 #+end_src
ocsenave@419 1574
ocsenave@347 1575
ocsenave@312 1576 ** Internal Pok\eacute{}mon IDs
ocsenave@312 1577 ** Type IDs
ocsenave@347 1578
ocsenave@347 1579 #+name: type-ids
ocsenave@347 1580 #+begin_src clojure
ocsenave@347 1581 (def pkmn-types
ocsenave@347 1582 [:normal ;;0
ocsenave@347 1583 :fighting ;;1
ocsenave@347 1584 :flying ;;2
ocsenave@347 1585 :poison ;;3
ocsenave@347 1586 :ground ;;4
ocsenave@347 1587 :rock ;;5
ocsenave@347 1588 :bird ;;6
ocsenave@347 1589 :bug ;;7
ocsenave@347 1590 :ghost ;;8
ocsenave@347 1591 :A
ocsenave@347 1592 :B
ocsenave@347 1593 :C
ocsenave@347 1594 :D
ocsenave@347 1595 :E
ocsenave@347 1596 :F
ocsenave@347 1597 :G
ocsenave@347 1598 :H
ocsenave@347 1599 :I
ocsenave@347 1600 :J
ocsenave@347 1601 :K
ocsenave@347 1602 :fire ;;20 (0x14)
ocsenave@347 1603 :water ;;21 (0x15)
ocsenave@347 1604 :grass ;;22 (0x16)
ocsenave@347 1605 :electric ;;23 (0x17)
ocsenave@347 1606 :psychic ;;24 (0x18)
ocsenave@347 1607 :ice ;;25 (0x19)
ocsenave@347 1608 :dragon ;;26 (0x1A)
ocsenave@347 1609 ])
ocsenave@347 1610 #+end_src
ocsenave@347 1611
ocsenave@312 1612 ** Basic effects of moves
ocsenave@347 1613
ocsenave@347 1614 *** Table of basic effects
ocsenave@347 1615
ocsenave@347 1616 The possible effects of moves in Pok\eacute{}mon \mdash{} for example, dealing
ocsenave@347 1617 damage, leeching health, or potentially poisoning the opponent
ocsenave@347 1618 \mdash{} are stored in a table. Each move has exactly one effect, and
ocsenave@347 1619 different moves might have the same effect.
ocsenave@347 1620
ocsenave@347 1621 For example, Leech Life, Mega Drain, and Absorb all have effect ID #3, which is \ldquo{}Leech half of the inflicted damage.\rdquo{}
ocsenave@347 1622
ocsenave@347 1623 All the legitimate move effects are listed in the table
ocsenave@347 1624 below. Here are some notes for reading it:
ocsenave@347 1625
ocsenave@347 1626 - Whenever an effect has a chance of doing something (like a chance of
ocsenave@371 1627 poisoning the opponent), I list the chance as a hexadecimal amount
ocsenave@371 1628 out of 256; this is to avoid rounding errors. To convert the hex amount into a percentage, divide by 256.
ocsenave@347 1629 - For some effects, the description is too cumbersome to
ocsenave@347 1630 write. Instead, I just write a move name
ocsenave@347 1631 in parentheses, like: (leech seed). That move gives a characteristic example
ocsenave@347 1632 of the effect.
ocsenave@347 1633 - I use the abbreviations =atk=, =def=, =spd=, =spc=, =acr=, =evd= for
ocsenave@371 1634 attack, defense, speed, special, accuracy, and evasiveness.
ocsenave@347 1635 .
ocsenave@347 1636
ocsenave@347 1637
ocsenave@347 1638
ocsenave@347 1639 | ID (hex) | Description | Notes |
ocsenave@347 1640 |----------+-------------------------------------------------------------------------------------------------+------------------------------------------------------------------|
ocsenave@347 1641 | 0 | normal damage | |
ocsenave@347 1642 | 1 | no damage, just sleep | TODO: find out how many turns |
ocsenave@347 1643 | 2 | 0x4C chance of poison | |
ocsenave@347 1644 | 3 | leech half of inflicted damage | |
ocsenave@347 1645 | 4 | 0x19 chance of burn | |
ocsenave@347 1646 | 5 | 0x19 chance of freeze | |
ocsenave@347 1647 | 6 | 0x19 chance of paralysis | |
ocsenave@347 1648 | 7 | user faints; opponent's defense is halved during attack. | |
ocsenave@347 1649 | 8 | leech half of inflicted damage ONLY if the opponent is asleep | |
ocsenave@347 1650 | 9 | imitate last attack | |
ocsenave@347 1651 | A | user atk +1 | |
ocsenave@347 1652 | B | user def +1 | |
ocsenave@347 1653 | C | user spd +1 | |
ocsenave@347 1654 | D | user spc +1 | |
ocsenave@347 1655 | E | user acr +1 | This effect is unused. |
ocsenave@347 1656 | F | user evd +1 | |
ocsenave@347 1657 | 10 | get post-battle money = 2 * level * uses | |
ocsenave@347 1658 | 11 | move has 0xFE acr, regardless of battle stat modifications. | |
ocsenave@347 1659 | 12 | opponent atk -1 | |
ocsenave@347 1660 | 13 | opponent def -1 | |
ocsenave@347 1661 | 14 | opponent spd -1 | |
ocsenave@347 1662 | 15 | opponent spc -1 | |
ocsenave@347 1663 | 16 | opponent acr -1 | |
ocsenave@347 1664 | 17 | opponent evd -1 | |
ocsenave@347 1665 | 18 | converts user's type to opponent's. | |
ocsenave@347 1666 | 19 | (haze) | |
ocsenave@347 1667 | 1A | (bide) | |
ocsenave@347 1668 | 1B | (thrash) | |
ocsenave@347 1669 | 1C | (teleport) | |
ocsenave@347 1670 | 1D | (fury swipes) | |
ocsenave@347 1671 | 1E | attacks 2-5 turns | Unused. TODO: find out what it does. |
ocsenave@347 1672 | 1F | 0x19 chance of flinching | |
ocsenave@347 1673 | 20 | opponent sleep for 1-7 turns | |
ocsenave@347 1674 | 21 | 0x66 chance of poison | |
ocsenave@347 1675 | 22 | 0x4D chance of burn | |
ocsenave@347 1676 | 23 | 0x4D chance of freeze | |
ocsenave@347 1677 | 24 | 0x4D chance of paralysis | |
ocsenave@347 1678 | 25 | 0x4D chance of flinching | |
ocsenave@347 1679 | 26 | one-hit KO | |
ocsenave@347 1680 | 27 | charge one turn, atk next. | |
ocsenave@347 1681 | 28 | fixed damage, leaves 1HP. | Is the fixed damage the power of the move? |
ocsenave@347 1682 | 29 | fixed damage. | Like seismic toss, dragon rage, psywave. |
ocsenave@347 1683 | 2A | atk 2-5 turns; opponent can't attack | The odds of attacking for /n/ turns are: (0 0x60 0x60 0x20 0x20) |
ocsenave@347 1684 | 2B | charge one turn, atk next. (can't be hit when charging) | |
ocsenave@347 1685 | 2C | atk hits twice. | |
ocsenave@347 1686 | 2D | user takes 1 damage if misses. | |
ocsenave@347 1687 | 2E | evade status-lowering effects | Caused by you or also your opponent? |
ocsenave@347 1688 | 2F | broken: if user is slower than opponent, makes critical hit impossible, otherwise has no effect | This is the effect of Focus Energy. It's (very) broken. |
ocsenave@347 1689 | 30 | atk causes recoil dmg = 1/4 dmg dealt | |
ocsenave@347 1690 | 31 | confuses opponent | |
ocsenave@347 1691 | 32 | user atk +2 | |
ocsenave@347 1692 | 33 | user def +2 | |
ocsenave@347 1693 | 34 | user spd +2 | |
ocsenave@347 1694 | 35 | user spc +2 | |
ocsenave@347 1695 | 36 | user acr +2 | This effect is unused. |
ocsenave@347 1696 | 37 | user evd +2 | This effect is unused. |
ocsenave@347 1697 | 38 | restores up to half of user's max hp. | |
ocsenave@347 1698 | 39 | (transform) | |
ocsenave@347 1699 | 3A | opponent atk -2 | |
ocsenave@347 1700 | 3B | opponent def -2 | |
ocsenave@347 1701 | 3C | opponent spd -2 | |
ocsenave@347 1702 | 3D | opponent spc -2 | |
ocsenave@347 1703 | 3E | opponent acr -2 | |
ocsenave@347 1704 | 3F | opponent evd -2 | |
ocsenave@347 1705 | 40 | doubles user spc when attacked | |
ocsenave@347 1706 | 41 | doubles user def when attacked | |
ocsenave@347 1707 | 42 | just poisons opponent | |
ocsenave@347 1708 | 43 | just paralyzes opponent | |
ocsenave@347 1709 | 44 | 0x19 chance opponent atk -1 | |
ocsenave@347 1710 | 45 | 0x19 chance opponent def -1 | |
ocsenave@347 1711 | 46 | 0x19 chance opponent spd -1 | |
ocsenave@347 1712 | 47 | 0x4C chance opponent spc -1 | |
ocsenave@347 1713 | 48 | 0x19 chance opponent acr -1 | |
ocsenave@347 1714 | 49 | 0x19 chance opponent evd -1 | |
ocsenave@347 1715 | 4A | ??? | ;; unused? no effect? |
ocsenave@347 1716 | 4B | ??? | ;; unused? no effect? |
ocsenave@347 1717 | 4C | 0x19 chance of confusing the opponent | |
ocsenave@347 1718 | 4D | atk hits twice. 0x33 chance opponent poisioned. | |
ocsenave@347 1719 | 4E | broken. crash the game after attack. | |
ocsenave@347 1720 | 4F | (substitute) | |
ocsenave@347 1721 | 50 | unless opponent faints, user must recharge after atk. some exceptions apply | |
ocsenave@347 1722 | 51 | (rage) | |
ocsenave@347 1723 | 52 | (mimic) | |
ocsenave@347 1724 | 53 | (metronome) | |
ocsenave@347 1725 | 54 | (leech seed) | |
ocsenave@347 1726 | 55 | does nothing (splash) | |
ocsenave@347 1727 | 56 | (disable) | |
ocsenave@347 1728 #+end_src
ocsenave@347 1729
ocsenave@347 1730 *** Source
ocsenave@347 1731 #+name: move-effects
ocsenave@347 1732 #+begin_src clojure
ocsenave@347 1733 (def move-effects
ocsenave@347 1734 ["normal damage"
ocsenave@347 1735 "no damage, just opponent sleep" ;; how many turns? is atk power ignored?
ocsenave@347 1736 "0x4C chance of poison"
ocsenave@347 1737 "leech half of inflicted damage"
ocsenave@347 1738 "0x19 chance of burn"
ocsenave@347 1739 "0x19 chance of freeze"
ocsenave@347 1740 "0x19 chance of paralyze"
ocsenave@347 1741 "user faints; opponent defense halved during attack."
ocsenave@347 1742 "leech half of inflicted damage ONLY if sleeping opponent."
ocsenave@347 1743 "imitate last attack"
ocsenave@347 1744 "user atk +1"
ocsenave@347 1745 "user def +1"
ocsenave@347 1746 "user spd +1"
ocsenave@347 1747 "user spc +1"
ocsenave@347 1748 "user acr +1" ;; unused?!
ocsenave@347 1749 "user evd +1"
ocsenave@347 1750 "get post-battle $ = 2*level*uses"
ocsenave@347 1751 "0xFE acr, no matter what."
ocsenave@347 1752 "opponent atk -1" ;; acr taken from move acr?
ocsenave@347 1753 "opponent def -1" ;;
ocsenave@347 1754 "opponent spd -1" ;;
ocsenave@347 1755 "opponent spc -1" ;;
ocsenave@347 1756 "opponent acr -1";;
ocsenave@347 1757 "opponent evd -1"
ocsenave@347 1758 "converts user's type to opponent's."
ocsenave@347 1759 "(haze)"
ocsenave@347 1760 "(bide)"
ocsenave@347 1761 "(thrash)"
ocsenave@347 1762 "(teleport)"
ocsenave@347 1763 "(fury swipes)"
ocsenave@347 1764 "attacks 2-5 turns" ;; unused? like rollout?
ocsenave@347 1765 "0x19 chance of flinch"
ocsenave@347 1766 "opponent sleep for 1-7 turns"
ocsenave@347 1767 "0x66 chance of poison"
ocsenave@347 1768 "0x4D chance of burn"
ocsenave@347 1769 "0x4D chance of freeze"
ocsenave@347 1770 "0x4D chance of paralyze"
ocsenave@347 1771 "0x4D chance of flinch"
ocsenave@347 1772 "one-hit KO"
ocsenave@347 1773 "charge one turn, atk next."
ocsenave@347 1774 "fixed damage, leaves 1HP." ;; how is dmg determined?
ocsenave@347 1775 "fixed damage." ;; cf seismic toss, dragon rage, psywave.
ocsenave@347 1776 "atk 2-5 turns; opponent can't attack" ;; unnormalized? (0 0x60 0x60 0x20 0x20)
ocsenave@347 1777 "charge one turn, atk next. (can't be hit when charging)"
ocsenave@347 1778 "atk hits twice."
ocsenave@347 1779 "user takes 1 damage if misses."
ocsenave@347 1780 "evade status-lowering effects" ;;caused by you or also your opponent?
ocsenave@347 1781 "(broken) if user is slower than opponent, makes critical hit impossible, otherwise has no effect"
ocsenave@347 1782 "atk causes recoil dmg = 1/4 dmg dealt"
ocsenave@347 1783 "confuses opponent" ;; acr taken from move acr
ocsenave@347 1784 "user atk +2"
ocsenave@347 1785 "user def +2"
ocsenave@347 1786 "user spd +2"
ocsenave@347 1787 "user spc +2"
ocsenave@347 1788 "user acr +2" ;; unused!
ocsenave@347 1789 "user evd +2" ;; unused!
ocsenave@347 1790 "restores up to half of user's max hp." ;; broken: fails if the difference
ocsenave@347 1791 ;; b/w max and current hp is one less than a multiple of 256.
ocsenave@347 1792 "(transform)"
ocsenave@347 1793 "opponent atk -2"
ocsenave@347 1794 "opponent def -2"
ocsenave@347 1795 "opponent spd -2"
ocsenave@347 1796 "opponent spc -2"
ocsenave@347 1797 "opponent acr -2"
ocsenave@347 1798 "opponent evd -2"
ocsenave@347 1799 "doubles user spc when attacked"
ocsenave@347 1800 "doubles user def when attacked"
ocsenave@347 1801 "just poisons opponent" ;;acr taken from move acr
ocsenave@347 1802 "just paralyzes opponent" ;;
ocsenave@347 1803 "0x19 chance opponent atk -1"
ocsenave@347 1804 "0x19 chance opponent def -1"
ocsenave@347 1805 "0x19 chance opponent spd -1"
ocsenave@347 1806 "0x4C chance opponent spc -1" ;; context suggest chance is 0x19
ocsenave@347 1807 "0x19 chance opponent acr -1"
ocsenave@347 1808 "0x19 chance opponent evd -1"
ocsenave@347 1809 "???" ;; unused? no effect?
ocsenave@347 1810 "???" ;; unused? no effect?
ocsenave@347 1811 "0x19 chance opponent confused"
ocsenave@347 1812 "atk hits twice. 0x33 chance opponent poisioned."
ocsenave@347 1813 "broken. crash the game after attack."
ocsenave@347 1814 "(substitute)"
ocsenave@347 1815 "unless opponent faints, user must recharge after atk. some
ocsenave@347 1816 exceptions apply."
ocsenave@347 1817 "(rage)"
ocsenave@347 1818 "(mimic)"
ocsenave@347 1819 "(metronome)"
ocsenave@347 1820 "(leech seed)"
ocsenave@347 1821 "does nothing (splash)"
ocsenave@347 1822 "(disable)"
ocsenave@347 1823 ])
ocsenave@347 1824 #+end_src
ocsenave@347 1825
ocsenave@347 1826
ocsenave@312 1827 ** Alphabet code
ocsenave@347 1828
ocsenave@348 1829 * Source
ocsenave@348 1830
ocsenave@347 1831 #+begin_src clojure :tangle ../clojure/com/aurellem/gb/hxc.clj
ocsenave@347 1832
ocsenave@347 1833 (ns com.aurellem.gb.hxc
ocsenave@347 1834 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@347 1835 constants species))
ocsenave@347 1836 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@347 1837
ocsenave@347 1838 ; ************* HANDWRITTEN CONSTANTS
ocsenave@347 1839
ocsenave@347 1840 <<type-ids>>
ocsenave@347 1841
ocsenave@347 1842
ocsenave@347 1843 ;; question: when status effects claim to take
ocsenave@347 1844 ;; their accuracy from the move accuracy, does
ocsenave@347 1845 ;; this mean that the move always "hits" but the
ocsenave@347 1846 ;; status effect may not?
ocsenave@347 1847
ocsenave@347 1848 <<move-effects>>
ocsenave@347 1849
ocsenave@347 1850 ;; ************** HARDCODED DATA
ocsenave@347 1851
ocsenave@347 1852 <<hxc-thunks>>
ocsenave@347 1853 ;; --------------------------------------------------
ocsenave@347 1854
ocsenave@347 1855 <<pokenames>>
ocsenave@348 1856 <<type-names>>
ocsenave@347 1857
ocsenave@347 1858 ;; http://hax.iimarck.us/topic/581/
ocsenave@348 1859 <<pokecry>>
ocsenave@347 1860
ocsenave@347 1861
ocsenave@348 1862 <<item-names>>
ocsenave@347 1863
ocsenave@347 1864
ocsenave@347 1865
ocsenave@347 1866 (def hxc-titles
ocsenave@347 1867 "The hardcoded names of the trainer titles in memory. List begins at
ocsenave@347 1868 ROM@27E77"
ocsenave@347 1869 (hxc-thunk-words 0x27E77 196))
ocsenave@347 1870
ocsenave@347 1871
ocsenave@348 1872 <<dex-text>>
ocsenave@347 1873
ocsenave@347 1874 ;; In red/blue, pokedex stats are in internal order.
ocsenave@347 1875 ;; In yellow, pokedex stats are in pokedex order.
ocsenave@348 1876 <<dex-stats>>
ocsenave@347 1877
ocsenave@347 1878
ocsenave@347 1879
ocsenave@347 1880
ocsenave@348 1881 <<places>>
ocsenave@347 1882
ocsenave@347 1883 (defn hxc-dialog
ocsenave@347 1884 "The hardcoded dialogue in memory, including in-game alerts. Dialog
ocsenave@347 1885 seems to be separated by 0x57 instead of 0x50 (END). Begins at ROM@98000."
ocsenave@347 1886 ([rom]
ocsenave@347 1887 (map character-codes->str
ocsenave@347 1888 (take-nth 2
ocsenave@347 1889 (partition-by #(= % 0x57)
ocsenave@347 1890 (take 0x0F728
ocsenave@347 1891 (drop 0x98000 rom))))))
ocsenave@347 1892 ([]
ocsenave@347 1893 (hxc-dialog com.aurellem.gb.gb-driver/original-rom)))
ocsenave@347 1894
ocsenave@347 1895
ocsenave@348 1896 <<move-names>>
ocsenave@348 1897 <<move-data>>
ocsenave@347 1898
ocsenave@348 1899 <<machines>>
ocsenave@347 1900
ocsenave@347 1901
ocsenave@347 1902
ocsenave@347 1903 (defn internal-id
ocsenave@347 1904 ([rom]
ocsenave@347 1905 (zipmap
ocsenave@347 1906 (hxc-pokenames rom)
ocsenave@347 1907 (range)))
ocsenave@347 1908 ([]
ocsenave@347 1909 (internal-id com.aurellem.gb.gb-driver/original-rom)))
ocsenave@347 1910
ocsenave@347 1911
ocsenave@347 1912
ocsenave@347 1913
ocsenave@347 1914
ocsenave@347 1915 ;; nidoran gender change upon levelup
ocsenave@347 1916 ;; (->
ocsenave@347 1917 ;; @current-state
ocsenave@347 1918 ;; rom
ocsenave@347 1919 ;; vec
ocsenave@347 1920 ;; (rewrite-memory
ocsenave@347 1921 ;; (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♂))
ocsenave@347 1922 ;; [1 1 15])
ocsenave@347 1923 ;; (rewrite-memory
ocsenave@347 1924 ;; (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♀))
ocsenave@347 1925 ;; [1 1 3])
ocsenave@347 1926 ;; (write-rom!)
ocsenave@347 1927
ocsenave@347 1928 ;; )
ocsenave@347 1929
ocsenave@347 1930
ocsenave@347 1931
ocsenave@348 1932 <<type-advantage>>
ocsenave@347 1933
ocsenave@347 1934
ocsenave@347 1935
ocsenave@348 1936 <<evolution-header>>
ocsenave@349 1937 <<evolution>>
ocsenave@348 1938 <<learnsets>>
ocsenave@348 1939 <<pokebase>>
ocsenave@347 1940
ocsenave@347 1941
ocsenave@347 1942 (defn hxc-intro-pkmn
ocsenave@347 1943 "The hardcoded pokemon to display in Prof. Oak's introduction; the pokemon's
ocsenave@347 1944 internal id is stored at ROM@5EDB."
ocsenave@347 1945 ([] (hxc-intro-pkmn
ocsenave@347 1946 com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 1947 ([rom]
ocsenave@347 1948 (nth (hxc-pokenames rom) (nth rom 0x5EDB))))
ocsenave@347 1949
ocsenave@347 1950 (defn sxc-intro-pkmn!
ocsenave@347 1951 "Set the hardcoded pokemon to display in Prof. Oak's introduction."
ocsenave@347 1952 [pokemon]
ocsenave@347 1953 (write-rom!
ocsenave@347 1954 (rewrite-rom 0x5EDB
ocsenave@347 1955 [
ocsenave@347 1956 (inc
ocsenave@347 1957 ((zipmap
ocsenave@347 1958 (hxc-pokenames)
ocsenave@347 1959 (range))
ocsenave@347 1960 pokemon))])))
ocsenave@347 1961
ocsenave@347 1962
ocsenave@348 1963 <<item-prices>>
ocsenave@347 1964
ocsenave@348 1965 <<item-vendors>>
ocsenave@347 1966
ocsenave@348 1967 <<wilds>>
ocsenave@347 1968
ocsenave@347 1969
ocsenave@347 1970 ;; ********************** MANIPULATION FNS
ocsenave@347 1971
ocsenave@347 1972
ocsenave@347 1973 (defn same-type
ocsenave@347 1974 ([pkmn move]
ocsenave@347 1975 (same-type
ocsenave@347 1976 com.aurellem.gb.gb-driver/original-rom pkmn move))
ocsenave@347 1977 ([rom pkmn move]
ocsenave@347 1978 (((comp :types (hxc-pokemon-base rom)) pkmn)
ocsenave@347 1979 ((comp :type (hxc-move-data rom)) move))))
ocsenave@347 1980
ocsenave@347 1981
ocsenave@347 1982
ocsenave@347 1983
ocsenave@347 1984 (defn submap?
ocsenave@347 1985 "Compares the two maps. Returns true if map-big has the same associations as map-small, otherwise false."
ocsenave@347 1986 [map-small map-big]
ocsenave@347 1987 (cond (empty? map-small) true
ocsenave@347 1988 (and
ocsenave@347 1989 (contains? map-big (ffirst map-small))
ocsenave@347 1990 (= (get map-big (ffirst map-small))
ocsenave@347 1991 (second (first map-small))))
ocsenave@347 1992 (recur (next map-small) map-big)
ocsenave@347 1993
ocsenave@347 1994 :else false))
ocsenave@347 1995
ocsenave@347 1996
ocsenave@347 1997 (defn search-map [proto-map maps]
ocsenave@347 1998 "Returns all the maps that make the same associations as proto-map."
ocsenave@347 1999 (some (partial submap? proto-map) maps))
ocsenave@347 2000
ocsenave@347 2001 (defn filter-vals
ocsenave@347 2002 "Returns a map consisting of all the pairs [key val] for
ocsenave@347 2003 which (pred key) returns true."
ocsenave@347 2004 [pred map]
ocsenave@347 2005 (reduce (partial apply assoc) {}
ocsenave@347 2006 (filter (fn [[k v]] (pred v)) map)))
ocsenave@347 2007
ocsenave@347 2008
ocsenave@347 2009 (defn search-moves
ocsenave@347 2010 "Returns a subcollection of all hardcoded moves with the
ocsenave@347 2011 given attributes. Attributes consist of :name :power
ocsenave@347 2012 :accuracy :pp :fx-id
ocsenave@347 2013 (and also :fx-txt, but it contains the same information
ocsenave@347 2014 as :fx-id)"
ocsenave@347 2015 ([attribute-map]
ocsenave@347 2016 (search-moves
ocsenave@347 2017 com.aurellem.gb.gb-driver/original-rom attribute-map))
ocsenave@347 2018 ([rom attribute-map]
ocsenave@347 2019 (filter-vals (partial submap? attribute-map)
ocsenave@347 2020 (hxc-move-data rom))))
ocsenave@347 2021
ocsenave@347 2022
ocsenave@347 2023
ocsenave@347 2024
ocsenave@347 2025
ocsenave@347 2026 ;; note: 0x2f31 contains the names "TM" "HM"?
ocsenave@347 2027
ocsenave@347 2028 ;; note for later: credits start at F1290
ocsenave@347 2029
ocsenave@347 2030 ;; note: DADB hyper-potion-hp _ _ _ super-potion-hp _ _ _ potion-hp ??
ocsenave@347 2031
ocsenave@347 2032 ;; note: DD4D spells out pokemon vital stat names ("speed", etc.)
ocsenave@347 2033
ocsenave@347 2034 ;; note: 1195C-6A says ABLE#NOT ABLE#, but so does 119C0-119CE.
ocsenave@347 2035 ;; The first instance is for Machines; the second, for stones.
ocsenave@347 2036
ocsenave@410 2037 ;; note: according to
ocsenave@410 2038 ;; http://www.upokecenter.com/games/rby/guides/rgbtrainers.php
ocsenave@410 2039 ;; the amount of money given by a trainer is equal to the
ocsenave@410 2040 ;; base money times the level of the last Pokemon on that trainer's
ocsenave@410 2041 ;; list. Other sources say it's the the level of the last pokemon
ocsenave@410 2042 ;; /defeated/.
ocsenave@410 2043
ocsenave@410 2044 ;; todo: find base money.
ocsenave@410 2045
ocsenave@410 2046
ocsenave@411 2047 ;; note: 0xDFEA (in indexable mem) is the dex# of the currently-viewed Pokemon in
ocsenave@411 2048 ;; in the pokedex. It's used for other purposes if there is none.
ocsenave@411 2049
ocsenave@412 2050 ;; note: 0x9D35 (index.) switches from 0xFF to 0x00 temporarily when
ocsenave@412 2051 ;; you walk between areas.
ocsenave@412 2052
ocsenave@412 2053 ;; note: 0xD059 (index.) is the special battle type of your next battle:
ocsenave@412 2054 ;; - 00 is a usual battle
ocsenave@412 2055 ;; - 01 is a pre-scripted OLD MAN battle which always fails to catch the
ocsenave@412 2056 ;; target Pokemon.
ocsenave@412 2057 ;; - 02 is a safari zone battle
ocsenave@412 2058 ;; - 03 obligates you to run away. (unused)
ocsenave@412 2059 ;; - 04 is a pre-scripted OAK battle, which (temporarily) causes the
ocsenave@412 2060 ;; enemy Pokemon to cry PIKAAA, and which always catches the target
ocsenave@412 2061 ;; Pokemon. The target Pokemon is erased after the battle.
ocsenave@412 2062 ;; - 05+ are glitch states in which you are sort of the Pokemon.
ocsenave@412 2063
ocsenave@412 2064
ocsenave@412 2065 ;; note: 0x251A (in indexable mem): image decompression routine seems to begin here.
ocsenave@347 2066
ocsenave@420 2067 ;; note: 0x4845 (index): vending inventory is loaded here. possibly
ocsenave@420 2068 ;; other things, too.
ocsenave@420 2069 (comment
ocsenave@420 2070 ;; temporarily intercept/adjust what pops out of the vending
ocsenave@420 2071 ;; machine.
ocsenave@420 2072 ;; (and how much it costs)
ocsenave@420 2073
ocsenave@420 2074 ;; located at 0x4845
ocsenave@420 2075 ;; not to be confused with shop inventory, 0xCF7B
ocsenave@420 2076 (do
ocsenave@420 2077 (step (read-state "vend-menu"))
ocsenave@420 2078 (write-memory! (rewrite-memory (vec(memory)) 0x4845 [2 0 1 0]))
ocsenave@420 2079 (step @current-state [:a])
ocsenave@420 2080 (step @current-state [])
ocsenave@420 2081 (nstep @current-state 200) ))
ocsenave@420 2082
ocsenave@347 2083
ocsenave@373 2084 ;; Note: There are two tile tables, one from 8000-8FFF, the other from
ocsenave@373 2085 ;; 8800-97FF. The latter contains symbols, possibly map tiles(?), with some japanese chars and stuff at the end.
ocsenave@373 2086 (defn print-pixel-letters!
ocsenave@373 2087 "The pixel tiles representing letters. Neat!"
ocsenave@373 2088 ([] (print-pixel-letters! (read-state "oak-speaks")))
ocsenave@373 2089 ([state]
ocsenave@373 2090 (map
ocsenave@373 2091 (comp
ocsenave@373 2092 println
ocsenave@373 2093 (partial map #(if (zero? %) \space 0))
ocsenave@373 2094 #(if (< (count %) 8)
ocsenave@373 2095 (recur (cons 0 %))
ocsenave@373 2096 %)
ocsenave@373 2097 reverse bit-list)
ocsenave@373 2098
ocsenave@373 2099 (take 0xFFF (drop 0x8800 (memory state))))))
ocsenave@373 2100
ocsenave@373 2101
ocsenave@419 2102 ;; (defn test-2 []
ocsenave@419 2103 ;; (loop [n 0
ocsenave@419 2104 ;; pc-1 (pc-trail (-> state-defend (tick) (step [:a]) (step [:a]) (step []) (nstep 100)) 100000)
ocsenave@419 2105 ;; pc-2 (pc-trail (-> state-speed (tick) (step [:a]) (step [:a])
ocsenave@419 2106 ;; (step []) (nstep 100)) 100000)]
ocsenave@419 2107 ;; (cond (empty? (drop n pc-1)) [pc-1 n]
ocsenave@419 2108 ;; (not= (take 10 (drop n pc-1)) (take 10 pc-2))
ocsenave@419 2109 ;; (recur pc-1 pc-2 (inc n))
ocsenave@419 2110 ;; :else
ocsenave@419 2111 ;; [(take 1000 pc-2) n])))
ocsenave@406 2112
ocsenave@406 2113
ocsenave@406 2114
ocsenave@406 2115
ocsenave@410 2116 (defn test-3
ocsenave@410 2117 "Explore trainer data"
ocsenave@419 2118 ([] (test-3 0x3A289))
ocsenave@419 2119 ([start]
ocsenave@410 2120 (let [pokenames (vec(hxc-pokenames-raw))]
ocsenave@410 2121 (println
ocsenave@410 2122 (reduce
ocsenave@410 2123 str
ocsenave@410 2124 (map
ocsenave@419 2125 (fn [[adr lvl pkmn]]
ocsenave@419 2126 (str (format "%-11s %4d %02X %02X \t %05X\n"
ocsenave@419 2127
ocsenave@410 2128 (cond
ocsenave@410 2129 (zero? lvl) "+"
ocsenave@410 2130 (nil? (get pokenames (dec pkmn)))
ocsenave@410 2131 "-"
ocsenave@410 2132 :else
ocsenave@410 2133 (get pokenames (dec pkmn)))
ocsenave@410 2134 lvl
ocsenave@410 2135 pkmn
ocsenave@410 2136 lvl
ocsenave@419 2137 adr
ocsenave@419 2138 )))
ocsenave@419 2139 (map cons
ocsenave@419 2140 (take-nth 2 (drop start (range)))
ocsenave@419 2141 (partition 2
ocsenave@419 2142 (take 400;;703
ocsenave@419 2143 (drop
ocsenave@419 2144 start
ocsenave@419 2145 ;; 0x3A75D
ocsenave@419 2146 (rom)))))))))))
ocsenave@410 2147
ocsenave@412 2148 (defn search-memory* [mem codes k]
ocsenave@412 2149 (loop [index 0
ocsenave@412 2150 index-next 1
ocsenave@412 2151 start-match 0
ocsenave@412 2152 to-match codes
ocsenave@412 2153 matches []]
ocsenave@412 2154 (cond
ocsenave@412 2155 (>= index (count mem)) matches
ocsenave@412 2156
ocsenave@412 2157 (empty? to-match)
ocsenave@412 2158 (recur
ocsenave@412 2159 index-next
ocsenave@412 2160 (inc index-next)
ocsenave@412 2161 index-next
ocsenave@412 2162 codes
ocsenave@412 2163 (conj matches
ocsenave@412 2164 [(hex start-match) (take k (drop start-match mem))])
ocsenave@412 2165 )
ocsenave@412 2166
ocsenave@412 2167 (or (= (first to-match) \_) ;; wildcard
ocsenave@412 2168 (= (first to-match) (nth mem index)))
ocsenave@412 2169 (recur
ocsenave@412 2170 (inc index)
ocsenave@412 2171 index-next
ocsenave@412 2172 start-match
ocsenave@412 2173 (rest to-match)
ocsenave@412 2174 matches)
ocsenave@412 2175
ocsenave@412 2176 :else
ocsenave@412 2177 (recur
ocsenave@412 2178 index-next
ocsenave@412 2179 (inc index-next)
ocsenave@412 2180 index-next
ocsenave@412 2181 codes
ocsenave@412 2182 matches))))
ocsenave@420 2183
ocsenave@420 2184
ocsenave@420 2185 (def script-use-ball
ocsenave@420 2186 [0xFA ;; ld A, nn
ocsenave@420 2187 \_
ocsenave@420 2188 \_
ocsenave@420 2189 0xA7 ;; and A
ocsenave@420 2190 0xCA ;; JP Z
ocsenave@420 2191 \_
ocsenave@420 2192 \_
ocsenave@420 2193 0x3D ;; dec A
ocsenave@420 2194 0xC2 ;; JP NZ
ocsenave@420 2195 \_
ocsenave@420 2196 \_
ocsenave@420 2197 0xFA ;; LD A
ocsenave@420 2198 \_
ocsenave@420 2199 \_
ocsenave@420 2200 ])
ocsenave@420 2201
ocsenave@420 2202
ocsenave@420 2203
ocsenave@420 2204 (defn search-pattern [ptn coll]
ocsenave@420 2205 (loop
ocsenave@420 2206 [index 0
ocsenave@420 2207 to-match ptn
ocsenave@420 2208 binds {}
ocsenave@420 2209
ocsenave@420 2210 next-index 1
ocsenave@420 2211 match-start 0
ocsenave@420 2212 matches []]
ocsenave@420 2213
ocsenave@420 2214 (cond
ocsenave@420 2215 (>= index (count coll)) matches
ocsenave@420 2216 (empty? to-match)
ocsenave@420 2217 (recur
ocsenave@420 2218 next-index
ocsenave@420 2219 ptn
ocsenave@420 2220 {}
ocsenave@420 2221 (inc next-index)
ocsenave@420 2222 next-index
ocsenave@420 2223 (conj match-start
ocsenave@420 2224 [(hex match-start) binds]))
ocsenave@420 2225
ocsenave@420 2226 :else
ocsenave@420 2227 (let [k (first to-match)
ocsenave@420 2228 v (nth coll index)]
ocsenave@420 2229 (cond
ocsenave@420 2230 (= k \_) ;; wildcard
ocsenave@420 2231 (recur
ocsenave@420 2232 (inc index)
ocsenave@420 2233 (rest to-match)
ocsenave@420 2234 binds
ocsenave@420 2235
ocsenave@420 2236 next-index
ocsenave@420 2237 match-start
ocsenave@420 2238 matches)
ocsenave@420 2239
ocsenave@420 2240 (keyword? k)
ocsenave@420 2241 (if (binds k)
ocsenave@420 2242 (if (= (binds k) v)
ocsenave@420 2243 (recur
ocsenave@420 2244 (inc index)
ocsenave@420 2245 (rest to-match)
ocsenave@420 2246 binds
ocsenave@420 2247 next-index
ocsenave@420 2248 match-start
ocsenave@420 2249 matches)
ocsenave@420 2250
ocsenave@420 2251 (recur
ocsenave@420 2252 next-index
ocsenave@420 2253 ptn
ocsenave@420 2254 {}
ocsenave@420 2255 (inc next-index)
ocsenave@420 2256 next-index
ocsenave@420 2257 matches))
ocsenave@420 2258
ocsenave@420 2259 ;; ;; consistent bindings
ocsenave@420 2260 ;; (recur
ocsenave@420 2261 ;; (inc index)
ocsenave@420 2262 ;; (rest to-match)
ocsenave@420 2263 ;; binds
ocsenave@420 2264
ocsenave@420 2265 ;; next-index
ocsenave@420 2266 ;; match-start
ocsenave@420 2267 ;; matches)
ocsenave@420 2268
ocsenave@420 2269 ;; ;; inconsistent bindings
ocsenave@420 2270 ;; (recur
ocsenave@420 2271 ;; next-index
ocsenave@420 2272 ;; ptn
ocsenave@420 2273 ;; {}
ocsenave@420 2274 ;; (inc next-index)
ocsenave@420 2275 ;; next-index
ocsenave@420 2276 ;; matches))
ocsenave@420 2277
ocsenave@420 2278 (if ((set (vals binds)) v)
ocsenave@420 2279 ;; bindings are not unique
ocsenave@420 2280 (recur
ocsenave@420 2281 next-index
ocsenave@420 2282 ptn
ocsenave@420 2283 {}
ocsenave@420 2284 (inc next-index)
ocsenave@420 2285 next-index
ocsenave@420 2286 matches)
ocsenave@420 2287
ocsenave@420 2288 ;; bindings are unique
ocsenave@420 2289 (recur
ocsenave@420 2290 (inc index)
ocsenave@420 2291 (rest to-match)
ocsenave@420 2292 (assoc binds k v)
ocsenave@420 2293
ocsenave@420 2294 next-index
ocsenave@420 2295 match-start
ocsenave@420 2296 matches)))
ocsenave@420 2297
ocsenave@420 2298 :else ;; k is just a number
ocsenave@420 2299 (if (= k v)
ocsenave@420 2300 (recur
ocsenave@420 2301 (inc index)
ocsenave@420 2302 (rest to-match)
ocsenave@420 2303 binds
ocsenave@420 2304
ocsenave@420 2305 next-index
ocsenave@420 2306 match-start
ocsenave@420 2307 matches)
ocsenave@420 2308
ocsenave@420 2309 (recur
ocsenave@420 2310 next-index
ocsenave@420 2311 ptn
ocsenave@420 2312 {}
ocsenave@420 2313 (inc next-index)
ocsenave@420 2314 next-index
ocsenave@420 2315 matches)))))))
ocsenave@420 2316
ocsenave@420 2317
ocsenave@420 2318
ocsenave@420 2319
ocsenave@420 2320
ocsenave@420 2321
ocsenave@420 2322
ocsenave@420 2323
ocsenave@420 2324
ocsenave@420 2325 (defn search-pattern* [ptn coll]
ocsenave@420 2326 (loop
ocsenave@420 2327 [
ocsenave@420 2328 binds {}
ocsenave@420 2329 index 0
ocsenave@420 2330 index-next 1
ocsenave@420 2331 start-match 0
ocsenave@420 2332 to-match ptn
ocsenave@420 2333 matches []]
ocsenave@420 2334
ocsenave@420 2335 (cond
ocsenave@420 2336 (>= index (count coll)) matches
ocsenave@420 2337 (empty? to-match)
ocsenave@420 2338 (recur
ocsenave@420 2339 {}
ocsenave@420 2340 index-next
ocsenave@420 2341 (inc index-next)
ocsenave@420 2342 index-next
ocsenave@420 2343 ptn
ocsenave@420 2344 (conj matches
ocsenave@420 2345 [(hex start-match) binds]))
ocsenave@420 2346
ocsenave@420 2347 :else
ocsenave@420 2348 (let [k (first to-match)
ocsenave@420 2349 v (nth coll index)]
ocsenave@420 2350 (cond
ocsenave@420 2351 (= k \_) ;; wildcard
ocsenave@420 2352 (recur
ocsenave@420 2353 binds
ocsenave@420 2354 (inc index)
ocsenave@420 2355 index-next
ocsenave@420 2356 start-match
ocsenave@420 2357 (rest to-match)
ocsenave@420 2358 matches)
ocsenave@420 2359
ocsenave@420 2360 (keyword? k)
ocsenave@420 2361 (if (binds k)
ocsenave@420 2362 (if (= (binds k) v)
ocsenave@420 2363 (recur
ocsenave@420 2364 binds
ocsenave@420 2365 (inc index)
ocsenave@420 2366 index-next
ocsenave@420 2367 start-match
ocsenave@420 2368 (rest to-match)
ocsenave@420 2369 matches)
ocsenave@420 2370 (recur
ocsenave@420 2371 {}
ocsenave@420 2372 index-next
ocsenave@420 2373 (inc index-next)
ocsenave@420 2374 index-next
ocsenave@420 2375 ptn
ocsenave@420 2376 matches))
ocsenave@420 2377 (if
ocsenave@420 2378 ;; every symbol must be bound to a different thing.
ocsenave@420 2379 ((set (vals binds)) v)
ocsenave@420 2380 (recur
ocsenave@420 2381 {}
ocsenave@420 2382 index-next
ocsenave@420 2383 (inc index-next)
ocsenave@420 2384 index-next
ocsenave@420 2385 ptn
ocsenave@420 2386 matches)
ocsenave@420 2387 (recur
ocsenave@420 2388 (assoc binds k v)
ocsenave@420 2389 (inc index)
ocsenave@420 2390 index-next
ocsenave@420 2391 start-match
ocsenave@420 2392 (rest to-match)
ocsenave@421 2393 matches)))
ocsenave@421 2394
ocsenave@421 2395 :else
ocsenave@421 2396 (if (= k v)
ocsenave@421 2397 (recur
ocsenave@421 2398 binds
ocsenave@421 2399 (inc index)
ocsenave@421 2400 index-next
ocsenave@421 2401 start-match
ocsenave@421 2402 (rest to-match)
ocsenave@421 2403 matches)
ocsenave@421 2404 (recur
ocsenave@421 2405 {}
ocsenave@421 2406 index-next
ocsenave@421 2407 (inc index-next)
ocsenave@421 2408 index-next
ocsenave@421 2409 ptn
ocsenave@421 2410 matches))
ocsenave@421 2411
ocsenave@421 2412
ocsenave@421 2413
ocsenave@421 2414 )))))
ocsenave@420 2415
ocsenave@412 2416
ocsenave@406 2417
ocsenave@406 2418
ocsenave@410 2419 ;; look for the rainbow badge in memory
ocsenave@410 2420 (println (reduce str (map #(str (first %) "\t" (vec(second %)) "\n") (search-memory (rom) [221] 10))))
ocsenave@410 2421
ocsenave@406 2422
ocsenave@347 2423 (comment
ocsenave@347 2424
ocsenave@347 2425 (def hxc-later
ocsenave@347 2426 "Running this code produces, e.g. hardcoded names NPCs give
ocsenave@347 2427 their pokemon. Will sort through it later."
ocsenave@347 2428 (print (character-codes->str(take 10000
ocsenave@347 2429 (drop 0x71597
ocsenave@347 2430 (rom (root)))))))
ocsenave@347 2431
ocsenave@347 2432 (let [dex
ocsenave@347 2433 (partition-by #(= 0x50 %)
ocsenave@347 2434 (take 2540
ocsenave@347 2435 (drop 0x40687
ocsenave@347 2436 (rom (root)))))]
ocsenave@347 2437 (def dex dex)
ocsenave@347 2438 (def hxc-species
ocsenave@347 2439 (map character-codes->str
ocsenave@347 2440 (take-nth 4 dex))))
ocsenave@347 2441 )
ocsenave@347 2442
ocsenave@347 2443
ocsenave@347 2444 #+end_src
ocsenave@347 2445
ocsenave@348 2446 #+results:
ocsenave@348 2447 : nil
ocsenave@348 2448