annotate org/rom.org @ 437:20a9d5faf47c

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