annotate org/rom.org @ 412:543a78679971

saving progress...
author Dylan Holmes <ocsenave@gmail.com>
date Fri, 13 Apr 2012 09:07:09 -0500
parents 0406867ead8a
children 4901ba2d3860
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@311 4 #+description:
ocsenave@312 5 #+keywords:
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@311 9
ocsenave@346 10 # about map headers http://datacrystal.romhacking.net/wiki/Pokemon_Red/Blue:Notes
ocsenave@346 11 # map headers Yellow http://www.pokecommunity.com/archive/index.php/t-235311.html
ocsenave@312 12 # pokedollar: U+20B1
ocsenave@347 13 * Introduction
ocsenave@347 14
ocsenave@348 15
ocsenave@348 16 ** COMMENT Getting linguistic data: names, words, etc.
ocsenave@348 17
ocsenave@348 18 Some of the simplest data
ocsenave@348 19
ocsenave@348 20
ocsenave@348 21 One of the simplest data structures in the Pok\eacute{} ROM is an
ocsenave@348 22 unbroken list of strings that either (a) all have a specific length,
ocsenave@348 23 or (b) are all separated by the same character.
ocsenave@348 24
ocsenave@348 25 Because lots of good data has this format, we'll start by writing a
ocsenave@348 26 template function to extract it:
ocsenave@348 27
ocsenave@348 28 #+name: hxc-thunks
ocsenave@348 29 #+begin_src clojure :results silent
ocsenave@348 30 (defn hxc-thunk
ocsenave@348 31 "Creates a thunk (nullary fn) that grabs data in a certain region of rom and
ocsenave@348 32 splits it into a collection by 0x50. If rom is not supplied, uses the
ocsenave@348 33 original rom data."
ocsenave@348 34 [start length]
ocsenave@348 35 (fn self
ocsenave@348 36 ([rom]
ocsenave@348 37 (take-nth 2
ocsenave@348 38 (partition-by #(= % 0x50)
ocsenave@348 39 (take length
ocsenave@348 40 (drop start rom)))))
ocsenave@348 41 ([]
ocsenave@348 42 (self com.aurellem.gb.gb-driver/original-rom))))
ocsenave@348 43
ocsenave@348 44 (def hxc-thunk-words
ocsenave@348 45 "Same as hxc-thunk, except it interprets the rom data as characters,
ocsenave@348 46 returning a collection of strings."
ocsenave@348 47 (comp
ocsenave@348 48 (partial comp (partial map character-codes->str))
ocsenave@348 49 hxc-thunk))
ocsenave@348 50
ocsenave@348 51 #+end_src
ocsenave@348 52
ocsenave@348 53
ocsenave@348 54 * Pok\eacute{}mon I
ocsenave@348 55 ** Names of each species
ocsenave@348 56 The names of the Pok\eacute{}mon species are stored in
ocsenave@348 57 ROM@E8000. This name list is interesting, for a number of reasons:
ocsenave@348 58 - The names are stored in [[ ][internal order]] rather than in the familiar
ocsenave@348 59 Pok\eacute{}dex order. This seemingly random order probably represents the order in which the authors created or
ocsenave@348 60 programmed in the Pok\eacute{}mon; it's used throughout the game.
ocsenave@348 61 - There is enough space allocated for 190 Pok\eacute{}mon. As I
ocsenave@348 62 understand it, there were originally going to be 190 Pok\eacute{}mon
ocsenave@348 63 in Generation I, but the creators decided to defer some to
ocsenave@348 64 Generation II. This explains why many Gen I and Gen II Pok\eacute{}mon
ocsenave@348 65 have the same aesthetic feel.
ocsenave@348 66 - The list is pockmarked with random gaps, due to the strange internal
ocsenave@348 67 ordering
ocsenave@348 68 and the 39 unused spaces [fn::190 allocated spaces minus 151 true Pok\eacute{}mon]. These missing spaces are filled with the
ocsenave@348 69 placeholder name =MISSINGNO.= (\ldquo{}Missing number\rdquo{}).
ocsenave@348 70
ocsenave@348 71 Each name is exactly ten letters long; whenever a name would be too short, the extra
ocsenave@348 72 space is padded with the character 0x50.
ocsenave@348 73
ocsenave@348 74 *** See the data
ocsenave@348 75
ocsenave@348 76 Here you can see the raw data in three stages: in the first stage, we
ocsenave@348 77 just grab the first few bytes starting from position 0xE8000. In the
ocsenave@371 78 second stage, we partition the bytes into ten-letter chunks to show you
ocsenave@348 79 where the names begin and end. In the final stage, we convert each
ocsenave@348 80 byte into the letter it represents using the =character-codes->str=
ocsenave@348 81 function. (0x50 is rendered as the symbol \ldquo{} =#= \rdquo{} for
ocsenave@348 82 ease of reading).
ocsenave@348 83
ocsenave@348 84 #+begin_src clojure :exports both :cache no :results output
ocsenave@348 85 (ns com.aurellem.gb.hxc
ocsenave@348 86 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@348 87 constants))
ocsenave@348 88 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@348 89
ocsenave@371 90
ocsenave@348 91 (println (take 100 (drop 0xE8000 (rom))))
ocsenave@348 92
ocsenave@348 93 (println (partition 10 (take 100 (drop 0xE8000 (rom)))))
ocsenave@348 94
ocsenave@348 95 (println (character-codes->str (take 100 (drop 0xE8000 (rom)))))
ocsenave@348 96
ocsenave@348 97
ocsenave@348 98 #+end_src
ocsenave@348 99
ocsenave@348 100 #+results:
ocsenave@348 101 : (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 102 : ((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 103 : RHYDON####KANGASKHANNIDORAN♂##CLEFAIRY##SPEAROW###VOLTORB###NIDOKING##SLOWBRO###IVYSAUR###EXEGGUTOR#
ocsenave@348 104
ocsenave@348 105
ocsenave@348 106 *** Automatically grab the data.
ocsenave@348 107
ocsenave@348 108 #+name: pokenames
ocsenave@348 109 #+begin_src clojure
ocsenave@348 110
ocsenave@348 111 (defn hxc-pokenames-raw
ocsenave@348 112 "The hardcoded names of the 190 species in memory. List begins at
ocsenave@348 113 ROM@E8000. Although names in memory are padded with 0x50 to be 10 characters
ocsenave@348 114 long, these names are stripped of padding. See also, hxc-pokedex-names"
ocsenave@348 115 ([]
ocsenave@348 116 (hxc-pokenames-raw com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 117 ([rom]
ocsenave@348 118 (let [count-species 190
ocsenave@348 119 name-length 10]
ocsenave@348 120 (map character-codes->str
ocsenave@348 121 (partition name-length
ocsenave@348 122 (map #(if (= 0x50 %) 0x00 %)
ocsenave@348 123 (take (* count-species name-length)
ocsenave@348 124 (drop 0xE8000
ocsenave@348 125 rom))))))))
ocsenave@348 126 (def hxc-pokenames
ocsenave@348 127 (comp
ocsenave@348 128 (partial map format-name)
ocsenave@348 129 hxc-pokenames-raw))
ocsenave@348 130
ocsenave@348 131
ocsenave@348 132
ocsenave@348 133
ocsenave@348 134 (defn hxc-pokedex-names
ocsenave@411 135 "The names of the pokemon in hardcoded pokedex order. List of the
ocsenave@411 136 pokedex numbers of each pokemon (in internal order) begins at
ocsenave@348 137 ROM@410B1. See also, hxc-pokenames."
ocsenave@348 138 ([] (hxc-pokedex-names
ocsenave@348 139 com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 140 ([rom]
ocsenave@348 141 (let [names (hxc-pokenames rom)]
ocsenave@348 142 (#(mapv %
ocsenave@348 143 ((comp range count keys) %))
ocsenave@348 144 (zipmap
ocsenave@348 145 (take (count names)
ocsenave@348 146 (drop 0x410b1 rom))
ocsenave@348 147
ocsenave@348 148 names)))))
ocsenave@348 149
ocsenave@348 150 #+end_src
ocsenave@348 151
ocsenave@348 152
ocsenave@348 153
ocsenave@348 154 ** Generic species information
ocsenave@348 155
ocsenave@348 156 #+name: pokebase
ocsenave@348 157 #+begin_src clojure
ocsenave@348 158 (defn hxc-pokemon-base
ocsenave@348 159 ([] (hxc-pokemon-base com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 160 ([rom]
ocsenave@348 161 (let [entry-size 28
ocsenave@371 162
ocsenave@348 163 pokemon (rest (hxc-pokedex-names))
ocsenave@371 164 pkmn-count (inc(count pokemon))
ocsenave@348 165 types (apply assoc {}
ocsenave@348 166 (interleave
ocsenave@348 167 (range)
ocsenave@348 168 pkmn-types)) ;;!! softcoded
ocsenave@348 169 moves (apply assoc {}
ocsenave@348 170 (interleave
ocsenave@348 171 (range)
ocsenave@348 172 (map format-name
ocsenave@348 173 (hxc-move-names rom))))
ocsenave@348 174 machines (hxc-machines)
ocsenave@348 175 ]
ocsenave@348 176 (zipmap
ocsenave@348 177 pokemon
ocsenave@348 178 (map
ocsenave@348 179 (fn [[n
ocsenave@348 180 rating-hp
ocsenave@348 181 rating-atk
ocsenave@348 182 rating-def
ocsenave@348 183 rating-speed
ocsenave@348 184 rating-special
ocsenave@348 185 type-1
ocsenave@348 186 type-2
ocsenave@348 187 rarity
ocsenave@348 188 rating-xp
ocsenave@348 189 pic-dimensions ;; tile_width|tile_height (8px/tile)
ocsenave@348 190 ptr-pic-obverse-1
ocsenave@348 191 ptr-pic-obverse-2
ocsenave@348 192 ptr-pic-reverse-1
ocsenave@348 193 ptr-pic-reverse-2
ocsenave@348 194 move-1
ocsenave@348 195 move-2
ocsenave@348 196 move-3
ocsenave@348 197 move-4
ocsenave@348 198 growth-rate
ocsenave@348 199 &
ocsenave@348 200 TMs|HMs]]
ocsenave@348 201 (let
ocsenave@348 202 [base-moves
ocsenave@348 203 (mapv moves
ocsenave@348 204 ((comp
ocsenave@348 205 ;; since the game uses zero as a delimiter,
ocsenave@348 206 ;; it must also increment all move indices by 1.
ocsenave@348 207 ;; heren we decrement to correct this.
ocsenave@348 208 (partial map dec)
ocsenave@348 209 (partial take-while (comp not zero?)))
ocsenave@348 210 [move-1 move-2 move-3 move-4]))
ocsenave@348 211
ocsenave@348 212 types
ocsenave@348 213 (set (list (types type-1)
ocsenave@348 214 (types type-2)))
ocsenave@348 215 TMs|HMs
ocsenave@348 216 (map
ocsenave@348 217 (comp
ocsenave@348 218 (partial map first)
ocsenave@348 219 (partial remove (comp zero? second)))
ocsenave@348 220 (split-at
ocsenave@348 221 50
ocsenave@348 222 (map vector
ocsenave@348 223 (rest(range))
ocsenave@348 224 (reduce concat
ocsenave@348 225 (map
ocsenave@348 226 #(take 8
ocsenave@348 227 (concat (bit-list %)
ocsenave@348 228 (repeat 0)))
ocsenave@348 229
ocsenave@348 230 TMs|HMs)))))
ocsenave@348 231
ocsenave@348 232 TMs (vec (first TMs|HMs))
ocsenave@348 233 HMs (take 5 (map (partial + -50) (vec (second TMs|HMs))))
ocsenave@348 234
ocsenave@348 235
ocsenave@348 236 ]
ocsenave@348 237
ocsenave@348 238
ocsenave@348 239 {:dex# n
ocsenave@348 240 :base-moves base-moves
ocsenave@348 241 :types types
ocsenave@348 242 :TMs TMs
ocsenave@348 243 :HMs HMs
ocsenave@348 244 :base-hp rating-hp
ocsenave@348 245 :base-atk rating-atk
ocsenave@348 246 :base-def rating-def
ocsenave@348 247 :base-speed rating-speed
ocsenave@348 248 :base-special rating-special
ocsenave@348 249 :o0 pic-dimensions
ocsenave@348 250 :o1 ptr-pic-obverse-1
ocsenave@348 251 :o2 ptr-pic-obverse-2
ocsenave@348 252 }))
ocsenave@348 253
ocsenave@348 254 (partition entry-size
ocsenave@348 255 (take (* entry-size pkmn-count)
ocsenave@348 256 (drop 0x383DE
ocsenave@348 257 rom))))))))
ocsenave@348 258
ocsenave@348 259 #+end_src
ocsenave@348 260
ocsenave@348 261
ocsenave@348 262 ** Pok\eacute{}mon evolutions
ocsenave@348 263 #+name: evolution-header
ocsenave@348 264 #+begin_src clojure
ocsenave@348 265 (defn format-evo
ocsenave@348 266 "Parse a sequence of evolution data, returning a map. First is the
ocsenave@348 267 method: 0 = end-evolution-data. 1 = level-up, 2 = item, 3 = trade. Next is an item id, if the
ocsenave@348 268 method of evolution is by item (only stones will actually make pokemon
ocsenave@348 269 evolve, for some auxillary reason.) Finally, the minimum level for
ocsenave@348 270 evolution to occur (level 1 means no limit, which is used for trade
ocsenave@348 271 and item evolutions), followed by the internal id of the pokemon
ocsenave@348 272 into which to evolve. Hence, level up and trade evolutions are
ocsenave@348 273 described with 3
ocsenave@348 274 bytes; item evolutions with four."
ocsenave@348 275 [coll]
ocsenave@348 276 (let [method (first coll)]
ocsenave@348 277 (cond (empty? coll) []
ocsenave@348 278 (= 0 method) [] ;; just in case
ocsenave@348 279 (= 1 method) ;; level-up evolution
ocsenave@348 280 (conj (format-evo (drop 3 coll))
ocsenave@348 281 {:method :level-up
ocsenave@348 282 :min-level (nth coll 1)
ocsenave@348 283 :into (dec (nth coll 2))})
ocsenave@348 284
ocsenave@348 285 (= 2 method) ;; item evolution
ocsenave@348 286 (conj (format-evo (drop 4 coll))
ocsenave@348 287 {:method :item
ocsenave@348 288 :item (dec (nth coll 1))
ocsenave@348 289 :min-level (nth coll 2)
ocsenave@348 290 :into (dec (nth coll 3))})
ocsenave@348 291
ocsenave@348 292 (= 3 method) ;; trade evolution
ocsenave@348 293 (conj (format-evo (drop 3 coll))
ocsenave@348 294 {:method :trade
ocsenave@348 295 :min-level (nth coll 1) ;; always 1 for trade.
ocsenave@348 296 :into (dec (nth coll 2))}))))
ocsenave@348 297
ocsenave@348 298
ocsenave@348 299 (defn hxc-ptrs-evolve
ocsenave@348 300 "A hardcoded collection of 190 pointers to alternating evolution/learnset data,
ocsenave@348 301 in internal order."
ocsenave@348 302 ([]
ocsenave@348 303 (hxc-ptrs-evolve com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 304 ([rom]
ocsenave@348 305 (let [
ocsenave@348 306 pkmn-count (count (hxc-pokenames-raw)) ;; 190
ocsenave@348 307 ptrs
ocsenave@348 308 (map (fn [[a b]] (low-high a b))
ocsenave@348 309 (partition 2
ocsenave@348 310 (take (* 2 pkmn-count)
ocsenave@348 311 (drop 0x3b1e5 rom))))]
ocsenave@348 312 (map (partial + 0x34000) ptrs)
ocsenave@348 313
ocsenave@348 314 )))
ocsenave@348 315 #+end_src
ocsenave@348 316
ocsenave@348 317 #+name:evolution
ocsenave@348 318 #+begin_src clojure
ocsenave@348 319
ocsenave@348 320 (defn hxc-evolution
ocsenave@348 321 "Hardcoded evolution data in memory. The data exists at ROM@34000,
ocsenave@348 322 sorted by internal order. Pointers to the data exist at ROM@3B1E5; see also, hxc-ptrs-evolve."
ocsenave@348 323 ([] (hxc-evolution com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 324 ([rom]
ocsenave@348 325 (apply assoc {}
ocsenave@348 326 (interleave
ocsenave@348 327 (hxc-pokenames rom)
ocsenave@348 328 (map
ocsenave@348 329 (comp
ocsenave@348 330 format-evo
ocsenave@348 331 (partial take-while (comp not zero?))
ocsenave@348 332 #(drop % rom))
ocsenave@348 333 (hxc-ptrs-evolve rom)
ocsenave@348 334 )))))
ocsenave@348 335
ocsenave@348 336 (defn hxc-evolution-pretty
ocsenave@348 337 "Like hxc-evolution, except it uses the names of items and pokemon
ocsenave@348 338 --- grabbed from ROM --- rather than their numerical identifiers."
ocsenave@348 339 ([] (hxc-evolution-pretty com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 340 ([rom]
ocsenave@348 341 (let
ocsenave@348 342 [poke-names (vec (hxc-pokenames rom))
ocsenave@348 343 item-names (vec (hxc-items rom))
ocsenave@348 344 use-names
ocsenave@348 345 (fn [m]
ocsenave@348 346 (loop [ks (keys m) new-map m]
ocsenave@348 347 (let [k (first ks)]
ocsenave@348 348 (cond (nil? ks) new-map
ocsenave@348 349 (= k :into)
ocsenave@348 350 (recur
ocsenave@348 351 (next ks)
ocsenave@348 352 (assoc new-map
ocsenave@348 353 :into
ocsenave@348 354 (poke-names
ocsenave@348 355 (:into
ocsenave@348 356 new-map))))
ocsenave@348 357 (= k :item)
ocsenave@348 358 (recur
ocsenave@348 359 (next ks)
ocsenave@348 360 (assoc new-map
ocsenave@348 361 :item
ocsenave@348 362 (item-names
ocsenave@348 363 (:item new-map))))
ocsenave@348 364 :else
ocsenave@348 365 (recur
ocsenave@348 366 (next ks)
ocsenave@348 367 new-map)
ocsenave@348 368 ))))]
ocsenave@348 369
ocsenave@348 370 (into {}
ocsenave@348 371 (map (fn [[pkmn evo-coll]]
ocsenave@348 372 [pkmn (map use-names evo-coll)])
ocsenave@348 373 (hxc-evolution rom))))))
ocsenave@348 374
ocsenave@348 375
ocsenave@348 376 #+end_src
ocsenave@348 377
ocsenave@348 378
ocsenave@348 379 ** Level-up moves (learnsets)
ocsenave@348 380 #+name: learnsets
ocsenave@348 381 #+begin_src clojure
ocsenave@348 382
ocsenave@348 383
ocsenave@348 384 (defn hxc-learnsets
ocsenave@348 385 "Hardcoded map associating pokemon names to lists of pairs [lvl
ocsenave@348 386 move] of abilities they learn as they level up. The data
ocsenave@348 387 exists at ROM@34000, sorted by internal order. Pointers to the data
ocsenave@348 388 exist at ROM@3B1E5; see also, hxc-ptrs-evolve"
ocsenave@348 389 ([] (hxc-learnsets com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 390 ([rom]
ocsenave@348 391 (apply assoc
ocsenave@348 392 {}
ocsenave@348 393 (interleave
ocsenave@348 394 (hxc-pokenames rom)
ocsenave@348 395 (map (comp
ocsenave@348 396 (partial map
ocsenave@348 397 (fn [[lvl mv]] [lvl (dec mv)]))
ocsenave@348 398 (partial partition 2)
ocsenave@348 399 ;; keep the learnset data
ocsenave@348 400 (partial take-while (comp not zero?))
ocsenave@348 401 ;; skip the evolution data
ocsenave@348 402 rest
ocsenave@348 403 (partial drop-while (comp not zero?)))
ocsenave@348 404 (map #(drop % rom)
ocsenave@348 405 (hxc-ptrs-evolve rom)))))))
ocsenave@348 406
ocsenave@348 407 (defn hxc-learnsets-pretty
ocsenave@348 408 "Live hxc-learnsets except it reports the name of each move --- as
ocsenave@348 409 it appears in rom --- rather than the move index."
ocsenave@348 410 ([] (hxc-learnsets-pretty com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 411 ([rom]
ocsenave@348 412 (let [moves (vec(map format-name (hxc-move-names)))]
ocsenave@348 413 (into {}
ocsenave@348 414 (map (fn [[pkmn learnset]]
ocsenave@348 415 [pkmn (map (fn [[lvl mv]] [lvl (moves mv)])
ocsenave@348 416 learnset)])
ocsenave@348 417 (hxc-learnsets rom))))))
ocsenave@348 418
ocsenave@348 419
ocsenave@348 420
ocsenave@348 421 #+end_src
ocsenave@348 422
ocsenave@348 423
ocsenave@348 424
ocsenave@348 425 * Pok\eacute{}mon II : the Pok\eacute{}dex
ocsenave@348 426 ** Species vital stats
ocsenave@348 427 #+name: dex-stats
ocsenave@348 428 #+begin_src clojure
ocsenave@348 429 (defn hxc-pokedex-stats
ocsenave@348 430 "The hardcoded pokedex stats (species height weight) in memory. List
ocsenave@348 431 begins at ROM@40687"
ocsenave@348 432 ([] (hxc-pokedex-stats com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 433 ([rom]
ocsenave@348 434 (let [pokedex-names (zipmap (range) (hxc-pokedex-names rom))
ocsenave@348 435 pkmn-count (count pokedex-names)
ocsenave@348 436 ]
ocsenave@348 437 ((fn capture-stats
ocsenave@348 438 [n stats data]
ocsenave@348 439 (if (zero? n) stats
ocsenave@348 440 (let [[species
ocsenave@348 441 [_
ocsenave@348 442 height-ft
ocsenave@348 443 height-in
ocsenave@348 444 weight-1
ocsenave@348 445 weight-2
ocsenave@348 446 _
ocsenave@348 447 dex-ptr-1
ocsenave@348 448 dex-ptr-2
ocsenave@348 449 dex-bank
ocsenave@348 450 _
ocsenave@348 451 & data]]
ocsenave@348 452 (split-with (partial not= 0x50) data)]
ocsenave@348 453 (recur (dec n)
ocsenave@348 454 (assoc stats
ocsenave@348 455 (pokedex-names (- pkmn-count (dec n)))
ocsenave@348 456 {:species
ocsenave@348 457 (format-name (character-codes->str species))
ocsenave@348 458 :height-ft
ocsenave@348 459 height-ft
ocsenave@348 460 :height-in
ocsenave@348 461 height-in
ocsenave@348 462 :weight
ocsenave@348 463 (/ (low-high weight-1 weight-2) 10.)
ocsenave@348 464
ocsenave@348 465 ;; :text
ocsenave@348 466 ;; (character-codes->str
ocsenave@348 467 ;; (take-while
ocsenave@348 468 ;; (partial not= 0x50)
ocsenave@348 469 ;; (drop
ocsenave@348 470 ;; (+ 0xB8000
ocsenave@348 471 ;; -0x4000
ocsenave@348 472 ;; (low-high dex-ptr-1 dex-ptr-2))
ocsenave@348 473 ;; rom)))
ocsenave@348 474 })
ocsenave@348 475
ocsenave@348 476 data)
ocsenave@348 477
ocsenave@348 478
ocsenave@348 479 )))
ocsenave@348 480
ocsenave@348 481 pkmn-count
ocsenave@348 482 {}
ocsenave@348 483 (drop 0x40687 rom))) ))
ocsenave@348 484 #+end_src
ocsenave@348 485
ocsenave@411 486 #+results: dex-stats
ocsenave@411 487 : #'com.aurellem.gb.hxc/hxc-pokedex-stats
ocsenave@411 488
ocsenave@348 489 ** Species synopses
ocsenave@348 490
ocsenave@348 491 #+name: dex-text
ocsenave@348 492 #+begin_src clojure
ocsenave@348 493 (def hxc-pokedex-text-raw
ocsenave@348 494 "The hardcoded pokedex entries in memory. List begins at
ocsenave@348 495 ROM@B8000, shortly before move names."
ocsenave@348 496 (hxc-thunk-words 0xB8000 14754))
ocsenave@348 497
ocsenave@348 498
ocsenave@348 499
ocsenave@348 500
ocsenave@348 501 (defn hxc-pokedex-text
ocsenave@348 502 "The hardcoded pokedex entries in memory, presented as an
ocsenave@348 503 associative hash map. List begins at ROM@B8000."
ocsenave@348 504 ([] (hxc-pokedex-text com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 505 ([rom]
ocsenave@348 506 (zipmap
ocsenave@348 507 (hxc-pokedex-names rom)
ocsenave@348 508 (cons nil ;; for missingno.
ocsenave@348 509 (hxc-pokedex-text-raw rom)))))
ocsenave@348 510 #+end_src
ocsenave@348 511
ocsenave@348 512
ocsenave@348 513 ** Pok\eacute{}mon cries
ocsenave@348 514 #+name: pokecry
ocsenave@348 515 #+begin_src clojure
ocsenave@348 516 (defn hxc-cry
ocsenave@348 517 "The pokemon cry data in internal order. List begins at ROM@39462"
ocsenave@348 518 ([](hxc-cry com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 519 ([rom]
ocsenave@348 520 (zipmap
ocsenave@348 521 (hxc-pokenames rom)
ocsenave@348 522 (map
ocsenave@348 523 (fn [[cry-id pitch length]]
ocsenave@348 524 {:cry-id cry-id
ocsenave@348 525 :pitch pitch
ocsenave@348 526 :length length}
ocsenave@348 527 )
ocsenave@348 528 (partition 3
ocsenave@348 529 (drop 0x39462 rom))))))
ocsenave@348 530
ocsenave@348 531 (defn hxc-cry-groups
ocsenave@348 532 ([] (hxc-cry-groups com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 533 ([rom]
ocsenave@348 534 (map #(mapv first
ocsenave@348 535 (filter
ocsenave@348 536 (fn [[k v]]
ocsenave@348 537 (= % (:cry-id v)))
ocsenave@348 538 (hxc-cry)))
ocsenave@348 539 ((comp
ocsenave@348 540 range
ocsenave@348 541 count
ocsenave@348 542 set
ocsenave@348 543 (partial map :cry-id)
ocsenave@348 544 vals
ocsenave@348 545 hxc-cry)
ocsenave@348 546 rom))))
ocsenave@348 547
ocsenave@348 548
ocsenave@348 549 (defn cry-conversion!
ocsenave@348 550 "Convert Porygon's cry in ROM to be the cry of the given pokemon."
ocsenave@348 551 [pkmn]
ocsenave@348 552 (write-rom!
ocsenave@348 553 (rewrite-memory
ocsenave@348 554 (vec(rom))
ocsenave@348 555 0x3965D
ocsenave@348 556 (map second
ocsenave@348 557 ((hxc-cry) pkmn)))))
ocsenave@348 558
ocsenave@348 559 #+end_src
ocsenave@348 560
ocsenave@348 561 ** COMMENT Names of permanent stats
ocsenave@348 562 0DD4D-DD72
ocsenave@348 563
ocsenave@348 564 * Items
ocsenave@348 565 ** Item names
ocsenave@371 566
ocsenave@371 567 *** See the data
ocsenave@371 568 #+begin_src clojure :exports both :results output
ocsenave@371 569 (ns com.aurellem.gb.hxc
ocsenave@371 570 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@371 571 constants))
ocsenave@371 572 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@371 573
ocsenave@371 574 (println (take 100 (drop 0x045B7 (rom))))
ocsenave@371 575
ocsenave@371 576 (println
ocsenave@371 577 (partition-by
ocsenave@371 578 (partial = 0x50)
ocsenave@371 579 (take 100 (drop 0x045B7 (rom)))))
ocsenave@371 580
ocsenave@371 581 (println
ocsenave@371 582 (map character-codes->str
ocsenave@371 583 (partition-by
ocsenave@371 584 (partial = 0x50)
ocsenave@371 585 (take 100 (drop 0x045B7 (rom))))))
ocsenave@371 586
ocsenave@371 587
ocsenave@371 588 #+end_src
ocsenave@371 589
ocsenave@371 590 #+results:
ocsenave@371 591 : (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 592 : ((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 593 : (MASTER BALL # ULTRA BALL # GREAT BALL # POKĂ© BALL # TOWN MAP # BICYCLE # ????? # SAFARI BALL # POKĂ©DEX # MOON STONE # AN)
ocsenave@371 594
ocsenave@371 595 *** Automatically grab the data
ocsenave@348 596 #+name: item-names
ocsenave@348 597 #+begin_src clojure
ocsenave@348 598
ocsenave@348 599 (def hxc-items-raw
ocsenave@348 600 "The hardcoded names of the items in memory. List begins at
ocsenave@348 601 ROM@045B7"
ocsenave@348 602 (hxc-thunk-words 0x45B7 870))
ocsenave@348 603
ocsenave@348 604 (def hxc-items
ocsenave@348 605 "The hardcoded names of the items in memory, presented as
ocsenave@348 606 keywords. List begins at ROM@045B7. See also, hxc-items-raw."
ocsenave@348 607 (comp (partial map format-name) hxc-items-raw))
ocsenave@348 608 #+end_src
ocsenave@348 609
ocsenave@348 610 ** Item prices
ocsenave@371 611
ocsenave@371 612 ***
ocsenave@371 613 #+begin_src clojure :exports both :results output
ocsenave@371 614 (ns com.aurellem.gb.hxc
ocsenave@371 615 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@371 616 constants))
ocsenave@371 617 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@371 618
ocsenave@371 619 (println (take 90 (drop 0x4495 (rom))))
ocsenave@371 620
ocsenave@371 621 (println
ocsenave@371 622 (partition 3
ocsenave@371 623 (take 90 (drop 0x4495 (rom)))))
ocsenave@371 624
ocsenave@371 625 (println
ocsenave@371 626 (partition 3
ocsenave@371 627 (map hex
ocsenave@371 628 (take 90 (drop 0x4495 (rom))))))
ocsenave@371 629
ocsenave@371 630 (println
ocsenave@371 631 (map decode-bcd
ocsenave@371 632 (map butlast
ocsenave@371 633 (partition 3
ocsenave@371 634 (take 90 (drop 0x4495 (rom)))))))
ocsenave@371 635
ocsenave@371 636 (println
ocsenave@371 637 (map
ocsenave@371 638 vector
ocsenave@371 639 (hxc-items (rom))
ocsenave@371 640 (map decode-bcd
ocsenave@371 641 (map butlast
ocsenave@371 642 (partition 3
ocsenave@371 643 (take 90 (drop 0x4495 (rom))))))))
ocsenave@371 644
ocsenave@371 645
ocsenave@371 646
ocsenave@371 647
ocsenave@371 648
ocsenave@371 649 #+end_src
ocsenave@371 650
ocsenave@371 651 #+results:
ocsenave@371 652 : (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 653 : ((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 654 : ((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 655 : (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 656 : ([: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 657
ocsenave@371 658
ocsenave@371 659 ***
ocsenave@348 660 #+name: item-prices
ocsenave@348 661 #+begin_src clojure
ocsenave@348 662 (defn hxc-item-prices
ocsenave@348 663 "The hardcoded list of item prices in memory. List begins at ROM@4495"
ocsenave@348 664 ([] (hxc-item-prices com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 665 ([rom]
ocsenave@348 666 (let [items (hxc-items rom)
ocsenave@348 667 price-size 3]
ocsenave@348 668 (zipmap items
ocsenave@348 669 (map (comp
ocsenave@348 670 ;; zero-cost items are "priceless"
ocsenave@348 671 #(if (zero? %) :priceless %)
ocsenave@348 672 decode-bcd butlast)
ocsenave@348 673 (partition price-size
ocsenave@348 674 (take (* price-size (count items))
ocsenave@348 675 (drop 0x4495 rom))))))))
ocsenave@348 676 #+end_src
ocsenave@348 677 ** Vendor inventories
ocsenave@348 678
ocsenave@348 679 #+name: item-vendors
ocsenave@348 680 #+begin_src clojure
ocsenave@348 681 (defn hxc-shops
ocsenave@348 682 ([] (hxc-shops com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 683 ([rom]
ocsenave@348 684 (let [items (zipmap (range) (hxc-items rom))
ocsenave@348 685
ocsenave@348 686 ;; temporarily softcode the TM items
ocsenave@348 687 items (into
ocsenave@348 688 items
ocsenave@348 689 (map (juxt identity
ocsenave@348 690 (comp keyword
ocsenave@348 691 (partial str "tm-")
ocsenave@348 692 (partial + 1 -200)
ocsenave@348 693 ))
ocsenave@348 694 (take 200 (drop 200 (range)))))
ocsenave@348 695
ocsenave@348 696 ]
ocsenave@348 697
ocsenave@348 698 ((fn parse-shop [coll [num-items & items-etc]]
ocsenave@348 699 (let [inventory (take-while
ocsenave@348 700 (partial not= 0xFF)
ocsenave@348 701 items-etc)
ocsenave@348 702 [separator & items-etc] (drop num-items (rest items-etc))]
ocsenave@348 703 (if (= separator 0x50)
ocsenave@348 704 (map (partial mapv (comp items dec)) (conj coll inventory))
ocsenave@348 705 (recur (conj coll inventory) items-etc)
ocsenave@348 706 )
ocsenave@348 707 ))
ocsenave@348 708
ocsenave@348 709 '()
ocsenave@348 710 (drop 0x233C rom))
ocsenave@348 711
ocsenave@348 712
ocsenave@348 713 )))
ocsenave@348 714 #+end_src
ocsenave@348 715
ocsenave@348 716 #+results: item-vendors
ocsenave@348 717 : #'com.aurellem.gb.hxc/hxc-shops
ocsenave@348 718
ocsenave@348 719
ocsenave@348 720
ocsenave@348 721 * Types
ocsenave@348 722 ** Names of types
ocsenave@406 723
ocsenave@406 724 *** COMMENT Pointers to type names
ocsenave@406 725 #+begin_src clojure :exports both :results output
ocsenave@406 726 (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 727 #+end_src
ocsenave@406 728
ocsenave@406 729
ocsenave@371 730 ***
ocsenave@371 731 #+begin_src clojure :exports both :results output
ocsenave@371 732 (ns com.aurellem.gb.hxc
ocsenave@371 733 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@371 734 constants))
ocsenave@371 735 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@371 736
ocsenave@371 737 (println (take 90 (drop 0x27D99 (rom))))
ocsenave@371 738
ocsenave@371 739 (println
ocsenave@371 740 (partition-by (partial = 0x50)
ocsenave@371 741 (take 90 (drop 0x27D99 (rom)))))
ocsenave@371 742
ocsenave@371 743 (println
ocsenave@371 744 (map character-codes->str
ocsenave@371 745 (partition-by (partial = 0x50)
ocsenave@371 746 (take 90 (drop 0x27D99 (rom))))))
ocsenave@371 747
ocsenave@371 748 #+end_src
ocsenave@371 749
ocsenave@371 750 #+results:
ocsenave@371 751 : (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 752 : ((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 753 : (NORMAL # FIGHTING # FLYING # POISON # FIRE # WATER # GRASS # ELECTRIC # PSYCHIC # ICE # GROUND # ROCK # BIRD # BUG # G)
ocsenave@371 754
ocsenave@371 755
ocsenave@371 756 ***
ocsenave@348 757 #+name: type-names
ocsenave@348 758 #+begin_src clojure
ocsenave@348 759 (def hxc-types
ocsenave@348 760 "The hardcoded type names in memory. List begins at ROM@27D99,
ocsenave@348 761 shortly before hxc-titles."
ocsenave@348 762 (hxc-thunk-words 0x27D99 102))
ocsenave@348 763
ocsenave@348 764 #+end_src
ocsenave@348 765
ocsenave@348 766 ** Type effectiveness
ocsenave@371 767 ***
ocsenave@371 768 #+begin_src clojure :exports both :results output
ocsenave@371 769 (ns com.aurellem.gb.hxc
ocsenave@371 770 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@371 771 constants))
ocsenave@371 772 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@371 773
ocsenave@371 774
ocsenave@371 775 ;; POKEMON TYPES
ocsenave@371 776
ocsenave@371 777 (println pkmn-types) ;; these are the pokemon types
ocsenave@371 778 (println (map vector (range) pkmn-types)) ;; each type has an id number.
ocsenave@371 779
ocsenave@371 780 (newline)
ocsenave@371 781
ocsenave@371 782
ocsenave@371 783
ocsenave@371 784
ocsenave@371 785 ;;; TYPE EFFECTIVENESS
ocsenave@371 786
ocsenave@371 787 (println (take 15 (drop 0x3E62D (rom))))
ocsenave@371 788 (println (partition 3 (take 15 (drop 0x3E62D (rom)))))
ocsenave@371 789
ocsenave@371 790 (println
ocsenave@371 791 (map
ocsenave@371 792 (fn [[atk-type def-type multiplier]]
ocsenave@371 793 (list atk-type def-type (/ multiplier 10.)))
ocsenave@371 794
ocsenave@371 795 (partition 3
ocsenave@371 796 (take 15 (drop 0x3E62D (rom))))))
ocsenave@371 797
ocsenave@371 798
ocsenave@371 799 (println
ocsenave@371 800 (map
ocsenave@371 801 (fn [[atk-type def-type multiplier]]
ocsenave@371 802 [
ocsenave@371 803 (get pkmn-types atk-type)
ocsenave@371 804 (get pkmn-types def-type)
ocsenave@371 805 (/ multiplier 10.)
ocsenave@371 806 ])
ocsenave@371 807
ocsenave@371 808 (partition 3
ocsenave@371 809 (take 15 (drop 0x3E62D (rom))))))
ocsenave@371 810
ocsenave@371 811 #+end_src
ocsenave@371 812
ocsenave@371 813 #+results:
ocsenave@371 814 : [: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 815 : ([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 816 :
ocsenave@371 817 : (0 5 5 0 8 0 8 8 20 20 7 20 20 5 5)
ocsenave@371 818 : ((0 5 5) (0 8 0) (8 8 20) (20 7 20) (20 5 5))
ocsenave@371 819 : ((0 5 0.5) (0 8 0.0) (8 8 2.0) (20 7 2.0) (20 5 0.5))
ocsenave@371 820 : ([:normal :rock 0.5] [:normal :ghost 0.0] [:ghost :ghost 2.0] [:fire :bug 2.0] [:fire :rock 0.5])
ocsenave@371 821
ocsenave@371 822
ocsenave@371 823 ***
ocsenave@372 824
ocsenave@349 825 #+name: type-advantage
ocsenave@348 826 #+begin_src clojure
ocsenave@348 827 (defn hxc-advantage
ocsenave@348 828 ;; in-game multipliers are stored as 10x their effective value
ocsenave@348 829 ;; to allow for fractional multipliers like 1/2
ocsenave@348 830
ocsenave@348 831 "The hardcoded type advantages in memory, returned as tuples of
ocsenave@348 832 atk-type def-type multiplier. By default (i.e. if not listed here),
ocsenave@348 833 the multiplier is 1. List begins at 0x3E62D."
ocsenave@348 834 ([] (hxc-advantage com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 835 ([rom]
ocsenave@348 836 (map
ocsenave@348 837 (fn [[atk def mult]] [(get pkmn-types atk (hex atk))
ocsenave@348 838 (get pkmn-types def (hex def))
ocsenave@348 839 (/ mult 10)])
ocsenave@348 840 (partition 3
ocsenave@348 841 (take-while (partial not= 0xFF)
ocsenave@348 842 (drop 0x3E62D rom))))))
ocsenave@348 843 #+end_src
ocsenave@348 844
ocsenave@348 845
ocsenave@348 846
ocsenave@348 847 * Moves
ocsenave@348 848 ** Names of moves
ocsenave@371 849 *** See the data
ocsenave@371 850 #+begin_src clojure :exports both :results output
ocsenave@371 851 (ns com.aurellem.gb.hxc
ocsenave@371 852 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@371 853 constants))
ocsenave@371 854 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@371 855
ocsenave@371 856 (println (take 100 (drop 0xBC000 (rom))))
ocsenave@371 857
ocsenave@371 858 (println
ocsenave@371 859 (partition-by
ocsenave@371 860 (partial = 0x50)
ocsenave@371 861 (take 100 (drop 0xBC000 (rom)))))
ocsenave@371 862
ocsenave@371 863 (println
ocsenave@371 864 (map character-codes->str
ocsenave@371 865 (partition-by
ocsenave@371 866 (partial = 0x50)
ocsenave@371 867 (take 100 (drop 0xBC000 (rom))))))
ocsenave@371 868
ocsenave@371 869
ocsenave@371 870 #+end_src
ocsenave@371 871
ocsenave@371 872 #+results:
ocsenave@371 873 : (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 874 : ((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 875 : (POUND # KARATE CHOP # DOUBLESLAP # COMET PUNCH # MEGA PUNCH # PAY DAY # FIRE PUNCH # ICE PUNCH # THUNDERPUNCH # SCRATC)
ocsenave@371 876
ocsenave@371 877 *** Automatically grab the data
ocsenave@371 878
ocsenave@348 879 #+name: move-names
ocsenave@348 880 #+begin_src clojure
ocsenave@348 881 (def hxc-move-names
ocsenave@348 882 "The hardcoded move names in memory. List begins at ROM@BC000"
ocsenave@348 883 (hxc-thunk-words 0xBC000 1551))
ocsenave@348 884 #+end_src
ocsenave@348 885
ocsenave@348 886 ** Properties of moves
ocsenave@348 887
ocsenave@348 888 #+name: move-data
ocsenave@348 889 #+begin_src clojure
ocsenave@348 890 (defn hxc-move-data
ocsenave@348 891 "The hardcoded (basic (move effects)) in memory. List begins at
ocsenave@348 892 0x38000. Returns a map of {:name :power :accuracy :pp :fx-id
ocsenave@348 893 :fx-txt}. The move descriptions are handwritten, not hardcoded."
ocsenave@348 894 ([]
ocsenave@348 895 (hxc-move-data com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 896 ([rom]
ocsenave@348 897 (let [names (vec (hxc-move-names rom))
ocsenave@348 898 move-count (count names)
ocsenave@348 899 move-size 6
ocsenave@348 900 types pkmn-types ;;; !! hardcoded types
ocsenave@348 901 ]
ocsenave@348 902 (zipmap (map format-name names)
ocsenave@348 903 (map
ocsenave@348 904 (fn [[idx effect power type-id accuracy pp]]
ocsenave@348 905 {:name (names (dec idx))
ocsenave@348 906 :power power
ocsenave@348 907 :accuracy accuracy
ocsenave@348 908 :pp pp
ocsenave@348 909 :type (types type-id)
ocsenave@348 910 :fx-id effect
ocsenave@348 911 :fx-txt (get move-effects effect)
ocsenave@348 912 }
ocsenave@348 913 )
ocsenave@348 914
ocsenave@348 915 (partition move-size
ocsenave@348 916 (take (* move-size move-count)
ocsenave@348 917 (drop 0x38000 rom))))))))
ocsenave@348 918
ocsenave@348 919
ocsenave@348 920
ocsenave@348 921 (defn hxc-move-data*
ocsenave@348 922 "Like hxc-move-data, but reports numbers as hexadecimal symbols instead."
ocsenave@348 923 ([]
ocsenave@348 924 (hxc-move-data* com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 925 ([rom]
ocsenave@348 926 (let [names (vec (hxc-move-names rom))
ocsenave@348 927 move-count (count names)
ocsenave@348 928 move-size 6
ocsenave@348 929 format-name (fn [s]
ocsenave@348 930 (keyword (.toLowerCase
ocsenave@348 931 (apply str
ocsenave@348 932 (map #(if (= % \space) "-" %) s)))))
ocsenave@348 933 ]
ocsenave@348 934 (zipmap (map format-name names)
ocsenave@348 935 (map
ocsenave@348 936 (fn [[idx effect power type accuracy pp]]
ocsenave@348 937 {:name (names (dec idx))
ocsenave@348 938 :power power
ocsenave@348 939 :accuracy (hex accuracy)
ocsenave@348 940 :pp pp
ocsenave@348 941 :fx-id (hex effect)
ocsenave@348 942 :fx-txt (get move-effects effect)
ocsenave@348 943 }
ocsenave@348 944 )
ocsenave@348 945
ocsenave@348 946 (partition move-size
ocsenave@348 947 (take (* move-size move-count)
ocsenave@348 948 (drop 0x38000 rom))))))))
ocsenave@348 949
ocsenave@348 950 #+end_src
ocsenave@348 951
ocsenave@348 952 ** TM and HM moves
ocsenave@371 953 ***
ocsenave@371 954 #+begin_src clojure :exports both :results output
ocsenave@371 955 (ns com.aurellem.gb.hxc
ocsenave@371 956 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@371 957 constants))
ocsenave@371 958 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@348 959
ocsenave@371 960
ocsenave@371 961 (println (hxc-move-names))
ocsenave@371 962 (println (map vector (rest(range)) (hxc-move-names)))
ocsenave@371 963
ocsenave@371 964 (newline)
ocsenave@371 965
ocsenave@371 966 (println (take 55 (drop 0x1232D (rom))))
ocsenave@371 967
ocsenave@371 968 (println
ocsenave@371 969 (interpose "."
ocsenave@371 970 (map
ocsenave@371 971 (zipmap (rest (range)) (hxc-move-names))
ocsenave@371 972 (take 55 (drop 0x1232D (rom))))))
ocsenave@371 973
ocsenave@371 974 #+end_src
ocsenave@371 975
ocsenave@371 976 #+results:
ocsenave@371 977 : (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 978 : ([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 979 :
ocsenave@371 980 : (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 981 : (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 982
ocsenave@371 983
ocsenave@371 984 ***
ocsenave@348 985 #+name: machines
ocsenave@348 986 #+begin_src clojure
ocsenave@348 987 (defn hxc-machines
ocsenave@348 988 "The hardcoded moves taught by TMs and HMs. List begins at ROM@1232D."
ocsenave@348 989 ([] (hxc-machines
ocsenave@348 990 com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 991 ([rom]
ocsenave@348 992 (let [moves (hxc-move-names rom)]
ocsenave@348 993 (zipmap
ocsenave@348 994 (range)
ocsenave@348 995 (take-while
ocsenave@348 996 (comp not nil?)
ocsenave@348 997 (map (comp
ocsenave@348 998 format-name
ocsenave@348 999 (zipmap
ocsenave@348 1000 (range)
ocsenave@348 1001 moves)
ocsenave@348 1002 dec)
ocsenave@348 1003 (take 100
ocsenave@348 1004 (drop 0x1232D rom))))))))
ocsenave@348 1005
ocsenave@348 1006 #+end_src
ocsenave@348 1007
ocsenave@348 1008
ocsenave@348 1009
ocsenave@348 1010
ocsenave@348 1011
ocsenave@348 1012 ** COMMENT Status ailments
ocsenave@348 1013
ocsenave@348 1014 * Places
ocsenave@348 1015 ** Names of places
ocsenave@348 1016
ocsenave@348 1017 #+name: places
ocsenave@348 1018 #+begin_src clojure
ocsenave@348 1019 (def hxc-places
ocsenave@348 1020 "The hardcoded place names in memory. List begins at
ocsenave@348 1021 ROM@71500. [Cinnabar] Mansion seems to be dynamically calculated."
ocsenave@348 1022 (hxc-thunk-words 0x71500 560))
ocsenave@348 1023
ocsenave@348 1024 #+end_src
ocsenave@348 1025
ocsenave@348 1026 ** Wild Pok\eacute{}mon demographics
ocsenave@348 1027 #+name: wilds
ocsenave@348 1028 #+begin_src clojure
ocsenave@348 1029
ocsenave@348 1030
ocsenave@348 1031
ocsenave@348 1032 (defn hxc-ptrs-wild
ocsenave@348 1033 "A list of the hardcoded wild encounter data in memory. Pointers
ocsenave@348 1034 begin at ROM@0CB95; data begins at ROM@0x04D89"
ocsenave@348 1035 ([] (hxc-ptrs-wild com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 1036 ([rom]
ocsenave@348 1037 (let [ptrs
ocsenave@348 1038 (map (fn [[a b]] (+ a (* 0x100 b)))
ocsenave@348 1039 (take-while (partial not= (list 0xFF 0xFF))
ocsenave@348 1040 (partition 2 (drop 0xCB95 rom))))]
ocsenave@348 1041 ptrs)))
ocsenave@348 1042
ocsenave@348 1043
ocsenave@348 1044
ocsenave@348 1045 (defn hxc-wilds
ocsenave@348 1046 "A list of the hardcoded wild encounter data in memory. Pointers
ocsenave@348 1047 begin at ROM@0CB95; data begins at ROM@0x04D89"
ocsenave@348 1048 ([] (hxc-wilds com.aurellem.gb.gb-driver/original-rom))
ocsenave@348 1049 ([rom]
ocsenave@348 1050 (let [pokenames (zipmap (range) (hxc-pokenames rom))]
ocsenave@348 1051 (map
ocsenave@348 1052 (partial map (fn [[a b]] {:species (pokenames (dec b)) :level
ocsenave@348 1053 a}))
ocsenave@348 1054 (partition 10
ocsenave@348 1055
ocsenave@348 1056 (take-while (comp (partial not= 1)
ocsenave@348 1057 first)
ocsenave@348 1058 (partition 2
ocsenave@348 1059 (drop 0xCD8C rom))
ocsenave@348 1060
ocsenave@348 1061 ))))))
ocsenave@348 1062
ocsenave@348 1063 #+end_src
ocsenave@348 1064
ocsenave@348 1065
ocsenave@348 1066
ocsenave@348 1067
ocsenave@348 1068
ocsenave@348 1069 * Appendices
ocsenave@348 1070
ocsenave@348 1071
ocsenave@348 1072
ocsenave@347 1073 ** Mapping the ROM
ocsenave@311 1074
ocsenave@411 1075 | ROM address (hex) | Description | Format | Example |
ocsenave@411 1076 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1077 | | <15> | <15> | <15> |
ocsenave@411 1078 | 01823-0184A | Important prefix strings. | Variable-length strings, separated by 0x50. | TM#TRAINER#PC#ROCKET#POK\eacute{}#... |
ocsenave@411 1079 | 0233C- | Shop inventories. | | |
ocsenave@412 1080 | 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@411 1081 | 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 1082 | 04524-04527 | (unconfirmed) possibly the bike price in Cerulean. | | |
ocsenave@411 1083 | 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@411 1084 | 04D89- | Lists of wild Pok\eacute{}mon to encounter in each region. | Each list contains ten Pokemon (ids) and their levels; twenty bytes in total. First, the level of the first Pokemon. Then the internal id of the first Pokemon. Next, the level of the second Pokemon, and so on. Since Pokemon cannot have level 0, the lists are separated by a pair 0 /X/, where /X/ is an apparently random Pokemon id. | The first list is (3 36 4 36 2 165 3 165 2 36 3 36 5 36 4 165 6 36 7 36 0 25), i.e. 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, \ldquo{}level 0 gastly\rdquo{} (i.e., end-of-list). |
ocsenave@412 1085 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@412 1086 | 05DD2-05DF2 | Menu text for player info. | | PLAYER [newline] BADGES [nelwine] POK\Eacute{}DEX [newline] TIME [0x50] |
ocsenave@411 1087 | 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 1088 | 06698- | ? Background music. | | |
ocsenave@412 1089 | 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 1090 | 7570-757D | Menu options for trading Pok\eacute{}mon | | TRADE [newline] CANCEL [0x50] |
ocsenave@412 1091 | 757D-758A | Menu options for healing Pok\eacute{}mon | | HEAL [newline] CANCEL [0x50] |
ocsenave@412 1092 | 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 1093 | 7AF0-8000 | (empty space) | | 0 0 0 0 0 ... |
ocsenave@411 1094 | 0822E-082F? | Pointers to background music, part I. | | |
ocsenave@411 1095 | 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, the location of the first list of wild Pok\eacute{}mon (see 04D89, above). |
ocsenave@411 1096 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1097 | 0DADB. | Amount of HP restored by Hyper Potion. | The HP consists of a single byte. TODO: Discover what the surrounding data does, and find the data for the amount of HP restored by other items: Fresh Water (50HP), Soda (60HP), Lemonade(80HP). | 200 |
ocsenave@411 1098 | 0DAE0. | Amount of HP restored by Super Potion. | " | 50 |
ocsenave@411 1099 | 0DAE3. | Amount of HP restored by Potion. | " | 20 |
ocsenave@411 1100 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1101 | 0DD4D-DD72 | Names of permanent stats. | Variable-length strings separated by 0x50. | #HEALTH#ATTACK#DEFENSE#SPEED#SPECIAL# |
ocsenave@412 1102 | 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 1103 | 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 1104 | 11852- | Terminology for current stats in the Pok\eacute{}mon menu. | Contiguous, variable-length strings. | EXP POINTS[newline]LEVEL UP[0x50] |
ocsenave@411 1105 | 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 1106 | 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@411 1107 | 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 1108 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1109 | 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 1110 | 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 1111 | 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 1112 | 27DFF-27E77 | ? | 120 bytes of unknown data. | |
ocsenave@411 1113 | 27E77- | Trainer title names. | Variable-length names separated by 0x50. | YOUNGSTER#BUG CATCHER#LASS#... |
ocsenave@411 1114 | 34000- | | | |
ocsenave@411 1115 | 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 1116 | 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 1117 | 39462- | The Pok\eacute{}mon cry data. | Fixed-length (3 byte) descriptions of cries. | |
ocsenave@411 1118 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1119 | 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 1120 | 39B05-39DD0. | unknown | | |
ocsenave@412 1121 | 39DD1- | (?) Pointers to trainer Pok\eacute{}mon | | |
ocsenave@411 1122 | 3A289-3A540 (approx) | Trainer Pok\eacute{}mon | Consecutive level/internal-id pairs (as with wild Pok\eacute{}mon; see 04D89) with irregular spacing \mdash{} the separators seem to have some metadata purpose. | The first entry is 0x05 0x66, representing level 5 Eevee (from your first battle in the game[fn::Incidentally, 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 1123 | 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 1124 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1125 | 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 1126 | 3BBAA-3C000 | (empty) | | 0 0 0 0 ... |
ocsenave@411 1127 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@412 1128 | 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 1129 | 3D6C7-3D6D6 | Two miscellaneous strings. | Variable length, separated by 0x50 | Disabled!#TYPE |
ocsenave@411 1130 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1131 | 40252-4027B | Pok\eacute{}dex menu text | Variable-length strings separated by 0x50. | SEEN#OWN#CONTENTS#... |
ocsenave@411 1132 | 40370-40386 | Important constants for Pok\eacute{}dex entries | | HT _ _ *?′??″* [newline] WT _ _ _ *???* lb [0x50] *POK\Eacute{}* [0x50] |
ocsenave@411 1133 | 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 1134 | 41072- | Pok\eacute{} placeholder species, "???" | | |
ocsenave@411 1135 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1136 | 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@412 1137 | 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 1138 | 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 1139 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@412 1140 | 70295- | Hall of fame | The text "HALL OF FAME" | |
ocsenave@412 1141 | 70442- | Play time/money | The text "PLAY TIME [0x50] MONEY" | |
ocsenave@411 1142 | 71500-7174B | Names of places. | Variable-length place names (strings), separated by 0x50. | PALLET TOWN#VIRIDIAN CITY#PEWTER CITY#CERULEAN CITY#... |
ocsenave@411 1143 | 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 1144 | 7C249-7C2?? | Pointers to background music, pt II. | | |
ocsenave@412 1145 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@411 1146 | 98000-B8000 | Dialogue and other messsages. | Variable-length strings. | |
ocsenave@411 1147 | 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@411 1148 | BC000-BC60E | Move names. | Variable-length move names, separated by 0x50. The moves are in internal order. | POUND#KARATE CHOP#DOUBLESLAP#COMET PUNCH#... |
ocsenave@411 1149 | 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 1150 |-----------------------+-----------------+-----------------+-----------------|
ocsenave@412 1151 | E9BD5- | The text PLAY TIME (see above, 70442) | | |
ocsenave@410 1152 #+TBLFM:
ocsenave@312 1153
ocsenave@347 1154
ocsenave@347 1155
ocsenave@312 1156 ** Internal Pok\eacute{}mon IDs
ocsenave@312 1157 ** Type IDs
ocsenave@347 1158
ocsenave@347 1159 #+name: type-ids
ocsenave@347 1160 #+begin_src clojure
ocsenave@347 1161 (def pkmn-types
ocsenave@347 1162 [:normal ;;0
ocsenave@347 1163 :fighting ;;1
ocsenave@347 1164 :flying ;;2
ocsenave@347 1165 :poison ;;3
ocsenave@347 1166 :ground ;;4
ocsenave@347 1167 :rock ;;5
ocsenave@347 1168 :bird ;;6
ocsenave@347 1169 :bug ;;7
ocsenave@347 1170 :ghost ;;8
ocsenave@347 1171 :A
ocsenave@347 1172 :B
ocsenave@347 1173 :C
ocsenave@347 1174 :D
ocsenave@347 1175 :E
ocsenave@347 1176 :F
ocsenave@347 1177 :G
ocsenave@347 1178 :H
ocsenave@347 1179 :I
ocsenave@347 1180 :J
ocsenave@347 1181 :K
ocsenave@347 1182 :fire ;;20 (0x14)
ocsenave@347 1183 :water ;;21 (0x15)
ocsenave@347 1184 :grass ;;22 (0x16)
ocsenave@347 1185 :electric ;;23 (0x17)
ocsenave@347 1186 :psychic ;;24 (0x18)
ocsenave@347 1187 :ice ;;25 (0x19)
ocsenave@347 1188 :dragon ;;26 (0x1A)
ocsenave@347 1189 ])
ocsenave@347 1190 #+end_src
ocsenave@347 1191
ocsenave@312 1192 ** Basic effects of moves
ocsenave@347 1193
ocsenave@347 1194 *** Table of basic effects
ocsenave@347 1195
ocsenave@347 1196 The possible effects of moves in Pok\eacute{}mon \mdash{} for example, dealing
ocsenave@347 1197 damage, leeching health, or potentially poisoning the opponent
ocsenave@347 1198 \mdash{} are stored in a table. Each move has exactly one effect, and
ocsenave@347 1199 different moves might have the same effect.
ocsenave@347 1200
ocsenave@347 1201 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 1202
ocsenave@347 1203 All the legitimate move effects are listed in the table
ocsenave@347 1204 below. Here are some notes for reading it:
ocsenave@347 1205
ocsenave@347 1206 - Whenever an effect has a chance of doing something (like a chance of
ocsenave@371 1207 poisoning the opponent), I list the chance as a hexadecimal amount
ocsenave@371 1208 out of 256; this is to avoid rounding errors. To convert the hex amount into a percentage, divide by 256.
ocsenave@347 1209 - For some effects, the description is too cumbersome to
ocsenave@347 1210 write. Instead, I just write a move name
ocsenave@347 1211 in parentheses, like: (leech seed). That move gives a characteristic example
ocsenave@347 1212 of the effect.
ocsenave@347 1213 - I use the abbreviations =atk=, =def=, =spd=, =spc=, =acr=, =evd= for
ocsenave@371 1214 attack, defense, speed, special, accuracy, and evasiveness.
ocsenave@347 1215 .
ocsenave@347 1216
ocsenave@347 1217
ocsenave@347 1218
ocsenave@347 1219 | ID (hex) | Description | Notes |
ocsenave@347 1220 |----------+-------------------------------------------------------------------------------------------------+------------------------------------------------------------------|
ocsenave@347 1221 | 0 | normal damage | |
ocsenave@347 1222 | 1 | no damage, just sleep | TODO: find out how many turns |
ocsenave@347 1223 | 2 | 0x4C chance of poison | |
ocsenave@347 1224 | 3 | leech half of inflicted damage | |
ocsenave@347 1225 | 4 | 0x19 chance of burn | |
ocsenave@347 1226 | 5 | 0x19 chance of freeze | |
ocsenave@347 1227 | 6 | 0x19 chance of paralysis | |
ocsenave@347 1228 | 7 | user faints; opponent's defense is halved during attack. | |
ocsenave@347 1229 | 8 | leech half of inflicted damage ONLY if the opponent is asleep | |
ocsenave@347 1230 | 9 | imitate last attack | |
ocsenave@347 1231 | A | user atk +1 | |
ocsenave@347 1232 | B | user def +1 | |
ocsenave@347 1233 | C | user spd +1 | |
ocsenave@347 1234 | D | user spc +1 | |
ocsenave@347 1235 | E | user acr +1 | This effect is unused. |
ocsenave@347 1236 | F | user evd +1 | |
ocsenave@347 1237 | 10 | get post-battle money = 2 * level * uses | |
ocsenave@347 1238 | 11 | move has 0xFE acr, regardless of battle stat modifications. | |
ocsenave@347 1239 | 12 | opponent atk -1 | |
ocsenave@347 1240 | 13 | opponent def -1 | |
ocsenave@347 1241 | 14 | opponent spd -1 | |
ocsenave@347 1242 | 15 | opponent spc -1 | |
ocsenave@347 1243 | 16 | opponent acr -1 | |
ocsenave@347 1244 | 17 | opponent evd -1 | |
ocsenave@347 1245 | 18 | converts user's type to opponent's. | |
ocsenave@347 1246 | 19 | (haze) | |
ocsenave@347 1247 | 1A | (bide) | |
ocsenave@347 1248 | 1B | (thrash) | |
ocsenave@347 1249 | 1C | (teleport) | |
ocsenave@347 1250 | 1D | (fury swipes) | |
ocsenave@347 1251 | 1E | attacks 2-5 turns | Unused. TODO: find out what it does. |
ocsenave@347 1252 | 1F | 0x19 chance of flinching | |
ocsenave@347 1253 | 20 | opponent sleep for 1-7 turns | |
ocsenave@347 1254 | 21 | 0x66 chance of poison | |
ocsenave@347 1255 | 22 | 0x4D chance of burn | |
ocsenave@347 1256 | 23 | 0x4D chance of freeze | |
ocsenave@347 1257 | 24 | 0x4D chance of paralysis | |
ocsenave@347 1258 | 25 | 0x4D chance of flinching | |
ocsenave@347 1259 | 26 | one-hit KO | |
ocsenave@347 1260 | 27 | charge one turn, atk next. | |
ocsenave@347 1261 | 28 | fixed damage, leaves 1HP. | Is the fixed damage the power of the move? |
ocsenave@347 1262 | 29 | fixed damage. | Like seismic toss, dragon rage, psywave. |
ocsenave@347 1263 | 2A | atk 2-5 turns; opponent can't attack | The odds of attacking for /n/ turns are: (0 0x60 0x60 0x20 0x20) |
ocsenave@347 1264 | 2B | charge one turn, atk next. (can't be hit when charging) | |
ocsenave@347 1265 | 2C | atk hits twice. | |
ocsenave@347 1266 | 2D | user takes 1 damage if misses. | |
ocsenave@347 1267 | 2E | evade status-lowering effects | Caused by you or also your opponent? |
ocsenave@347 1268 | 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 1269 | 30 | atk causes recoil dmg = 1/4 dmg dealt | |
ocsenave@347 1270 | 31 | confuses opponent | |
ocsenave@347 1271 | 32 | user atk +2 | |
ocsenave@347 1272 | 33 | user def +2 | |
ocsenave@347 1273 | 34 | user spd +2 | |
ocsenave@347 1274 | 35 | user spc +2 | |
ocsenave@347 1275 | 36 | user acr +2 | This effect is unused. |
ocsenave@347 1276 | 37 | user evd +2 | This effect is unused. |
ocsenave@347 1277 | 38 | restores up to half of user's max hp. | |
ocsenave@347 1278 | 39 | (transform) | |
ocsenave@347 1279 | 3A | opponent atk -2 | |
ocsenave@347 1280 | 3B | opponent def -2 | |
ocsenave@347 1281 | 3C | opponent spd -2 | |
ocsenave@347 1282 | 3D | opponent spc -2 | |
ocsenave@347 1283 | 3E | opponent acr -2 | |
ocsenave@347 1284 | 3F | opponent evd -2 | |
ocsenave@347 1285 | 40 | doubles user spc when attacked | |
ocsenave@347 1286 | 41 | doubles user def when attacked | |
ocsenave@347 1287 | 42 | just poisons opponent | |
ocsenave@347 1288 | 43 | just paralyzes opponent | |
ocsenave@347 1289 | 44 | 0x19 chance opponent atk -1 | |
ocsenave@347 1290 | 45 | 0x19 chance opponent def -1 | |
ocsenave@347 1291 | 46 | 0x19 chance opponent spd -1 | |
ocsenave@347 1292 | 47 | 0x4C chance opponent spc -1 | |
ocsenave@347 1293 | 48 | 0x19 chance opponent acr -1 | |
ocsenave@347 1294 | 49 | 0x19 chance opponent evd -1 | |
ocsenave@347 1295 | 4A | ??? | ;; unused? no effect? |
ocsenave@347 1296 | 4B | ??? | ;; unused? no effect? |
ocsenave@347 1297 | 4C | 0x19 chance of confusing the opponent | |
ocsenave@347 1298 | 4D | atk hits twice. 0x33 chance opponent poisioned. | |
ocsenave@347 1299 | 4E | broken. crash the game after attack. | |
ocsenave@347 1300 | 4F | (substitute) | |
ocsenave@347 1301 | 50 | unless opponent faints, user must recharge after atk. some exceptions apply | |
ocsenave@347 1302 | 51 | (rage) | |
ocsenave@347 1303 | 52 | (mimic) | |
ocsenave@347 1304 | 53 | (metronome) | |
ocsenave@347 1305 | 54 | (leech seed) | |
ocsenave@347 1306 | 55 | does nothing (splash) | |
ocsenave@347 1307 | 56 | (disable) | |
ocsenave@347 1308 #+end_src
ocsenave@347 1309
ocsenave@347 1310 *** Source
ocsenave@347 1311 #+name: move-effects
ocsenave@347 1312 #+begin_src clojure
ocsenave@347 1313 (def move-effects
ocsenave@347 1314 ["normal damage"
ocsenave@347 1315 "no damage, just opponent sleep" ;; how many turns? is atk power ignored?
ocsenave@347 1316 "0x4C chance of poison"
ocsenave@347 1317 "leech half of inflicted damage"
ocsenave@347 1318 "0x19 chance of burn"
ocsenave@347 1319 "0x19 chance of freeze"
ocsenave@347 1320 "0x19 chance of paralyze"
ocsenave@347 1321 "user faints; opponent defense halved during attack."
ocsenave@347 1322 "leech half of inflicted damage ONLY if sleeping opponent."
ocsenave@347 1323 "imitate last attack"
ocsenave@347 1324 "user atk +1"
ocsenave@347 1325 "user def +1"
ocsenave@347 1326 "user spd +1"
ocsenave@347 1327 "user spc +1"
ocsenave@347 1328 "user acr +1" ;; unused?!
ocsenave@347 1329 "user evd +1"
ocsenave@347 1330 "get post-battle $ = 2*level*uses"
ocsenave@347 1331 "0xFE acr, no matter what."
ocsenave@347 1332 "opponent atk -1" ;; acr taken from move acr?
ocsenave@347 1333 "opponent def -1" ;;
ocsenave@347 1334 "opponent spd -1" ;;
ocsenave@347 1335 "opponent spc -1" ;;
ocsenave@347 1336 "opponent acr -1";;
ocsenave@347 1337 "opponent evd -1"
ocsenave@347 1338 "converts user's type to opponent's."
ocsenave@347 1339 "(haze)"
ocsenave@347 1340 "(bide)"
ocsenave@347 1341 "(thrash)"
ocsenave@347 1342 "(teleport)"
ocsenave@347 1343 "(fury swipes)"
ocsenave@347 1344 "attacks 2-5 turns" ;; unused? like rollout?
ocsenave@347 1345 "0x19 chance of flinch"
ocsenave@347 1346 "opponent sleep for 1-7 turns"
ocsenave@347 1347 "0x66 chance of poison"
ocsenave@347 1348 "0x4D chance of burn"
ocsenave@347 1349 "0x4D chance of freeze"
ocsenave@347 1350 "0x4D chance of paralyze"
ocsenave@347 1351 "0x4D chance of flinch"
ocsenave@347 1352 "one-hit KO"
ocsenave@347 1353 "charge one turn, atk next."
ocsenave@347 1354 "fixed damage, leaves 1HP." ;; how is dmg determined?
ocsenave@347 1355 "fixed damage." ;; cf seismic toss, dragon rage, psywave.
ocsenave@347 1356 "atk 2-5 turns; opponent can't attack" ;; unnormalized? (0 0x60 0x60 0x20 0x20)
ocsenave@347 1357 "charge one turn, atk next. (can't be hit when charging)"
ocsenave@347 1358 "atk hits twice."
ocsenave@347 1359 "user takes 1 damage if misses."
ocsenave@347 1360 "evade status-lowering effects" ;;caused by you or also your opponent?
ocsenave@347 1361 "(broken) if user is slower than opponent, makes critical hit impossible, otherwise has no effect"
ocsenave@347 1362 "atk causes recoil dmg = 1/4 dmg dealt"
ocsenave@347 1363 "confuses opponent" ;; acr taken from move acr
ocsenave@347 1364 "user atk +2"
ocsenave@347 1365 "user def +2"
ocsenave@347 1366 "user spd +2"
ocsenave@347 1367 "user spc +2"
ocsenave@347 1368 "user acr +2" ;; unused!
ocsenave@347 1369 "user evd +2" ;; unused!
ocsenave@347 1370 "restores up to half of user's max hp." ;; broken: fails if the difference
ocsenave@347 1371 ;; b/w max and current hp is one less than a multiple of 256.
ocsenave@347 1372 "(transform)"
ocsenave@347 1373 "opponent atk -2"
ocsenave@347 1374 "opponent def -2"
ocsenave@347 1375 "opponent spd -2"
ocsenave@347 1376 "opponent spc -2"
ocsenave@347 1377 "opponent acr -2"
ocsenave@347 1378 "opponent evd -2"
ocsenave@347 1379 "doubles user spc when attacked"
ocsenave@347 1380 "doubles user def when attacked"
ocsenave@347 1381 "just poisons opponent" ;;acr taken from move acr
ocsenave@347 1382 "just paralyzes opponent" ;;
ocsenave@347 1383 "0x19 chance opponent atk -1"
ocsenave@347 1384 "0x19 chance opponent def -1"
ocsenave@347 1385 "0x19 chance opponent spd -1"
ocsenave@347 1386 "0x4C chance opponent spc -1" ;; context suggest chance is 0x19
ocsenave@347 1387 "0x19 chance opponent acr -1"
ocsenave@347 1388 "0x19 chance opponent evd -1"
ocsenave@347 1389 "???" ;; unused? no effect?
ocsenave@347 1390 "???" ;; unused? no effect?
ocsenave@347 1391 "0x19 chance opponent confused"
ocsenave@347 1392 "atk hits twice. 0x33 chance opponent poisioned."
ocsenave@347 1393 "broken. crash the game after attack."
ocsenave@347 1394 "(substitute)"
ocsenave@347 1395 "unless opponent faints, user must recharge after atk. some
ocsenave@347 1396 exceptions apply."
ocsenave@347 1397 "(rage)"
ocsenave@347 1398 "(mimic)"
ocsenave@347 1399 "(metronome)"
ocsenave@347 1400 "(leech seed)"
ocsenave@347 1401 "does nothing (splash)"
ocsenave@347 1402 "(disable)"
ocsenave@347 1403 ])
ocsenave@347 1404 #+end_src
ocsenave@347 1405
ocsenave@347 1406
ocsenave@312 1407 ** Alphabet code
ocsenave@347 1408
ocsenave@348 1409 * Source
ocsenave@348 1410
ocsenave@347 1411 #+begin_src clojure :tangle ../clojure/com/aurellem/gb/hxc.clj
ocsenave@347 1412
ocsenave@347 1413 (ns com.aurellem.gb.hxc
ocsenave@347 1414 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@347 1415 constants species))
ocsenave@347 1416 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@347 1417
ocsenave@347 1418 ; ************* HANDWRITTEN CONSTANTS
ocsenave@347 1419
ocsenave@347 1420 <<type-ids>>
ocsenave@347 1421
ocsenave@347 1422
ocsenave@347 1423 ;; question: when status effects claim to take
ocsenave@347 1424 ;; their accuracy from the move accuracy, does
ocsenave@347 1425 ;; this mean that the move always "hits" but the
ocsenave@347 1426 ;; status effect may not?
ocsenave@347 1427
ocsenave@347 1428 <<move-effects>>
ocsenave@347 1429
ocsenave@347 1430 ;; ************** HARDCODED DATA
ocsenave@347 1431
ocsenave@347 1432 <<hxc-thunks>>
ocsenave@347 1433 ;; --------------------------------------------------
ocsenave@347 1434
ocsenave@347 1435 <<pokenames>>
ocsenave@348 1436 <<type-names>>
ocsenave@347 1437
ocsenave@347 1438 ;; http://hax.iimarck.us/topic/581/
ocsenave@348 1439 <<pokecry>>
ocsenave@347 1440
ocsenave@347 1441
ocsenave@348 1442 <<item-names>>
ocsenave@347 1443
ocsenave@347 1444
ocsenave@347 1445
ocsenave@347 1446 (def hxc-titles
ocsenave@347 1447 "The hardcoded names of the trainer titles in memory. List begins at
ocsenave@347 1448 ROM@27E77"
ocsenave@347 1449 (hxc-thunk-words 0x27E77 196))
ocsenave@347 1450
ocsenave@347 1451
ocsenave@348 1452 <<dex-text>>
ocsenave@347 1453
ocsenave@347 1454 ;; In red/blue, pokedex stats are in internal order.
ocsenave@347 1455 ;; In yellow, pokedex stats are in pokedex order.
ocsenave@348 1456 <<dex-stats>>
ocsenave@347 1457
ocsenave@347 1458
ocsenave@347 1459
ocsenave@347 1460
ocsenave@348 1461 <<places>>
ocsenave@347 1462
ocsenave@347 1463 (defn hxc-dialog
ocsenave@347 1464 "The hardcoded dialogue in memory, including in-game alerts. Dialog
ocsenave@347 1465 seems to be separated by 0x57 instead of 0x50 (END). Begins at ROM@98000."
ocsenave@347 1466 ([rom]
ocsenave@347 1467 (map character-codes->str
ocsenave@347 1468 (take-nth 2
ocsenave@347 1469 (partition-by #(= % 0x57)
ocsenave@347 1470 (take 0x0F728
ocsenave@347 1471 (drop 0x98000 rom))))))
ocsenave@347 1472 ([]
ocsenave@347 1473 (hxc-dialog com.aurellem.gb.gb-driver/original-rom)))
ocsenave@347 1474
ocsenave@347 1475
ocsenave@348 1476 <<move-names>>
ocsenave@348 1477 <<move-data>>
ocsenave@347 1478
ocsenave@348 1479 <<machines>>
ocsenave@347 1480
ocsenave@347 1481
ocsenave@347 1482
ocsenave@347 1483 (defn internal-id
ocsenave@347 1484 ([rom]
ocsenave@347 1485 (zipmap
ocsenave@347 1486 (hxc-pokenames rom)
ocsenave@347 1487 (range)))
ocsenave@347 1488 ([]
ocsenave@347 1489 (internal-id com.aurellem.gb.gb-driver/original-rom)))
ocsenave@347 1490
ocsenave@347 1491
ocsenave@347 1492
ocsenave@347 1493
ocsenave@347 1494
ocsenave@347 1495 ;; nidoran gender change upon levelup
ocsenave@347 1496 ;; (->
ocsenave@347 1497 ;; @current-state
ocsenave@347 1498 ;; rom
ocsenave@347 1499 ;; vec
ocsenave@347 1500 ;; (rewrite-memory
ocsenave@347 1501 ;; (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♂))
ocsenave@347 1502 ;; [1 1 15])
ocsenave@347 1503 ;; (rewrite-memory
ocsenave@347 1504 ;; (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♀))
ocsenave@347 1505 ;; [1 1 3])
ocsenave@347 1506 ;; (write-rom!)
ocsenave@347 1507
ocsenave@347 1508 ;; )
ocsenave@347 1509
ocsenave@347 1510
ocsenave@347 1511
ocsenave@348 1512 <<type-advantage>>
ocsenave@347 1513
ocsenave@347 1514
ocsenave@347 1515
ocsenave@348 1516 <<evolution-header>>
ocsenave@349 1517 <<evolution>>
ocsenave@348 1518 <<learnsets>>
ocsenave@348 1519 <<pokebase>>
ocsenave@347 1520
ocsenave@347 1521
ocsenave@347 1522 (defn hxc-intro-pkmn
ocsenave@347 1523 "The hardcoded pokemon to display in Prof. Oak's introduction; the pokemon's
ocsenave@347 1524 internal id is stored at ROM@5EDB."
ocsenave@347 1525 ([] (hxc-intro-pkmn
ocsenave@347 1526 com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 1527 ([rom]
ocsenave@347 1528 (nth (hxc-pokenames rom) (nth rom 0x5EDB))))
ocsenave@347 1529
ocsenave@347 1530 (defn sxc-intro-pkmn!
ocsenave@347 1531 "Set the hardcoded pokemon to display in Prof. Oak's introduction."
ocsenave@347 1532 [pokemon]
ocsenave@347 1533 (write-rom!
ocsenave@347 1534 (rewrite-rom 0x5EDB
ocsenave@347 1535 [
ocsenave@347 1536 (inc
ocsenave@347 1537 ((zipmap
ocsenave@347 1538 (hxc-pokenames)
ocsenave@347 1539 (range))
ocsenave@347 1540 pokemon))])))
ocsenave@347 1541
ocsenave@347 1542
ocsenave@348 1543 <<item-prices>>
ocsenave@347 1544
ocsenave@348 1545 <<item-vendors>>
ocsenave@347 1546
ocsenave@348 1547 <<wilds>>
ocsenave@347 1548
ocsenave@347 1549
ocsenave@347 1550 ;; ********************** MANIPULATION FNS
ocsenave@347 1551
ocsenave@347 1552
ocsenave@347 1553 (defn same-type
ocsenave@347 1554 ([pkmn move]
ocsenave@347 1555 (same-type
ocsenave@347 1556 com.aurellem.gb.gb-driver/original-rom pkmn move))
ocsenave@347 1557 ([rom pkmn move]
ocsenave@347 1558 (((comp :types (hxc-pokemon-base rom)) pkmn)
ocsenave@347 1559 ((comp :type (hxc-move-data rom)) move))))
ocsenave@347 1560
ocsenave@347 1561
ocsenave@347 1562
ocsenave@347 1563
ocsenave@347 1564 (defn submap?
ocsenave@347 1565 "Compares the two maps. Returns true if map-big has the same associations as map-small, otherwise false."
ocsenave@347 1566 [map-small map-big]
ocsenave@347 1567 (cond (empty? map-small) true
ocsenave@347 1568 (and
ocsenave@347 1569 (contains? map-big (ffirst map-small))
ocsenave@347 1570 (= (get map-big (ffirst map-small))
ocsenave@347 1571 (second (first map-small))))
ocsenave@347 1572 (recur (next map-small) map-big)
ocsenave@347 1573
ocsenave@347 1574 :else false))
ocsenave@347 1575
ocsenave@347 1576
ocsenave@347 1577 (defn search-map [proto-map maps]
ocsenave@347 1578 "Returns all the maps that make the same associations as proto-map."
ocsenave@347 1579 (some (partial submap? proto-map) maps))
ocsenave@347 1580
ocsenave@347 1581 (defn filter-vals
ocsenave@347 1582 "Returns a map consisting of all the pairs [key val] for
ocsenave@347 1583 which (pred key) returns true."
ocsenave@347 1584 [pred map]
ocsenave@347 1585 (reduce (partial apply assoc) {}
ocsenave@347 1586 (filter (fn [[k v]] (pred v)) map)))
ocsenave@347 1587
ocsenave@347 1588
ocsenave@347 1589 (defn search-moves
ocsenave@347 1590 "Returns a subcollection of all hardcoded moves with the
ocsenave@347 1591 given attributes. Attributes consist of :name :power
ocsenave@347 1592 :accuracy :pp :fx-id
ocsenave@347 1593 (and also :fx-txt, but it contains the same information
ocsenave@347 1594 as :fx-id)"
ocsenave@347 1595 ([attribute-map]
ocsenave@347 1596 (search-moves
ocsenave@347 1597 com.aurellem.gb.gb-driver/original-rom attribute-map))
ocsenave@347 1598 ([rom attribute-map]
ocsenave@347 1599 (filter-vals (partial submap? attribute-map)
ocsenave@347 1600 (hxc-move-data rom))))
ocsenave@347 1601
ocsenave@347 1602
ocsenave@347 1603
ocsenave@347 1604
ocsenave@347 1605
ocsenave@347 1606 ;; note: 0x2f31 contains the names "TM" "HM"?
ocsenave@347 1607
ocsenave@347 1608 ;; note for later: credits start at F1290
ocsenave@347 1609
ocsenave@347 1610 ;; note: DADB hyper-potion-hp _ _ _ super-potion-hp _ _ _ potion-hp ??
ocsenave@347 1611
ocsenave@347 1612 ;; note: DD4D spells out pokemon vital stat names ("speed", etc.)
ocsenave@347 1613
ocsenave@347 1614 ;; note: 1195C-6A says ABLE#NOT ABLE#, but so does 119C0-119CE.
ocsenave@347 1615 ;; The first instance is for Machines; the second, for stones.
ocsenave@347 1616
ocsenave@410 1617 ;; note: according to
ocsenave@410 1618 ;; http://www.upokecenter.com/games/rby/guides/rgbtrainers.php
ocsenave@410 1619 ;; the amount of money given by a trainer is equal to the
ocsenave@410 1620 ;; base money times the level of the last Pokemon on that trainer's
ocsenave@410 1621 ;; list. Other sources say it's the the level of the last pokemon
ocsenave@410 1622 ;; /defeated/.
ocsenave@410 1623
ocsenave@410 1624 ;; todo: find base money.
ocsenave@410 1625
ocsenave@410 1626
ocsenave@411 1627 ;; note: 0xDFEA (in indexable mem) is the dex# of the currently-viewed Pokemon in
ocsenave@411 1628 ;; in the pokedex. It's used for other purposes if there is none.
ocsenave@411 1629
ocsenave@412 1630 ;; note: 0x9D35 (index.) switches from 0xFF to 0x00 temporarily when
ocsenave@412 1631 ;; you walk between areas.
ocsenave@412 1632
ocsenave@412 1633 ;; note: 0xD059 (index.) is the special battle type of your next battle:
ocsenave@412 1634 ;; - 00 is a usual battle
ocsenave@412 1635 ;; - 01 is a pre-scripted OLD MAN battle which always fails to catch the
ocsenave@412 1636 ;; target Pokemon.
ocsenave@412 1637 ;; - 02 is a safari zone battle
ocsenave@412 1638 ;; - 03 obligates you to run away. (unused)
ocsenave@412 1639 ;; - 04 is a pre-scripted OAK battle, which (temporarily) causes the
ocsenave@412 1640 ;; enemy Pokemon to cry PIKAAA, and which always catches the target
ocsenave@412 1641 ;; Pokemon. The target Pokemon is erased after the battle.
ocsenave@412 1642 ;; - 05+ are glitch states in which you are sort of the Pokemon.
ocsenave@412 1643
ocsenave@412 1644
ocsenave@412 1645 ;; note: 0x251A (in indexable mem): image decompression routine seems to begin here.
ocsenave@347 1646
ocsenave@347 1647
ocsenave@373 1648 ;; Note: There are two tile tables, one from 8000-8FFF, the other from
ocsenave@373 1649 ;; 8800-97FF. The latter contains symbols, possibly map tiles(?), with some japanese chars and stuff at the end.
ocsenave@373 1650 (defn print-pixel-letters!
ocsenave@373 1651 "The pixel tiles representing letters. Neat!"
ocsenave@373 1652 ([] (print-pixel-letters! (read-state "oak-speaks")))
ocsenave@373 1653 ([state]
ocsenave@373 1654 (map
ocsenave@373 1655 (comp
ocsenave@373 1656 println
ocsenave@373 1657 (partial map #(if (zero? %) \space 0))
ocsenave@373 1658 #(if (< (count %) 8)
ocsenave@373 1659 (recur (cons 0 %))
ocsenave@373 1660 %)
ocsenave@373 1661 reverse bit-list)
ocsenave@373 1662
ocsenave@373 1663 (take 0xFFF (drop 0x8800 (memory state))))))
ocsenave@373 1664
ocsenave@373 1665
ocsenave@406 1666 (defn test-2 []
ocsenave@406 1667 (loop [n 0
ocsenave@406 1668 pc-1 (pc-trail (-> state-defend (tick) (step [:a]) (step [:a]) (step []) (nstep 100)) 100000)
ocsenave@406 1669 pc-2 (pc-trail (-> state-speed (tick) (step [:a]) (step [:a])
ocsenave@406 1670 (step []) (nstep 100)) 100000)]
ocsenave@406 1671 (cond (empty? (drop n pc-1)) [pc-1 n]
ocsenave@406 1672 (not= (take 10 (drop n pc-1)) (take 10 pc-2))
ocsenave@406 1673 (recur pc-1 pc-2 (inc n))
ocsenave@406 1674 :else
ocsenave@406 1675 [(take 1000 pc-2) n])))
ocsenave@406 1676
ocsenave@406 1677
ocsenave@406 1678
ocsenave@406 1679
ocsenave@410 1680 (defn test-3
ocsenave@410 1681 "Explore trainer data"
ocsenave@410 1682 []
ocsenave@410 1683 (let [pokenames (vec(hxc-pokenames-raw))]
ocsenave@410 1684 (println
ocsenave@410 1685 (reduce
ocsenave@410 1686 str
ocsenave@410 1687 (map
ocsenave@410 1688 (fn [[lvl pkmn]]
ocsenave@410 1689 (str (format "%-11s %4d %02X %02X"
ocsenave@410 1690 (cond
ocsenave@410 1691 (zero? lvl) "+"
ocsenave@410 1692 (nil? (get pokenames (dec pkmn)))
ocsenave@410 1693 "-"
ocsenave@410 1694 :else
ocsenave@410 1695 (get pokenames (dec pkmn)))
ocsenave@410 1696 lvl
ocsenave@410 1697 pkmn
ocsenave@410 1698 lvl
ocsenave@410 1699 ) "\n"))
ocsenave@410 1700
ocsenave@410 1701 (partition 2
ocsenave@410 1702 (take 100;;703
ocsenave@412 1703 (drop
ocsenave@412 1704 0x3A281
ocsenave@412 1705 ;; 0x3A75D
ocsenave@412 1706 (rom)))))))))
ocsenave@410 1707
ocsenave@412 1708 (defn search-memory* [mem codes k]
ocsenave@412 1709 (loop [index 0
ocsenave@412 1710 index-next 1
ocsenave@412 1711 start-match 0
ocsenave@412 1712 to-match codes
ocsenave@412 1713 matches []]
ocsenave@412 1714 (cond
ocsenave@412 1715 (>= index (count mem)) matches
ocsenave@412 1716
ocsenave@412 1717 (empty? to-match)
ocsenave@412 1718 (recur
ocsenave@412 1719 index-next
ocsenave@412 1720 (inc index-next)
ocsenave@412 1721 index-next
ocsenave@412 1722 codes
ocsenave@412 1723 (conj matches
ocsenave@412 1724 [(hex start-match) (take k (drop start-match mem))])
ocsenave@412 1725 )
ocsenave@412 1726
ocsenave@412 1727 (or (= (first to-match) \_) ;; wildcard
ocsenave@412 1728 (= (first to-match) (nth mem index)))
ocsenave@412 1729 (recur
ocsenave@412 1730 (inc index)
ocsenave@412 1731 index-next
ocsenave@412 1732 start-match
ocsenave@412 1733 (rest to-match)
ocsenave@412 1734 matches)
ocsenave@412 1735
ocsenave@412 1736 :else
ocsenave@412 1737 (recur
ocsenave@412 1738 index-next
ocsenave@412 1739 (inc index-next)
ocsenave@412 1740 index-next
ocsenave@412 1741 codes
ocsenave@412 1742 matches))))
ocsenave@412 1743
ocsenave@412 1744
ocsenave@412 1745
ocsenave@406 1746
ocsenave@406 1747
ocsenave@410 1748 ;; look for the rainbow badge in memory
ocsenave@410 1749 (println (reduce str (map #(str (first %) "\t" (vec(second %)) "\n") (search-memory (rom) [221] 10))))
ocsenave@410 1750
ocsenave@406 1751
ocsenave@347 1752 (comment
ocsenave@347 1753
ocsenave@347 1754 (def hxc-later
ocsenave@347 1755 "Running this code produces, e.g. hardcoded names NPCs give
ocsenave@347 1756 their pokemon. Will sort through it later."
ocsenave@347 1757 (print (character-codes->str(take 10000
ocsenave@347 1758 (drop 0x71597
ocsenave@347 1759 (rom (root)))))))
ocsenave@347 1760
ocsenave@347 1761 (let [dex
ocsenave@347 1762 (partition-by #(= 0x50 %)
ocsenave@347 1763 (take 2540
ocsenave@347 1764 (drop 0x40687
ocsenave@347 1765 (rom (root)))))]
ocsenave@347 1766 (def dex dex)
ocsenave@347 1767 (def hxc-species
ocsenave@347 1768 (map character-codes->str
ocsenave@347 1769 (take-nth 4 dex))))
ocsenave@347 1770 )
ocsenave@347 1771
ocsenave@347 1772
ocsenave@347 1773 #+end_src
ocsenave@347 1774
ocsenave@348 1775 #+results:
ocsenave@348 1776 : nil
ocsenave@348 1777