annotate org/rom.org @ 347:ff65ee0944fe

more progess: now rom.org tangles into hxc.clj; i'll be subdividing the code blocks as I write more.
author Dylan Holmes <ocsenave@gmail.com>
date Sun, 08 Apr 2012 06:13:39 -0500
parents 5639312a393f
children 497ca041f5af
rev   line source
ocsenave@311 1 #+title: Notes on Deconstructing Pokemon Yellow
ocsenave@311 2 #+author: Dylan Holmes
ocsenave@311 3 #+email: rlm@mit.edu
ocsenave@311 4 #+description:
ocsenave@312 5 #+keywords:
ocsenave@311 6 #+SETUPFILE: ../../aurellem/org/setup.org
ocsenave@311 7 #+INCLUDE: ../../aurellem/org/level-0.org
ocsenave@311 8 #+BABEL: :exports both :noweb yes :cache no :mkdirp yes
ocsenave@311 9
ocsenave@346 10 # about map headers http://datacrystal.romhacking.net/wiki/Pokemon_Red/Blue:Notes
ocsenave@346 11 # map headers Yellow http://www.pokecommunity.com/archive/index.php/t-235311.html
ocsenave@312 12 # pokedollar: U+20B1
ocsenave@347 13 * Introduction
ocsenave@347 14
ocsenave@347 15 ** Mapping the ROM
ocsenave@311 16
ocsenave@311 17 | ROM address (hex) | Description | Format | Example |
ocsenave@311 18 |-------------------+-----------------+-----------------+-----------------|
ocsenave@311 19 | | <15> | <15> | <15> |
ocsenave@312 20 | 0233C- | Shop inventories. | | |
ocsenave@312 21 | 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@311 22 | 045B7-0491E | Names of the items in memory. | Variable-length item names (strings of character codes). Names are separated by a single 0x80 character. | MASTER BALL#ULTRA BALL#... |
ocsenave@346 23 | 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@311 24 | 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@312 25 | 06698- | ? Background music. | | |
ocsenave@312 26 | 0822E-082F? | Pointers to background music, part I. | | |
ocsenave@347 27 | 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@347 28 |-------------------+-----------------+-----------------+-----------------|
ocsenave@347 29 | 0DADB. | Amount of HP restored by Hyper Potion. | The HP consists of a single byte. TODO: Discover what the surrounding data does, and find the data for the amount of HP restored by other items: Fresh Water (50HP), Soda (60HP), Lemonade(80HP). | 200 |
ocsenave@347 30 | 0DAE0. | Amount of HP restored by Super Potion. | " | 50 |
ocsenave@347 31 | 0DAE3. | Amount of HP restored by Potion. | " | 20 |
ocsenave@347 32 |-------------------+-----------------+-----------------+-----------------|
ocsenave@346 33 | 0DD4D-DD72 | Names of permanent stats. | Variable-length strings separated by 0x50. | #HEALTH#ATTACK#DEFENSE#SPEED#SPECIAL# |
ocsenave@346 34 | 1195C-1196A | The two terms for being able/unable to learn a TM/HM. | Variable-length strings separated by 0x50. | ABLE#NOT ABLE# |
ocsenave@346 35 | 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@346 36 | 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@311 37 | 27D99-27DFF | Names of the Pok\eacute{}mon types. | Variable-length type names (strings of character codes). Names are separated by a single 0x80 character. | NORMAL#FIGHTING#... |
ocsenave@347 38 | 27E77- | Trainer title names. | Variable-length names separated by 0x80. | YOUNGSTER#BUG CATCHER#LASS#... |
ocsenave@347 39 | 34000- | | | |
ocsenave@347 40 | 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@312 41 | 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@311 42 | 39462- | The Pok\eacute{}mon cry data. | Fixed-length (3 byte) descriptions of cries. | |
ocsenave@312 43 | 3B1E5- | Pointers to evolution/learnset data. | | |
ocsenave@347 44 | 3B361- | 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@311 45 | 40687- | Species data from the Pok\eacute{}dex: species name, height, weight, etc. | Fixed-length sequences of bytes. See below for specifics. | |
ocsenave@312 46 | 410B1- | A conversion table between internal order and Pokedex order. | | |
ocsenave@346 47 | 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@312 48 | 71500- | Names of places. | | |
ocsenave@312 49 | 7C249-7C2?? | Pointers to background music, pt II. | | |
ocsenave@312 50 | 98000- | Dialogue | | |
ocsenave@312 51 | B8000- | The text of each Pokemon's Pok\eacute{}dex entry. | | |
ocsenave@347 52 | BC000-BC60E | Move names. | Variable-length move names, separated by 0x80. The moves are in internal order. | POUND#KARATE CHOP#DOUBLESLAP#COMET PUNCH#... |
ocsenave@311 53 | 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 0x80. The names are in \ldquo{}internal order\rdquo{}. | RHYDON####KANGASKHANNIDORAN♂#... |
ocsenave@311 54 | | | | |
ocsenave@311 55 | | | | |
ocsenave@312 56
ocsenave@347 57
ocsenave@347 58
ocsenave@347 59
ocsenave@347 60 ** COMMENT Getting linguistic data: names, words, etc.
ocsenave@347 61
ocsenave@347 62 Some of the simplest data
ocsenave@347 63
ocsenave@347 64
ocsenave@347 65 One of the simplest data structures in the Pok\eacute{} ROM is an
ocsenave@347 66 unbroken list of strings that either (a) all have a specific length,
ocsenave@347 67 or (b) are all separated by the same character.
ocsenave@347 68
ocsenave@347 69 Because lots of good data has this format, we'll start by writing a
ocsenave@347 70 template function to extract it:
ocsenave@347 71
ocsenave@347 72 #+name: hxc-thunks
ocsenave@347 73 #+begin_src clojure :results silent
ocsenave@347 74 (defn hxc-thunk
ocsenave@347 75 "Creates a thunk (nullary fn) that grabs data in a certain region of rom and
ocsenave@347 76 splits it into a collection by 0x50. If rom is not supplied, uses the
ocsenave@347 77 original rom data."
ocsenave@347 78 [start length]
ocsenave@347 79 (fn self
ocsenave@347 80 ([rom]
ocsenave@347 81 (take-nth 2
ocsenave@347 82 (partition-by #(= % 0x50)
ocsenave@347 83 (take length
ocsenave@347 84 (drop start rom)))))
ocsenave@347 85 ([]
ocsenave@347 86 (self com.aurellem.gb.gb-driver/original-rom))))
ocsenave@347 87
ocsenave@347 88 (def hxc-thunk-words
ocsenave@347 89 "Same as hxc-thunk, except it interprets the rom data as characters,
ocsenave@347 90 returning a collection of strings."
ocsenave@347 91 (comp
ocsenave@347 92 (partial comp (partial map character-codes->str))
ocsenave@347 93 hxc-thunk))
ocsenave@347 94
ocsenave@347 95 #+end_src
ocsenave@347 96
ocsenave@347 97 * Pok\eacute{}mon
ocsenave@347 98 ** Names of each species
ocsenave@347 99 The names of the Pok\eacute{}mon species are stored in
ocsenave@347 100 ROM@E8000. This name list is interesting, for a number of reasons:
ocsenave@347 101 - The names are stored in [[ ][internal order]] rather than in the familiar
ocsenave@347 102 Pok\eacute{}dex order. This seemingly random order probably represents the order in which the authors created or
ocsenave@347 103 programmed in the Pok\eacute{}mon; it's used throughout the game.
ocsenave@347 104 - There is enough space allocated for 190 Pok\eacute{}mon. As I
ocsenave@347 105 understand it, there were originally going to be 190 Pok\eacute{}mon
ocsenave@347 106 in Generation I, but the creators decided to defer some to
ocsenave@347 107 Generation II. This explains why many Gen I and Gen II Pok\eacute{}mon
ocsenave@347 108 have the same aesthetic feel.
ocsenave@347 109 - The list is pockmarked with random gaps, due to the strange internal
ocsenave@347 110 ordering
ocsenave@347 111 and 39 unused spaces [fn::190 allocated spaces minus 151 true Pok\eacute{}mon]. These missing spaces are filled with the
ocsenave@347 112 placeholder name, =MISSINGNO.= (\ldquo{}Missing number\rdquo{}).
ocsenave@347 113
ocsenave@347 114 Each name is exactly ten letters long (Whenever a name is too short, the extra
ocsenave@347 115 space is padded with the character 0x50).
ocsenave@347 116
ocsenave@347 117
ocsenave@347 118
ocsenave@347 119 #+name: pokenames
ocsenave@347 120 #+begin_src clojure
ocsenave@347 121
ocsenave@347 122 (defn hxc-pokenames-raw
ocsenave@347 123 "The hardcoded names of the 190 species in memory. List begins at
ocsenave@347 124 ROM@E8000. Although names in memory are padded with 0x50 to be 10 characters
ocsenave@347 125 long, these names are stripped of padding. See also, hxc-pokedex-names"
ocsenave@347 126 ([]
ocsenave@347 127 (hxc-pokenames-raw com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 128 ([rom]
ocsenave@347 129 (let [count-species 190
ocsenave@347 130 name-length 10]
ocsenave@347 131 (map character-codes->str
ocsenave@347 132 (partition name-length
ocsenave@347 133 (map #(if (= 0x50 %) 0x00 %)
ocsenave@347 134 (take (* count-species name-length)
ocsenave@347 135 (drop 0xE8000
ocsenave@347 136 rom))))))))
ocsenave@347 137 (def hxc-pokenames
ocsenave@347 138 (comp
ocsenave@347 139 (partial map format-name)
ocsenave@347 140 hxc-pokenames-raw))
ocsenave@347 141
ocsenave@347 142
ocsenave@347 143
ocsenave@347 144
ocsenave@347 145 (defn hxc-pokedex-names
ocsenave@347 146 "The names of the pokemon in hardcoded pokedex order. List begins at
ocsenave@347 147 ROM@410B1. See also, hxc-pokenames."
ocsenave@347 148 ([] (hxc-pokedex-names
ocsenave@347 149 com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 150 ([rom]
ocsenave@347 151 (let [names (hxc-pokenames rom)]
ocsenave@347 152 (#(mapv %
ocsenave@347 153 ((comp range count keys) %))
ocsenave@347 154 (zipmap
ocsenave@347 155 (take (count names)
ocsenave@347 156 (drop 0x410b1 rom))
ocsenave@347 157
ocsenave@347 158 names)))))
ocsenave@347 159
ocsenave@347 160 #+end_src
ocsenave@347 161
ocsenave@312 162 * Appendices
ocsenave@312 163 ** Internal Pok\eacute{}mon IDs
ocsenave@312 164 ** Type IDs
ocsenave@347 165
ocsenave@347 166 #+name: type-ids
ocsenave@347 167 #+begin_src clojure
ocsenave@347 168 (def pkmn-types
ocsenave@347 169 [:normal ;;0
ocsenave@347 170 :fighting ;;1
ocsenave@347 171 :flying ;;2
ocsenave@347 172 :poison ;;3
ocsenave@347 173 :ground ;;4
ocsenave@347 174 :rock ;;5
ocsenave@347 175 :bird ;;6
ocsenave@347 176 :bug ;;7
ocsenave@347 177 :ghost ;;8
ocsenave@347 178 :A
ocsenave@347 179 :B
ocsenave@347 180 :C
ocsenave@347 181 :D
ocsenave@347 182 :E
ocsenave@347 183 :F
ocsenave@347 184 :G
ocsenave@347 185 :H
ocsenave@347 186 :I
ocsenave@347 187 :J
ocsenave@347 188 :K
ocsenave@347 189 :fire ;;20 (0x14)
ocsenave@347 190 :water ;;21 (0x15)
ocsenave@347 191 :grass ;;22 (0x16)
ocsenave@347 192 :electric ;;23 (0x17)
ocsenave@347 193 :psychic ;;24 (0x18)
ocsenave@347 194 :ice ;;25 (0x19)
ocsenave@347 195 :dragon ;;26 (0x1A)
ocsenave@347 196 ])
ocsenave@347 197 #+end_src
ocsenave@347 198
ocsenave@312 199 ** Basic effects of moves
ocsenave@347 200
ocsenave@347 201 *** Table of basic effects
ocsenave@347 202
ocsenave@347 203 The possible effects of moves in Pok\eacute{}mon \mdash{} for example, dealing
ocsenave@347 204 damage, leeching health, or potentially poisoning the opponent
ocsenave@347 205 \mdash{} are stored in a table. Each move has exactly one effect, and
ocsenave@347 206 different moves might have the same effect.
ocsenave@347 207
ocsenave@347 208 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 209
ocsenave@347 210 All the legitimate move effects are listed in the table
ocsenave@347 211 below. Here are some notes for reading it:
ocsenave@347 212
ocsenave@347 213 - Whenever an effect has a chance of doing something (like a chance of
ocsenave@347 214 poisoning the opponent), I list the chance as a hexadecimal amount out of 256 to avoid rounding errors. To convert the hex amount into a percentage, divide by 256.
ocsenave@347 215 - For some effects, the description is too cumbersome to
ocsenave@347 216 write. Instead, I just write a move name
ocsenave@347 217 in parentheses, like: (leech seed). That move gives a characteristic example
ocsenave@347 218 of the effect.
ocsenave@347 219 - I use the abbreviations =atk=, =def=, =spd=, =spc=, =acr=, =evd= for
ocsenave@347 220 attack, defense, speed, special, accuracy, and evasion.
ocsenave@347 221 .
ocsenave@347 222
ocsenave@347 223
ocsenave@347 224
ocsenave@347 225 | ID (hex) | Description | Notes |
ocsenave@347 226 |----------+-------------------------------------------------------------------------------------------------+------------------------------------------------------------------|
ocsenave@347 227 | 0 | normal damage | |
ocsenave@347 228 | 1 | no damage, just sleep | TODO: find out how many turns |
ocsenave@347 229 | 2 | 0x4C chance of poison | |
ocsenave@347 230 | 3 | leech half of inflicted damage | |
ocsenave@347 231 | 4 | 0x19 chance of burn | |
ocsenave@347 232 | 5 | 0x19 chance of freeze | |
ocsenave@347 233 | 6 | 0x19 chance of paralysis | |
ocsenave@347 234 | 7 | user faints; opponent's defense is halved during attack. | |
ocsenave@347 235 | 8 | leech half of inflicted damage ONLY if the opponent is asleep | |
ocsenave@347 236 | 9 | imitate last attack | |
ocsenave@347 237 | A | user atk +1 | |
ocsenave@347 238 | B | user def +1 | |
ocsenave@347 239 | C | user spd +1 | |
ocsenave@347 240 | D | user spc +1 | |
ocsenave@347 241 | E | user acr +1 | This effect is unused. |
ocsenave@347 242 | F | user evd +1 | |
ocsenave@347 243 | 10 | get post-battle money = 2 * level * uses | |
ocsenave@347 244 | 11 | move has 0xFE acr, regardless of battle stat modifications. | |
ocsenave@347 245 | 12 | opponent atk -1 | |
ocsenave@347 246 | 13 | opponent def -1 | |
ocsenave@347 247 | 14 | opponent spd -1 | |
ocsenave@347 248 | 15 | opponent spc -1 | |
ocsenave@347 249 | 16 | opponent acr -1 | |
ocsenave@347 250 | 17 | opponent evd -1 | |
ocsenave@347 251 | 18 | converts user's type to opponent's. | |
ocsenave@347 252 | 19 | (haze) | |
ocsenave@347 253 | 1A | (bide) | |
ocsenave@347 254 | 1B | (thrash) | |
ocsenave@347 255 | 1C | (teleport) | |
ocsenave@347 256 | 1D | (fury swipes) | |
ocsenave@347 257 | 1E | attacks 2-5 turns | Unused. TODO: find out what it does. |
ocsenave@347 258 | 1F | 0x19 chance of flinching | |
ocsenave@347 259 | 20 | opponent sleep for 1-7 turns | |
ocsenave@347 260 | 21 | 0x66 chance of poison | |
ocsenave@347 261 | 22 | 0x4D chance of burn | |
ocsenave@347 262 | 23 | 0x4D chance of freeze | |
ocsenave@347 263 | 24 | 0x4D chance of paralysis | |
ocsenave@347 264 | 25 | 0x4D chance of flinching | |
ocsenave@347 265 | 26 | one-hit KO | |
ocsenave@347 266 | 27 | charge one turn, atk next. | |
ocsenave@347 267 | 28 | fixed damage, leaves 1HP. | Is the fixed damage the power of the move? |
ocsenave@347 268 | 29 | fixed damage. | Like seismic toss, dragon rage, psywave. |
ocsenave@347 269 | 2A | atk 2-5 turns; opponent can't attack | The odds of attacking for /n/ turns are: (0 0x60 0x60 0x20 0x20) |
ocsenave@347 270 | 2B | charge one turn, atk next. (can't be hit when charging) | |
ocsenave@347 271 | 2C | atk hits twice. | |
ocsenave@347 272 | 2D | user takes 1 damage if misses. | |
ocsenave@347 273 | 2E | evade status-lowering effects | Caused by you or also your opponent? |
ocsenave@347 274 | 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 275 | 30 | atk causes recoil dmg = 1/4 dmg dealt | |
ocsenave@347 276 | 31 | confuses opponent | |
ocsenave@347 277 | 32 | user atk +2 | |
ocsenave@347 278 | 33 | user def +2 | |
ocsenave@347 279 | 34 | user spd +2 | |
ocsenave@347 280 | 35 | user spc +2 | |
ocsenave@347 281 | 36 | user acr +2 | This effect is unused. |
ocsenave@347 282 | 37 | user evd +2 | This effect is unused. |
ocsenave@347 283 | 38 | restores up to half of user's max hp. | |
ocsenave@347 284 | 39 | (transform) | |
ocsenave@347 285 | 3A | opponent atk -2 | |
ocsenave@347 286 | 3B | opponent def -2 | |
ocsenave@347 287 | 3C | opponent spd -2 | |
ocsenave@347 288 | 3D | opponent spc -2 | |
ocsenave@347 289 | 3E | opponent acr -2 | |
ocsenave@347 290 | 3F | opponent evd -2 | |
ocsenave@347 291 | 40 | doubles user spc when attacked | |
ocsenave@347 292 | 41 | doubles user def when attacked | |
ocsenave@347 293 | 42 | just poisons opponent | |
ocsenave@347 294 | 43 | just paralyzes opponent | |
ocsenave@347 295 | 44 | 0x19 chance opponent atk -1 | |
ocsenave@347 296 | 45 | 0x19 chance opponent def -1 | |
ocsenave@347 297 | 46 | 0x19 chance opponent spd -1 | |
ocsenave@347 298 | 47 | 0x4C chance opponent spc -1 | |
ocsenave@347 299 | 48 | 0x19 chance opponent acr -1 | |
ocsenave@347 300 | 49 | 0x19 chance opponent evd -1 | |
ocsenave@347 301 | 4A | ??? | ;; unused? no effect? |
ocsenave@347 302 | 4B | ??? | ;; unused? no effect? |
ocsenave@347 303 | 4C | 0x19 chance of confusing the opponent | |
ocsenave@347 304 | 4D | atk hits twice. 0x33 chance opponent poisioned. | |
ocsenave@347 305 | 4E | broken. crash the game after attack. | |
ocsenave@347 306 | 4F | (substitute) | |
ocsenave@347 307 | 50 | unless opponent faints, user must recharge after atk. some exceptions apply | |
ocsenave@347 308 | 51 | (rage) | |
ocsenave@347 309 | 52 | (mimic) | |
ocsenave@347 310 | 53 | (metronome) | |
ocsenave@347 311 | 54 | (leech seed) | |
ocsenave@347 312 | 55 | does nothing (splash) | |
ocsenave@347 313 | 56 | (disable) | |
ocsenave@347 314 #+end_src
ocsenave@347 315
ocsenave@347 316 *** Source
ocsenave@347 317 #+name: move-effects
ocsenave@347 318 #+begin_src clojure
ocsenave@347 319 (def move-effects
ocsenave@347 320 ["normal damage"
ocsenave@347 321 "no damage, just opponent sleep" ;; how many turns? is atk power ignored?
ocsenave@347 322 "0x4C chance of poison"
ocsenave@347 323 "leech half of inflicted damage"
ocsenave@347 324 "0x19 chance of burn"
ocsenave@347 325 "0x19 chance of freeze"
ocsenave@347 326 "0x19 chance of paralyze"
ocsenave@347 327 "user faints; opponent defense halved during attack."
ocsenave@347 328 "leech half of inflicted damage ONLY if sleeping opponent."
ocsenave@347 329 "imitate last attack"
ocsenave@347 330 "user atk +1"
ocsenave@347 331 "user def +1"
ocsenave@347 332 "user spd +1"
ocsenave@347 333 "user spc +1"
ocsenave@347 334 "user acr +1" ;; unused?!
ocsenave@347 335 "user evd +1"
ocsenave@347 336 "get post-battle $ = 2*level*uses"
ocsenave@347 337 "0xFE acr, no matter what."
ocsenave@347 338 "opponent atk -1" ;; acr taken from move acr?
ocsenave@347 339 "opponent def -1" ;;
ocsenave@347 340 "opponent spd -1" ;;
ocsenave@347 341 "opponent spc -1" ;;
ocsenave@347 342 "opponent acr -1";;
ocsenave@347 343 "opponent evd -1"
ocsenave@347 344 "converts user's type to opponent's."
ocsenave@347 345 "(haze)"
ocsenave@347 346 "(bide)"
ocsenave@347 347 "(thrash)"
ocsenave@347 348 "(teleport)"
ocsenave@347 349 "(fury swipes)"
ocsenave@347 350 "attacks 2-5 turns" ;; unused? like rollout?
ocsenave@347 351 "0x19 chance of flinch"
ocsenave@347 352 "opponent sleep for 1-7 turns"
ocsenave@347 353 "0x66 chance of poison"
ocsenave@347 354 "0x4D chance of burn"
ocsenave@347 355 "0x4D chance of freeze"
ocsenave@347 356 "0x4D chance of paralyze"
ocsenave@347 357 "0x4D chance of flinch"
ocsenave@347 358 "one-hit KO"
ocsenave@347 359 "charge one turn, atk next."
ocsenave@347 360 "fixed damage, leaves 1HP." ;; how is dmg determined?
ocsenave@347 361 "fixed damage." ;; cf seismic toss, dragon rage, psywave.
ocsenave@347 362 "atk 2-5 turns; opponent can't attack" ;; unnormalized? (0 0x60 0x60 0x20 0x20)
ocsenave@347 363 "charge one turn, atk next. (can't be hit when charging)"
ocsenave@347 364 "atk hits twice."
ocsenave@347 365 "user takes 1 damage if misses."
ocsenave@347 366 "evade status-lowering effects" ;;caused by you or also your opponent?
ocsenave@347 367 "(broken) if user is slower than opponent, makes critical hit impossible, otherwise has no effect"
ocsenave@347 368 "atk causes recoil dmg = 1/4 dmg dealt"
ocsenave@347 369 "confuses opponent" ;; acr taken from move acr
ocsenave@347 370 "user atk +2"
ocsenave@347 371 "user def +2"
ocsenave@347 372 "user spd +2"
ocsenave@347 373 "user spc +2"
ocsenave@347 374 "user acr +2" ;; unused!
ocsenave@347 375 "user evd +2" ;; unused!
ocsenave@347 376 "restores up to half of user's max hp." ;; broken: fails if the difference
ocsenave@347 377 ;; b/w max and current hp is one less than a multiple of 256.
ocsenave@347 378 "(transform)"
ocsenave@347 379 "opponent atk -2"
ocsenave@347 380 "opponent def -2"
ocsenave@347 381 "opponent spd -2"
ocsenave@347 382 "opponent spc -2"
ocsenave@347 383 "opponent acr -2"
ocsenave@347 384 "opponent evd -2"
ocsenave@347 385 "doubles user spc when attacked"
ocsenave@347 386 "doubles user def when attacked"
ocsenave@347 387 "just poisons opponent" ;;acr taken from move acr
ocsenave@347 388 "just paralyzes opponent" ;;
ocsenave@347 389 "0x19 chance opponent atk -1"
ocsenave@347 390 "0x19 chance opponent def -1"
ocsenave@347 391 "0x19 chance opponent spd -1"
ocsenave@347 392 "0x4C chance opponent spc -1" ;; context suggest chance is 0x19
ocsenave@347 393 "0x19 chance opponent acr -1"
ocsenave@347 394 "0x19 chance opponent evd -1"
ocsenave@347 395 "???" ;; unused? no effect?
ocsenave@347 396 "???" ;; unused? no effect?
ocsenave@347 397 "0x19 chance opponent confused"
ocsenave@347 398 "atk hits twice. 0x33 chance opponent poisioned."
ocsenave@347 399 "broken. crash the game after attack."
ocsenave@347 400 "(substitute)"
ocsenave@347 401 "unless opponent faints, user must recharge after atk. some
ocsenave@347 402 exceptions apply."
ocsenave@347 403 "(rage)"
ocsenave@347 404 "(mimic)"
ocsenave@347 405 "(metronome)"
ocsenave@347 406 "(leech seed)"
ocsenave@347 407 "does nothing (splash)"
ocsenave@347 408 "(disable)"
ocsenave@347 409 ])
ocsenave@347 410 #+end_src
ocsenave@347 411
ocsenave@347 412
ocsenave@312 413 ** Alphabet code
ocsenave@347 414
ocsenave@347 415 #+begin_src clojure :tangle ../clojure/com/aurellem/gb/hxc.clj
ocsenave@347 416
ocsenave@347 417 (ns com.aurellem.gb.hxc
ocsenave@347 418 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@347 419 constants species))
ocsenave@347 420 (:import [com.aurellem.gb.gb_driver SaveState]))
ocsenave@347 421
ocsenave@347 422
ocsenave@347 423
ocsenave@347 424
ocsenave@347 425 ; ************* HANDWRITTEN CONSTANTS
ocsenave@347 426
ocsenave@347 427 <<type-ids>>
ocsenave@347 428
ocsenave@347 429
ocsenave@347 430 ;; question: when status effects claim to take
ocsenave@347 431 ;; their accuracy from the move accuracy, does
ocsenave@347 432 ;; this mean that the move always "hits" but the
ocsenave@347 433 ;; status effect may not?
ocsenave@347 434
ocsenave@347 435 <<move-effects>>
ocsenave@347 436
ocsenave@347 437 ;; ************** HARDCODED DATA
ocsenave@347 438
ocsenave@347 439 <<hxc-thunks>>
ocsenave@347 440 ;; --------------------------------------------------
ocsenave@347 441
ocsenave@347 442
ocsenave@347 443 <<pokenames>>
ocsenave@347 444
ocsenave@347 445 ;; http://hax.iimarck.us/topic/581/
ocsenave@347 446 (defn hxc-cry
ocsenave@347 447 "The pokemon cry data in internal order. List begins at ROM@39462"
ocsenave@347 448 ([](hxc-cry com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 449 ([rom]
ocsenave@347 450 (zipmap
ocsenave@347 451 (hxc-pokenames rom)
ocsenave@347 452 (map
ocsenave@347 453 (fn [[cry-id pitch length]]
ocsenave@347 454 {:cry-id cry-id
ocsenave@347 455 :pitch pitch
ocsenave@347 456 :length length}
ocsenave@347 457 )
ocsenave@347 458 (partition 3
ocsenave@347 459 (drop 0x39462 rom))))))
ocsenave@347 460
ocsenave@347 461 (defn hxc-cry-groups
ocsenave@347 462 ([] (hxc-cry-groups com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 463 ([rom]
ocsenave@347 464 (map #(mapv first
ocsenave@347 465 (filter
ocsenave@347 466 (fn [[k v]]
ocsenave@347 467 (= % (:cry-id v)))
ocsenave@347 468 (hxc-cry)))
ocsenave@347 469 ((comp
ocsenave@347 470 range
ocsenave@347 471 count
ocsenave@347 472 set
ocsenave@347 473 (partial map :cry-id)
ocsenave@347 474 vals
ocsenave@347 475 hxc-cry)
ocsenave@347 476 rom))))
ocsenave@347 477
ocsenave@347 478
ocsenave@347 479 (defn cry-conversion!
ocsenave@347 480 "Convert Porygon's cry in ROM to be the cry of the given pokemon."
ocsenave@347 481 [pkmn]
ocsenave@347 482 (write-rom!
ocsenave@347 483 (rewrite-memory
ocsenave@347 484 (vec(rom))
ocsenave@347 485 0x3965D
ocsenave@347 486 (map second
ocsenave@347 487 ((hxc-cry) pkmn)))))
ocsenave@347 488
ocsenave@347 489 (def hxc-items-raw
ocsenave@347 490 "The hardcoded names of the items in memory. List begins at
ocsenave@347 491 ROM@045B7"
ocsenave@347 492 (hxc-thunk-words 0x45B7 870))
ocsenave@347 493
ocsenave@347 494 (def hxc-types
ocsenave@347 495 "The hardcoded type names in memory. List begins at ROM@27D99,
ocsenave@347 496 shortly before hxc-titles."
ocsenave@347 497 (hxc-thunk-words 0x27D99 102))
ocsenave@347 498
ocsenave@347 499 (def hxc-titles
ocsenave@347 500 "The hardcoded names of the trainer titles in memory. List begins at
ocsenave@347 501 ROM@27E77"
ocsenave@347 502 (hxc-thunk-words 0x27E77 196))
ocsenave@347 503
ocsenave@347 504
ocsenave@347 505 (def hxc-pokedex-text-raw
ocsenave@347 506 "The hardcoded pokedex entries in memory. List begins at
ocsenave@347 507 ROM@B8000, shortly before move names."
ocsenave@347 508 (hxc-thunk-words 0xB8000 14754))
ocsenave@347 509
ocsenave@347 510
ocsenave@347 511
ocsenave@347 512 (def hxc-items
ocsenave@347 513 "The hardcoded names of the items in memory, presented as
ocsenave@347 514 keywords. List begins at ROM@045B7. See also, hxc-items-raw."
ocsenave@347 515 (comp (partial map format-name) hxc-items-raw))
ocsenave@347 516
ocsenave@347 517 (defn hxc-pokedex-text
ocsenave@347 518 "The hardcoded pokedex entries in memory, presented as an
ocsenave@347 519 associative hash map. List begins at ROM@B8000."
ocsenave@347 520 ([] (hxc-pokedex-text com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 521 ([rom]
ocsenave@347 522 (zipmap
ocsenave@347 523 (hxc-pokedex-names rom)
ocsenave@347 524 (cons nil ;; for missingno.
ocsenave@347 525 (hxc-pokedex-text-raw rom)))))
ocsenave@347 526
ocsenave@347 527 ;; In red/blue, pokedex stats are in internal order.
ocsenave@347 528 ;; In yellow, pokedex stats are in pokedex order.
ocsenave@347 529
ocsenave@347 530 (defn hxc-pokedex-stats
ocsenave@347 531 "The hardcoded pokedex stats (species height weight) in memory. List
ocsenave@347 532 begins at ROM@40687"
ocsenave@347 533 ([] (hxc-pokedex-stats com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 534 ([rom]
ocsenave@347 535 (let [pokedex-names (zipmap (range) (hxc-pokedex-names rom))
ocsenave@347 536 pkmn-count (count pokedex-names)
ocsenave@347 537 ]
ocsenave@347 538 ((fn capture-stats
ocsenave@347 539 [n stats data]
ocsenave@347 540 (if (zero? n) stats
ocsenave@347 541 (let [[species
ocsenave@347 542 [_
ocsenave@347 543 height-ft
ocsenave@347 544 height-in
ocsenave@347 545 weight-1
ocsenave@347 546 weight-2
ocsenave@347 547 _
ocsenave@347 548 dex-ptr-1
ocsenave@347 549 dex-ptr-2
ocsenave@347 550 dex-bank
ocsenave@347 551 _
ocsenave@347 552 & data]]
ocsenave@347 553 (split-with (partial not= 0x50) data)]
ocsenave@347 554 (recur (dec n)
ocsenave@347 555 (assoc stats
ocsenave@347 556 (pokedex-names (- pkmn-count (dec n)))
ocsenave@347 557 {:species
ocsenave@347 558 (format-name (character-codes->str species))
ocsenave@347 559 :height-ft
ocsenave@347 560 height-ft
ocsenave@347 561 :height-in
ocsenave@347 562 height-in
ocsenave@347 563 :weight
ocsenave@347 564 (/ (low-high weight-1 weight-2) 10.)
ocsenave@347 565
ocsenave@347 566 ;; :text
ocsenave@347 567 ;; (character-codes->str
ocsenave@347 568 ;; (take-while
ocsenave@347 569 ;; (partial not= 0x50)
ocsenave@347 570 ;; (drop
ocsenave@347 571 ;; (+ 0xB8000
ocsenave@347 572 ;; -0x4000
ocsenave@347 573 ;; (low-high dex-ptr-1 dex-ptr-2))
ocsenave@347 574 ;; rom)))
ocsenave@347 575 })
ocsenave@347 576
ocsenave@347 577 data)
ocsenave@347 578
ocsenave@347 579
ocsenave@347 580 )))
ocsenave@347 581
ocsenave@347 582 pkmn-count
ocsenave@347 583 {}
ocsenave@347 584 (drop 0x40687 rom))) ))
ocsenave@347 585
ocsenave@347 586
ocsenave@347 587
ocsenave@347 588
ocsenave@347 589
ocsenave@347 590
ocsenave@347 591
ocsenave@347 592 (def hxc-places
ocsenave@347 593 "The hardcoded place names in memory. List begins at
ocsenave@347 594 ROM@71500. [Cinnabar] Mansion seems to be dynamically calculated."
ocsenave@347 595 (hxc-thunk-words 0x71500 560))
ocsenave@347 596
ocsenave@347 597
ocsenave@347 598 (defn hxc-dialog
ocsenave@347 599 "The hardcoded dialogue in memory, including in-game alerts. Dialog
ocsenave@347 600 seems to be separated by 0x57 instead of 0x50 (END). Begins at ROM@98000."
ocsenave@347 601 ([rom]
ocsenave@347 602 (map character-codes->str
ocsenave@347 603 (take-nth 2
ocsenave@347 604 (partition-by #(= % 0x57)
ocsenave@347 605 (take 0x0F728
ocsenave@347 606 (drop 0x98000 rom))))))
ocsenave@347 607 ([]
ocsenave@347 608 (hxc-dialog com.aurellem.gb.gb-driver/original-rom)))
ocsenave@347 609
ocsenave@347 610
ocsenave@347 611 (def hxc-move-names
ocsenave@347 612 "The hardcoded move names in memory. List begins at ROM@BC000"
ocsenave@347 613 (hxc-thunk-words 0xBC000 1551))
ocsenave@347 614
ocsenave@347 615
ocsenave@347 616 (defn hxc-move-data
ocsenave@347 617 "The hardcoded (basic (move effects)) in memory. List begins at
ocsenave@347 618 0x38000. Returns a map of {:name :power :accuracy :pp :fx-id
ocsenave@347 619 :fx-txt}. The move descriptions are handwritten, not hardcoded."
ocsenave@347 620 ([]
ocsenave@347 621 (hxc-move-data com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 622 ([rom]
ocsenave@347 623 (let [names (vec (hxc-move-names rom))
ocsenave@347 624 move-count (count names)
ocsenave@347 625 move-size 6
ocsenave@347 626 types pkmn-types ;;; !! hardcoded types
ocsenave@347 627 ]
ocsenave@347 628 (zipmap (map format-name names)
ocsenave@347 629 (map
ocsenave@347 630 (fn [[idx effect power type-id accuracy pp]]
ocsenave@347 631 {:name (names (dec idx))
ocsenave@347 632 :power power
ocsenave@347 633 :accuracy accuracy
ocsenave@347 634 :pp pp
ocsenave@347 635 :type (types type-id)
ocsenave@347 636 :fx-id effect
ocsenave@347 637 :fx-txt (get move-effects effect)
ocsenave@347 638 }
ocsenave@347 639 )
ocsenave@347 640
ocsenave@347 641 (partition move-size
ocsenave@347 642 (take (* move-size move-count)
ocsenave@347 643 (drop 0x38000 rom))))))))
ocsenave@347 644
ocsenave@347 645
ocsenave@347 646
ocsenave@347 647 (defn hxc-move-data*
ocsenave@347 648 "Like hxc-move-data, but reports numbers as hexadecimal symbols instead."
ocsenave@347 649 ([]
ocsenave@347 650 (hxc-move-data* com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 651 ([rom]
ocsenave@347 652 (let [names (vec (hxc-move-names rom))
ocsenave@347 653 move-count (count names)
ocsenave@347 654 move-size 6
ocsenave@347 655 format-name (fn [s]
ocsenave@347 656 (keyword (.toLowerCase
ocsenave@347 657 (apply str
ocsenave@347 658 (map #(if (= % \space) "-" %) s)))))
ocsenave@347 659 ]
ocsenave@347 660 (zipmap (map format-name names)
ocsenave@347 661 (map
ocsenave@347 662 (fn [[idx effect power type accuracy pp]]
ocsenave@347 663 {:name (names (dec idx))
ocsenave@347 664 :power power
ocsenave@347 665 :accuracy (hex accuracy)
ocsenave@347 666 :pp pp
ocsenave@347 667 :fx-id (hex effect)
ocsenave@347 668 :fx-txt (get move-effects effect)
ocsenave@347 669 }
ocsenave@347 670 )
ocsenave@347 671
ocsenave@347 672 (partition move-size
ocsenave@347 673 (take (* move-size move-count)
ocsenave@347 674 (drop 0x38000 rom))))))))
ocsenave@347 675
ocsenave@347 676
ocsenave@347 677 (defn hxc-machines
ocsenave@347 678 "The hardcoded moves taught by TMs and HMs. List begins at ROM@1232D."
ocsenave@347 679 ([] (hxc-machines
ocsenave@347 680 com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 681 ([rom]
ocsenave@347 682 (let [moves (hxc-move-names rom)]
ocsenave@347 683 (zipmap
ocsenave@347 684 (range)
ocsenave@347 685 (take-while
ocsenave@347 686 (comp not nil?)
ocsenave@347 687 (map (comp
ocsenave@347 688 format-name
ocsenave@347 689 (zipmap
ocsenave@347 690 (range)
ocsenave@347 691 moves)
ocsenave@347 692 dec)
ocsenave@347 693 (take 100
ocsenave@347 694 (drop 0x1232D rom))))))))
ocsenave@347 695
ocsenave@347 696
ocsenave@347 697
ocsenave@347 698 (defn internal-id
ocsenave@347 699 ([rom]
ocsenave@347 700 (zipmap
ocsenave@347 701 (hxc-pokenames rom)
ocsenave@347 702 (range)))
ocsenave@347 703 ([]
ocsenave@347 704 (internal-id com.aurellem.gb.gb-driver/original-rom)))
ocsenave@347 705
ocsenave@347 706
ocsenave@347 707
ocsenave@347 708
ocsenave@347 709
ocsenave@347 710 ;; nidoran gender change upon levelup
ocsenave@347 711 ;; (->
ocsenave@347 712 ;; @current-state
ocsenave@347 713 ;; rom
ocsenave@347 714 ;; vec
ocsenave@347 715 ;; (rewrite-memory
ocsenave@347 716 ;; (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♂))
ocsenave@347 717 ;; [1 1 15])
ocsenave@347 718 ;; (rewrite-memory
ocsenave@347 719 ;; (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♀))
ocsenave@347 720 ;; [1 1 3])
ocsenave@347 721 ;; (write-rom!)
ocsenave@347 722
ocsenave@347 723 ;; )
ocsenave@347 724
ocsenave@347 725
ocsenave@347 726
ocsenave@347 727
ocsenave@347 728 (defn hxc-advantage
ocsenave@347 729 ;; in-game multipliers are stored as 10x their effective value
ocsenave@347 730 ;; to allow for fractional multipliers like 1/2
ocsenave@347 731
ocsenave@347 732 "The hardcoded type advantages in memory, returned as tuples of
ocsenave@347 733 atk-type def-type multiplier. By default (i.e. if not listed here),
ocsenave@347 734 the multiplier is 1. List begins at 0x3E62D."
ocsenave@347 735 ([] (hxc-advantage com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 736 ([rom]
ocsenave@347 737 (map
ocsenave@347 738 (fn [[atk def mult]] [(get pkmn-types atk (hex atk))
ocsenave@347 739 (get pkmn-types def (hex def))
ocsenave@347 740 (/ mult 10)])
ocsenave@347 741 (partition 3
ocsenave@347 742 (take-while (partial not= 0xFF)
ocsenave@347 743 (drop 0x3E62D rom))))))
ocsenave@347 744
ocsenave@347 745
ocsenave@347 746
ocsenave@347 747 (defn format-evo
ocsenave@347 748 "Parse a sequence of evolution data, returning a map. First is the
ocsenave@347 749 method: 0 = end-evolution-data. 1 = level-up, 2 = item, 3 = trade. Next is an item id, if the
ocsenave@347 750 method of evolution is by item (only stones will actually make pokemon
ocsenave@347 751 evolve, for some auxillary reason.) Finally, the minimum level for
ocsenave@347 752 evolution to occur (level 1 means no limit, which is used for trade
ocsenave@347 753 and item evolutions), followed by the internal id of the pokemon
ocsenave@347 754 into which to evolve. Hence, level up and trade evolutions are
ocsenave@347 755 described with 3
ocsenave@347 756 bytes; item evolutions with four."
ocsenave@347 757 [coll]
ocsenave@347 758 (let [method (first coll)]
ocsenave@347 759 (cond (empty? coll) []
ocsenave@347 760 (= 0 method) [] ;; just in case
ocsenave@347 761 (= 1 method) ;; level-up evolution
ocsenave@347 762 (conj (format-evo (drop 3 coll))
ocsenave@347 763 {:method :level-up
ocsenave@347 764 :min-level (nth coll 1)
ocsenave@347 765 :into (dec (nth coll 2))})
ocsenave@347 766
ocsenave@347 767 (= 2 method) ;; item evolution
ocsenave@347 768 (conj (format-evo (drop 4 coll))
ocsenave@347 769 {:method :item
ocsenave@347 770 :item (dec (nth coll 1))
ocsenave@347 771 :min-level (nth coll 2)
ocsenave@347 772 :into (dec (nth coll 3))})
ocsenave@347 773
ocsenave@347 774 (= 3 method) ;; trade evolution
ocsenave@347 775 (conj (format-evo (drop 3 coll))
ocsenave@347 776 {:method :trade
ocsenave@347 777 :min-level (nth coll 1) ;; always 1 for trade.
ocsenave@347 778 :into (dec (nth coll 2))}))))
ocsenave@347 779
ocsenave@347 780
ocsenave@347 781 (defn hxc-ptrs-evolve
ocsenave@347 782 "A hardcoded collection of 190 pointers to alternating evolution/learnset data,
ocsenave@347 783 in internal order."
ocsenave@347 784 ([]
ocsenave@347 785 (hxc-ptrs-evolve com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 786 ([rom]
ocsenave@347 787 (let [
ocsenave@347 788 pkmn-count (count (hxc-pokenames-raw)) ;; 190
ocsenave@347 789 ptrs
ocsenave@347 790 (map (fn [[a b]] (low-high a b))
ocsenave@347 791 (partition 2
ocsenave@347 792 (take (* 2 pkmn-count)
ocsenave@347 793 (drop 0x3b1e5 rom))))]
ocsenave@347 794 (map (partial + 0x34000) ptrs)
ocsenave@347 795
ocsenave@347 796 )))
ocsenave@347 797
ocsenave@347 798
ocsenave@347 799 (defn hxc-learnsets
ocsenave@347 800 "Hardcoded map associating pokemon names to lists of pairs [lvl
ocsenave@347 801 move] of abilities they learn as they level up. The data
ocsenave@347 802 exists at ROM@34000, sorted by internal order. Pointers to the data
ocsenave@347 803 exist at ROM@3B1E5; see also, hxc-ptrs-evolve"
ocsenave@347 804 ([] (hxc-learnsets com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 805 ([rom]
ocsenave@347 806 (apply assoc
ocsenave@347 807 {}
ocsenave@347 808 (interleave
ocsenave@347 809 (hxc-pokenames rom)
ocsenave@347 810 (map (comp
ocsenave@347 811 (partial map
ocsenave@347 812 (fn [[lvl mv]] [lvl (dec mv)]))
ocsenave@347 813 (partial partition 2)
ocsenave@347 814 ;; keep the learnset data
ocsenave@347 815 (partial take-while (comp not zero?))
ocsenave@347 816 ;; skip the evolution data
ocsenave@347 817 rest
ocsenave@347 818 (partial drop-while (comp not zero?)))
ocsenave@347 819 (map #(drop % rom)
ocsenave@347 820 (hxc-ptrs-evolve rom)))))))
ocsenave@347 821
ocsenave@347 822 (defn hxc-learnsets-pretty
ocsenave@347 823 "Live hxc-learnsets except it reports the name of each move --- as
ocsenave@347 824 it appears in rom --- rather than the move index."
ocsenave@347 825 ([] (hxc-learnsets-pretty com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 826 ([rom]
ocsenave@347 827 (let [moves (vec(map format-name (hxc-move-names)))]
ocsenave@347 828 (into {}
ocsenave@347 829 (map (fn [[pkmn learnset]]
ocsenave@347 830 [pkmn (map (fn [[lvl mv]] [lvl (moves mv)])
ocsenave@347 831 learnset)])
ocsenave@347 832 (hxc-learnsets rom))))))
ocsenave@347 833
ocsenave@347 834
ocsenave@347 835
ocsenave@347 836
ocsenave@347 837 (defn hxc-evolution
ocsenave@347 838 "Hardcoded evolution data in memory. The data exists at ROM@34000,
ocsenave@347 839 sorted by internal order. Pointers to the data exist at ROM@3B1E5; see also, hxc-ptrs-evolve."
ocsenave@347 840 ([] (hxc-evolution com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 841 ([rom]
ocsenave@347 842 (apply assoc {}
ocsenave@347 843 (interleave
ocsenave@347 844 (hxc-pokenames rom)
ocsenave@347 845 (map
ocsenave@347 846 (comp
ocsenave@347 847 format-evo
ocsenave@347 848 (partial take-while (comp not zero?))
ocsenave@347 849 #(drop % rom))
ocsenave@347 850 (hxc-ptrs-evolve rom)
ocsenave@347 851 )))))
ocsenave@347 852
ocsenave@347 853 (defn hxc-evolution-pretty
ocsenave@347 854 "Like hxc-evolution, except it uses the names of items and pokemon
ocsenave@347 855 --- grabbed from ROM --- rather than their numerical identifiers."
ocsenave@347 856 ([] (hxc-evolution-pretty com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 857 ([rom]
ocsenave@347 858 (let
ocsenave@347 859 [poke-names (vec (hxc-pokenames rom))
ocsenave@347 860 item-names (vec (hxc-items rom))
ocsenave@347 861 use-names
ocsenave@347 862 (fn [m]
ocsenave@347 863 (loop [ks (keys m) new-map m]
ocsenave@347 864 (let [k (first ks)]
ocsenave@347 865 (cond (nil? ks) new-map
ocsenave@347 866 (= k :into)
ocsenave@347 867 (recur
ocsenave@347 868 (next ks)
ocsenave@347 869 (assoc new-map
ocsenave@347 870 :into
ocsenave@347 871 (poke-names
ocsenave@347 872 (:into
ocsenave@347 873 new-map))))
ocsenave@347 874 (= k :item)
ocsenave@347 875 (recur
ocsenave@347 876 (next ks)
ocsenave@347 877 (assoc new-map
ocsenave@347 878 :item
ocsenave@347 879 (item-names
ocsenave@347 880 (:item new-map))))
ocsenave@347 881 :else
ocsenave@347 882 (recur
ocsenave@347 883 (next ks)
ocsenave@347 884 new-map)
ocsenave@347 885 ))))]
ocsenave@347 886
ocsenave@347 887 (into {}
ocsenave@347 888 (map (fn [[pkmn evo-coll]]
ocsenave@347 889 [pkmn (map use-names evo-coll)])
ocsenave@347 890 (hxc-evolution rom))))))
ocsenave@347 891
ocsenave@347 892
ocsenave@347 893 (defn hxc-pokemon-base
ocsenave@347 894 ([] (hxc-pokemon-base com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 895 ([rom]
ocsenave@347 896 (let [entry-size 28
ocsenave@347 897 pkmn-count (count (hxc-pokedex-text rom))
ocsenave@347 898 pokemon (rest (hxc-pokedex-names))
ocsenave@347 899 types (apply assoc {}
ocsenave@347 900 (interleave
ocsenave@347 901 (range)
ocsenave@347 902 pkmn-types)) ;;!! softcoded
ocsenave@347 903 moves (apply assoc {}
ocsenave@347 904 (interleave
ocsenave@347 905 (range)
ocsenave@347 906 (map format-name
ocsenave@347 907 (hxc-move-names rom))))
ocsenave@347 908 machines (hxc-machines)
ocsenave@347 909 ]
ocsenave@347 910 (zipmap
ocsenave@347 911 pokemon
ocsenave@347 912 (map
ocsenave@347 913 (fn [[n
ocsenave@347 914 rating-hp
ocsenave@347 915 rating-atk
ocsenave@347 916 rating-def
ocsenave@347 917 rating-speed
ocsenave@347 918 rating-special
ocsenave@347 919 type-1
ocsenave@347 920 type-2
ocsenave@347 921 rarity
ocsenave@347 922 rating-xp
ocsenave@347 923 pic-dimensions ;; tile_width|tile_height (8px/tile)
ocsenave@347 924 ptr-pic-obverse-1
ocsenave@347 925 ptr-pic-obverse-2
ocsenave@347 926 ptr-pic-reverse-1
ocsenave@347 927 ptr-pic-reverse-2
ocsenave@347 928 move-1
ocsenave@347 929 move-2
ocsenave@347 930 move-3
ocsenave@347 931 move-4
ocsenave@347 932 growth-rate
ocsenave@347 933 &
ocsenave@347 934 TMs|HMs]]
ocsenave@347 935 (let
ocsenave@347 936 [base-moves
ocsenave@347 937 (mapv moves
ocsenave@347 938 ((comp
ocsenave@347 939 ;; since the game uses zero as a delimiter,
ocsenave@347 940 ;; it must also increment all move indices by 1.
ocsenave@347 941 ;; heren we decrement to correct this.
ocsenave@347 942 (partial map dec)
ocsenave@347 943 (partial take-while (comp not zero?)))
ocsenave@347 944 [move-1 move-2 move-3 move-4]))
ocsenave@347 945
ocsenave@347 946 types
ocsenave@347 947 (set (list (types type-1)
ocsenave@347 948 (types type-2)))
ocsenave@347 949 TMs|HMs
ocsenave@347 950 (map
ocsenave@347 951 (comp
ocsenave@347 952 (partial map first)
ocsenave@347 953 (partial remove (comp zero? second)))
ocsenave@347 954 (split-at
ocsenave@347 955 50
ocsenave@347 956 (map vector
ocsenave@347 957 (rest(range))
ocsenave@347 958 (reduce concat
ocsenave@347 959 (map
ocsenave@347 960 #(take 8
ocsenave@347 961 (concat (bit-list %)
ocsenave@347 962 (repeat 0)))
ocsenave@347 963
ocsenave@347 964 TMs|HMs)))))
ocsenave@347 965
ocsenave@347 966 TMs (vec (first TMs|HMs))
ocsenave@347 967 HMs (take 5 (map (partial + -50) (vec (second TMs|HMs))))
ocsenave@347 968
ocsenave@347 969
ocsenave@347 970 ]
ocsenave@347 971
ocsenave@347 972
ocsenave@347 973 {:dex# n
ocsenave@347 974 :base-moves base-moves
ocsenave@347 975 :types types
ocsenave@347 976 :TMs TMs
ocsenave@347 977 :HMs HMs
ocsenave@347 978 :base-hp rating-hp
ocsenave@347 979 :base-atk rating-atk
ocsenave@347 980 :base-def rating-def
ocsenave@347 981 :base-speed rating-speed
ocsenave@347 982 :base-special rating-special
ocsenave@347 983 :o0 pic-dimensions
ocsenave@347 984 :o1 ptr-pic-obverse-1
ocsenave@347 985 :o2 ptr-pic-obverse-2
ocsenave@347 986 }))
ocsenave@347 987
ocsenave@347 988 (partition entry-size
ocsenave@347 989 (take (* entry-size pkmn-count)
ocsenave@347 990 (drop 0x383DE
ocsenave@347 991 rom))))))))
ocsenave@347 992
ocsenave@347 993
ocsenave@347 994 (defn hxc-intro-pkmn
ocsenave@347 995 "The hardcoded pokemon to display in Prof. Oak's introduction; the pokemon's
ocsenave@347 996 internal id is stored at ROM@5EDB."
ocsenave@347 997 ([] (hxc-intro-pkmn
ocsenave@347 998 com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 999 ([rom]
ocsenave@347 1000 (nth (hxc-pokenames rom) (nth rom 0x5EDB))))
ocsenave@347 1001
ocsenave@347 1002 (defn sxc-intro-pkmn!
ocsenave@347 1003 "Set the hardcoded pokemon to display in Prof. Oak's introduction."
ocsenave@347 1004 [pokemon]
ocsenave@347 1005 (write-rom!
ocsenave@347 1006 (rewrite-rom 0x5EDB
ocsenave@347 1007 [
ocsenave@347 1008 (inc
ocsenave@347 1009 ((zipmap
ocsenave@347 1010 (hxc-pokenames)
ocsenave@347 1011 (range))
ocsenave@347 1012 pokemon))])))
ocsenave@347 1013
ocsenave@347 1014
ocsenave@347 1015 (defn hxc-item-prices
ocsenave@347 1016 "The hardcoded list of item prices in memory. List begins at ROM@4495"
ocsenave@347 1017 ([] (hxc-item-prices com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 1018 ([rom]
ocsenave@347 1019 (let [items (hxc-items rom)
ocsenave@347 1020 price-size 3]
ocsenave@347 1021 (zipmap items
ocsenave@347 1022 (map (comp
ocsenave@347 1023 ;; zero-cost items are "priceless"
ocsenave@347 1024 #(if (zero? %) :priceless %)
ocsenave@347 1025 decode-bcd butlast)
ocsenave@347 1026 (partition price-size
ocsenave@347 1027 (take (* price-size (count items))
ocsenave@347 1028 (drop 0x4495 rom))))))))
ocsenave@347 1029
ocsenave@347 1030 (defn hxc-shops
ocsenave@347 1031 ([] (hxc-shops com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 1032 ([rom]
ocsenave@347 1033 (let [items (zipmap (range) (hxc-items rom))
ocsenave@347 1034
ocsenave@347 1035 ;; temporarily softcode the TM items
ocsenave@347 1036 items (into
ocsenave@347 1037 items
ocsenave@347 1038 (map (juxt identity
ocsenave@347 1039 (comp keyword
ocsenave@347 1040 (partial str "tm-")
ocsenave@347 1041 (partial + 1 -200)
ocsenave@347 1042 ))
ocsenave@347 1043 (take 200 (drop 200 (range)))))
ocsenave@347 1044
ocsenave@347 1045 ]
ocsenave@347 1046
ocsenave@347 1047 ((fn parse-shop [coll [num-items & items-etc]]
ocsenave@347 1048 (let [inventory (take-while
ocsenave@347 1049 (partial not= 0xFF)
ocsenave@347 1050 items-etc)
ocsenave@347 1051 [separator & items-etc] (drop num-items (rest items-etc))]
ocsenave@347 1052 (if (= separator 0x50)
ocsenave@347 1053 (map (partial mapv (comp items dec)) (conj coll inventory))
ocsenave@347 1054 (recur (conj coll inventory) items-etc)
ocsenave@347 1055 )
ocsenave@347 1056 ))
ocsenave@347 1057
ocsenave@347 1058 '()
ocsenave@347 1059 (drop 0x233C rom))
ocsenave@347 1060
ocsenave@347 1061
ocsenave@347 1062 )))
ocsenave@347 1063
ocsenave@347 1064
ocsenave@347 1065
ocsenave@347 1066
ocsenave@347 1067
ocsenave@347 1068 (defn hxc-ptrs-wild
ocsenave@347 1069 "A list of the hardcoded wild encounter data in memory. Pointers
ocsenave@347 1070 begin at ROM@0CB95; data begins at ROM@0x04D89"
ocsenave@347 1071 ([] (hxc-ptrs-wild com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 1072 ([rom]
ocsenave@347 1073 (let [ptrs
ocsenave@347 1074 (map (fn [[a b]] (+ a (* 0x100 b)))
ocsenave@347 1075 (take-while (partial not= (list 0xFF 0xFF))
ocsenave@347 1076 (partition 2 (drop 0xCB95 rom))))]
ocsenave@347 1077 ptrs)))
ocsenave@347 1078
ocsenave@347 1079
ocsenave@347 1080
ocsenave@347 1081 (defn hxc-wilds
ocsenave@347 1082 "A list of the hardcoded wild encounter data in memory. Pointers
ocsenave@347 1083 begin at ROM@0CB95; data begins at ROM@0x04D89"
ocsenave@347 1084 ([] (hxc-wilds com.aurellem.gb.gb-driver/original-rom))
ocsenave@347 1085 ([rom]
ocsenave@347 1086 (let [pokenames (zipmap (range) (hxc-pokenames rom))]
ocsenave@347 1087 (map
ocsenave@347 1088 (partial map (fn [[a b]] {:species (pokenames (dec b)) :level
ocsenave@347 1089 a}))
ocsenave@347 1090 (partition 10
ocsenave@347 1091
ocsenave@347 1092 (take-while (comp (partial not= 1)
ocsenave@347 1093 first)
ocsenave@347 1094 (partition 2
ocsenave@347 1095 (drop 0xCD8C rom))
ocsenave@347 1096
ocsenave@347 1097 ))))))
ocsenave@347 1098
ocsenave@347 1099
ocsenave@347 1100
ocsenave@347 1101
ocsenave@347 1102
ocsenave@347 1103
ocsenave@347 1104
ocsenave@347 1105
ocsenave@347 1106
ocsenave@347 1107
ocsenave@347 1108
ocsenave@347 1109
ocsenave@347 1110
ocsenave@347 1111
ocsenave@347 1112 ;; ********************** MANIPULATION FNS
ocsenave@347 1113
ocsenave@347 1114
ocsenave@347 1115 (defn same-type
ocsenave@347 1116 ([pkmn move]
ocsenave@347 1117 (same-type
ocsenave@347 1118 com.aurellem.gb.gb-driver/original-rom pkmn move))
ocsenave@347 1119 ([rom pkmn move]
ocsenave@347 1120 (((comp :types (hxc-pokemon-base rom)) pkmn)
ocsenave@347 1121 ((comp :type (hxc-move-data rom)) move))))
ocsenave@347 1122
ocsenave@347 1123
ocsenave@347 1124
ocsenave@347 1125
ocsenave@347 1126 (defn submap?
ocsenave@347 1127 "Compares the two maps. Returns true if map-big has the same associations as map-small, otherwise false."
ocsenave@347 1128 [map-small map-big]
ocsenave@347 1129 (cond (empty? map-small) true
ocsenave@347 1130 (and
ocsenave@347 1131 (contains? map-big (ffirst map-small))
ocsenave@347 1132 (= (get map-big (ffirst map-small))
ocsenave@347 1133 (second (first map-small))))
ocsenave@347 1134 (recur (next map-small) map-big)
ocsenave@347 1135
ocsenave@347 1136 :else false))
ocsenave@347 1137
ocsenave@347 1138
ocsenave@347 1139 (defn search-map [proto-map maps]
ocsenave@347 1140 "Returns all the maps that make the same associations as proto-map."
ocsenave@347 1141 (some (partial submap? proto-map) maps))
ocsenave@347 1142
ocsenave@347 1143 (defn filter-vals
ocsenave@347 1144 "Returns a map consisting of all the pairs [key val] for
ocsenave@347 1145 which (pred key) returns true."
ocsenave@347 1146 [pred map]
ocsenave@347 1147 (reduce (partial apply assoc) {}
ocsenave@347 1148 (filter (fn [[k v]] (pred v)) map)))
ocsenave@347 1149
ocsenave@347 1150
ocsenave@347 1151 (defn search-moves
ocsenave@347 1152 "Returns a subcollection of all hardcoded moves with the
ocsenave@347 1153 given attributes. Attributes consist of :name :power
ocsenave@347 1154 :accuracy :pp :fx-id
ocsenave@347 1155 (and also :fx-txt, but it contains the same information
ocsenave@347 1156 as :fx-id)"
ocsenave@347 1157 ([attribute-map]
ocsenave@347 1158 (search-moves
ocsenave@347 1159 com.aurellem.gb.gb-driver/original-rom attribute-map))
ocsenave@347 1160 ([rom attribute-map]
ocsenave@347 1161 (filter-vals (partial submap? attribute-map)
ocsenave@347 1162 (hxc-move-data rom))))
ocsenave@347 1163
ocsenave@347 1164
ocsenave@347 1165
ocsenave@347 1166
ocsenave@347 1167
ocsenave@347 1168 ;; note: 0x2f31 contains the names "TM" "HM"?
ocsenave@347 1169
ocsenave@347 1170 ;; note for later: credits start at F1290
ocsenave@347 1171
ocsenave@347 1172 ;; note: DADB hyper-potion-hp _ _ _ super-potion-hp _ _ _ potion-hp ??
ocsenave@347 1173
ocsenave@347 1174 ;; note: DD4D spells out pokemon vital stat names ("speed", etc.)
ocsenave@347 1175
ocsenave@347 1176 ;; note: 1195C-6A says ABLE#NOT ABLE#, but so does 119C0-119CE.
ocsenave@347 1177 ;; The first instance is for Machines; the second, for stones.
ocsenave@347 1178
ocsenave@347 1179 ;; 0x251A (in indexable mem): image decompression routine seems to begin here.
ocsenave@347 1180
ocsenave@347 1181
ocsenave@347 1182 (comment
ocsenave@347 1183
ocsenave@347 1184 (def hxc-later
ocsenave@347 1185 "Running this code produces, e.g. hardcoded names NPCs give
ocsenave@347 1186 their pokemon. Will sort through it later."
ocsenave@347 1187 (print (character-codes->str(take 10000
ocsenave@347 1188 (drop 0x71597
ocsenave@347 1189 (rom (root)))))))
ocsenave@347 1190
ocsenave@347 1191 (let [dex
ocsenave@347 1192 (partition-by #(= 0x50 %)
ocsenave@347 1193 (take 2540
ocsenave@347 1194 (drop 0x40687
ocsenave@347 1195 (rom (root)))))]
ocsenave@347 1196 (def dex dex)
ocsenave@347 1197 (def hxc-species
ocsenave@347 1198 (map character-codes->str
ocsenave@347 1199 (take-nth 4 dex))))
ocsenave@347 1200 )
ocsenave@347 1201
ocsenave@347 1202
ocsenave@347 1203 #+end_src
ocsenave@347 1204