Mercurial > vba-clojure
changeset 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 |
files | clojure/com/aurellem/gb/hxc.clj org/rom.org |
diffstat | 2 files changed, 1171 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
1.1 --- a/clojure/com/aurellem/gb/hxc.clj Sun Apr 08 01:28:39 2012 -0500 1.2 +++ b/clojure/com/aurellem/gb/hxc.clj Sun Apr 08 06:13:39 2012 -0500 1.3 @@ -1,3 +1,4 @@ 1.4 + 1.5 (ns com.aurellem.gb.hxc 1.6 (:use (com.aurellem.gb assembly characters gb-driver util mem-util 1.7 constants species)) 1.8 @@ -8,8 +9,6 @@ 1.9 1.10 ; ************* HANDWRITTEN CONSTANTS 1.11 1.12 - 1.13 - 1.14 (def pkmn-types 1.15 [:normal ;;0 1.16 :fighting ;;1 1.17 @@ -138,7 +137,6 @@ 1.18 "(disable)" 1.19 ]) 1.20 1.21 - 1.22 ;; ************** HARDCODED DATA 1.23 1.24 (defn hxc-thunk 1.25 @@ -162,7 +160,6 @@ 1.26 (partial comp (partial map character-codes->str)) 1.27 hxc-thunk)) 1.28 1.29 - 1.30 ;; -------------------------------------------------- 1.31 1.32 1.33 @@ -510,6 +507,15 @@ 1.34 1.35 1.36 (defn format-evo 1.37 + "Parse a sequence of evolution data, returning a map. First is the 1.38 +method: 0 = end-evolution-data. 1 = level-up, 2 = item, 3 = trade. Next is an item id, if the 1.39 + method of evolution is by item (only stones will actually make pokemon 1.40 + evolve, for some auxillary reason.) Finally, the minimum level for 1.41 + evolution to occur (level 1 means no limit, which is used for trade 1.42 + and item evolutions), followed by the internal id of the pokemon 1.43 + into which to evolve. Hence, level up and trade evolutions are 1.44 + described with 3 1.45 + bytes; item evolutions with four." 1.46 [coll] 1.47 (let [method (first coll)] 1.48 (cond (empty? coll) [] 1.49 @@ -555,7 +561,7 @@ 1.50 (defn hxc-learnsets 1.51 "Hardcoded map associating pokemon names to lists of pairs [lvl 1.52 move] of abilities they learn as they level up. The data 1.53 -exists at ROM@3400, sorted by internal order. Pointers to the data 1.54 +exists at ROM@34000, sorted by internal order. Pointers to the data 1.55 exist at ROM@3B1E5; see also, hxc-ptrs-evolve" 1.56 ([] (hxc-learnsets com.aurellem.gb.gb-driver/original-rom)) 1.57 ([rom] 1.58 @@ -932,6 +938,9 @@ 1.59 ;; note: 1195C-6A says ABLE#NOT ABLE#, but so does 119C0-119CE. 1.60 ;; The first instance is for Machines; the second, for stones. 1.61 1.62 +;; 0x251A (in indexable mem): image decompression routine seems to begin here. 1.63 + 1.64 + 1.65 (comment 1.66 1.67 (def hxc-later 1.68 @@ -951,9 +960,3 @@ 1.69 (map character-codes->str 1.70 (take-nth 4 dex)))) 1.71 ) 1.72 - 1.73 - 1.74 - 1.75 - 1.76 - 1.77 -
2.1 --- a/org/rom.org Sun Apr 08 01:28:39 2012 -0500 2.2 +++ b/org/rom.org Sun Apr 08 06:13:39 2012 -0500 2.3 @@ -10,7 +10,9 @@ 2.4 # about map headers http://datacrystal.romhacking.net/wiki/Pokemon_Red/Blue:Notes 2.5 # map headers Yellow http://www.pokecommunity.com/archive/index.php/t-235311.html 2.6 # pokedollar: U+20B1 2.7 -* Mapping the ROM 2.8 +* Introduction 2.9 + 2.10 +** Mapping the ROM 2.11 2.12 | ROM address (hex) | Description | Format | Example | 2.13 |-------------------+-----------------+-----------------+-----------------| 2.14 @@ -22,18 +24,24 @@ 2.15 | 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. | 2.16 | 06698- | ? Background music. | | | 2.17 | 0822E-082F? | Pointers to background music, part I. | | | 2.18 -| 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 above). | 2.19 +| 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). | 2.20 +|-------------------+-----------------+-----------------+-----------------| 2.21 +| 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 | 2.22 +| 0DAE0. | Amount of HP restored by Super Potion. | " | 50 | 2.23 +| 0DAE3. | Amount of HP restored by Potion. | " | 20 | 2.24 +|-------------------+-----------------+-----------------+-----------------| 2.25 | 0DD4D-DD72 | Names of permanent stats. | Variable-length strings separated by 0x50. | #HEALTH#ATTACK#DEFENSE#SPEED#SPECIAL# | 2.26 | 1195C-1196A | The two terms for being able/unable to learn a TM/HM. | Variable-length strings separated by 0x50. | ABLE#NOT ABLE# | 2.27 | 119C0-119CE | The two terms for being able/unable to evolve using the current stone. | Variable-length strings separated by 0x50. | ABLE#NOT ABLE# | 2.28 | 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), ... | 2.29 | 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#... | 2.30 -| 27E77- | Trainer title names. | | YOUNGSTER#BUG CATCHER#LASS#... | 2.31 -| 34000- | Evolution and learnset data. | | | 2.32 -| 38000- | The basic properties and effects of moves. | 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. | 2.33 +| 27E77- | Trainer title names. | Variable-length names separated by 0x80. | YOUNGSTER#BUG CATCHER#LASS#... | 2.34 +| 34000- | | | | 2.35 +| 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. | 2.36 | 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. | | | 2.37 | 39462- | The Pok\eacute{}mon cry data. | Fixed-length (3 byte) descriptions of cries. | | 2.38 | 3B1E5- | Pointers to evolution/learnset data. | | | 2.39 +| 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. | | 2.40 | 40687- | Species data from the Pok\eacute{}dex: species name, height, weight, etc. | Fixed-length sequences of bytes. See below for specifics. | | 2.41 | 410B1- | A conversion table between internal order and Pokedex order. | | | 2.42 | 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]... | 2.43 @@ -41,13 +49,1156 @@ 2.44 | 7C249-7C2?? | Pointers to background music, pt II. | | | 2.45 | 98000- | Dialogue | | | 2.46 | B8000- | The text of each Pokemon's Pok\eacute{}dex entry. | | | 2.47 -| BC000- | Move names. | | | 2.48 +| BC000-BC60E | Move names. | Variable-length move names, separated by 0x80. The moves are in internal order. | POUND#KARATE CHOP#DOUBLESLAP#COMET PUNCH#... | 2.49 | 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♂#... | 2.50 | | | | | 2.51 | | | | | 2.52 2.53 + 2.54 + 2.55 + 2.56 +** COMMENT Getting linguistic data: names, words, etc. 2.57 + 2.58 +Some of the simplest data 2.59 + 2.60 + 2.61 +One of the simplest data structures in the Pok\eacute{} ROM is an 2.62 +unbroken list of strings that either (a) all have a specific length, 2.63 +or (b) are all separated by the same character. 2.64 + 2.65 +Because lots of good data has this format, we'll start by writing a 2.66 +template function to extract it: 2.67 + 2.68 +#+name: hxc-thunks 2.69 +#+begin_src clojure :results silent 2.70 +(defn hxc-thunk 2.71 + "Creates a thunk (nullary fn) that grabs data in a certain region of rom and 2.72 +splits it into a collection by 0x50. If rom is not supplied, uses the 2.73 + original rom data." 2.74 + [start length] 2.75 + (fn self 2.76 + ([rom] 2.77 + (take-nth 2 2.78 + (partition-by #(= % 0x50) 2.79 + (take length 2.80 + (drop start rom))))) 2.81 + ([] 2.82 + (self com.aurellem.gb.gb-driver/original-rom)))) 2.83 + 2.84 +(def hxc-thunk-words 2.85 + "Same as hxc-thunk, except it interprets the rom data as characters, 2.86 + returning a collection of strings." 2.87 + (comp 2.88 + (partial comp (partial map character-codes->str)) 2.89 + hxc-thunk)) 2.90 + 2.91 +#+end_src 2.92 + 2.93 +* Pok\eacute{}mon 2.94 +** Names of each species 2.95 +The names of the Pok\eacute{}mon species are stored in 2.96 +ROM@E8000. This name list is interesting, for a number of reasons: 2.97 +- The names are stored in [[ ][internal order]] rather than in the familiar 2.98 + Pok\eacute{}dex order. This seemingly random order probably represents the order in which the authors created or 2.99 + programmed in the Pok\eacute{}mon; it's used throughout the game. 2.100 +- There is enough space allocated for 190 Pok\eacute{}mon. As I 2.101 + understand it, there were originally going to be 190 Pok\eacute{}mon 2.102 + in Generation I, but the creators decided to defer some to 2.103 + Generation II. This explains why many Gen I and Gen II Pok\eacute{}mon 2.104 + have the same aesthetic feel. 2.105 +- The list is pockmarked with random gaps, due to the strange internal 2.106 + ordering 2.107 + and 39 unused spaces [fn::190 allocated spaces minus 151 true Pok\eacute{}mon]. These missing spaces are filled with the 2.108 + placeholder name, =MISSINGNO.= (\ldquo{}Missing number\rdquo{}). 2.109 + 2.110 +Each name is exactly ten letters long (Whenever a name is too short, the extra 2.111 +space is padded with the character 0x50). 2.112 + 2.113 + 2.114 + 2.115 +#+name: pokenames 2.116 +#+begin_src clojure 2.117 + 2.118 +(defn hxc-pokenames-raw 2.119 + "The hardcoded names of the 190 species in memory. List begins at 2.120 +ROM@E8000. Although names in memory are padded with 0x50 to be 10 characters 2.121 + long, these names are stripped of padding. See also, hxc-pokedex-names" 2.122 + ([] 2.123 + (hxc-pokenames-raw com.aurellem.gb.gb-driver/original-rom)) 2.124 + ([rom] 2.125 + (let [count-species 190 2.126 + name-length 10] 2.127 + (map character-codes->str 2.128 + (partition name-length 2.129 + (map #(if (= 0x50 %) 0x00 %) 2.130 + (take (* count-species name-length) 2.131 + (drop 0xE8000 2.132 + rom)))))))) 2.133 +(def hxc-pokenames 2.134 + (comp 2.135 + (partial map format-name) 2.136 + hxc-pokenames-raw)) 2.137 + 2.138 + 2.139 + 2.140 + 2.141 +(defn hxc-pokedex-names 2.142 + "The names of the pokemon in hardcoded pokedex order. List begins at 2.143 +ROM@410B1. See also, hxc-pokenames." 2.144 + ([] (hxc-pokedex-names 2.145 + com.aurellem.gb.gb-driver/original-rom)) 2.146 + ([rom] 2.147 + (let [names (hxc-pokenames rom)] 2.148 + (#(mapv % 2.149 + ((comp range count keys) %)) 2.150 + (zipmap 2.151 + (take (count names) 2.152 + (drop 0x410b1 rom)) 2.153 + 2.154 + names))))) 2.155 + 2.156 +#+end_src 2.157 + 2.158 * Appendices 2.159 ** Internal Pok\eacute{}mon IDs 2.160 ** Type IDs 2.161 + 2.162 +#+name: type-ids 2.163 +#+begin_src clojure 2.164 +(def pkmn-types 2.165 + [:normal ;;0 2.166 + :fighting ;;1 2.167 + :flying ;;2 2.168 + :poison ;;3 2.169 + :ground ;;4 2.170 + :rock ;;5 2.171 + :bird ;;6 2.172 + :bug ;;7 2.173 + :ghost ;;8 2.174 + :A 2.175 + :B 2.176 + :C 2.177 + :D 2.178 + :E 2.179 + :F 2.180 + :G 2.181 + :H 2.182 + :I 2.183 + :J 2.184 + :K 2.185 + :fire ;;20 (0x14) 2.186 + :water ;;21 (0x15) 2.187 + :grass ;;22 (0x16) 2.188 + :electric ;;23 (0x17) 2.189 + :psychic ;;24 (0x18) 2.190 + :ice ;;25 (0x19) 2.191 + :dragon ;;26 (0x1A) 2.192 + ]) 2.193 +#+end_src 2.194 + 2.195 ** Basic effects of moves 2.196 + 2.197 +*** Table of basic effects 2.198 + 2.199 +The possible effects of moves in Pok\eacute{}mon \mdash{} for example, dealing 2.200 +damage, leeching health, or potentially poisoning the opponent 2.201 +\mdash{} are stored in a table. Each move has exactly one effect, and 2.202 +different moves might have the same effect. 2.203 + 2.204 +For example, Leech Life, Mega Drain, and Absorb all have effect ID #3, which is \ldquo{}Leech half of the inflicted damage.\rdquo{} 2.205 + 2.206 +All the legitimate move effects are listed in the table 2.207 +below. Here are some notes for reading it: 2.208 + 2.209 +- Whenever an effect has a chance of doing something (like a chance of 2.210 + 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. 2.211 +- For some effects, the description is too cumbersome to 2.212 + write. Instead, I just write a move name 2.213 + in parentheses, like: (leech seed). That move gives a characteristic example 2.214 + of the effect. 2.215 +- I use the abbreviations =atk=, =def=, =spd=, =spc=, =acr=, =evd= for 2.216 + attack, defense, speed, special, accuracy, and evasion. 2.217 +. 2.218 + 2.219 + 2.220 + 2.221 +| ID (hex) | Description | Notes | 2.222 +|----------+-------------------------------------------------------------------------------------------------+------------------------------------------------------------------| 2.223 +| 0 | normal damage | | 2.224 +| 1 | no damage, just sleep | TODO: find out how many turns | 2.225 +| 2 | 0x4C chance of poison | | 2.226 +| 3 | leech half of inflicted damage | | 2.227 +| 4 | 0x19 chance of burn | | 2.228 +| 5 | 0x19 chance of freeze | | 2.229 +| 6 | 0x19 chance of paralysis | | 2.230 +| 7 | user faints; opponent's defense is halved during attack. | | 2.231 +| 8 | leech half of inflicted damage ONLY if the opponent is asleep | | 2.232 +| 9 | imitate last attack | | 2.233 +| A | user atk +1 | | 2.234 +| B | user def +1 | | 2.235 +| C | user spd +1 | | 2.236 +| D | user spc +1 | | 2.237 +| E | user acr +1 | This effect is unused. | 2.238 +| F | user evd +1 | | 2.239 +| 10 | get post-battle money = 2 * level * uses | | 2.240 +| 11 | move has 0xFE acr, regardless of battle stat modifications. | | 2.241 +| 12 | opponent atk -1 | | 2.242 +| 13 | opponent def -1 | | 2.243 +| 14 | opponent spd -1 | | 2.244 +| 15 | opponent spc -1 | | 2.245 +| 16 | opponent acr -1 | | 2.246 +| 17 | opponent evd -1 | | 2.247 +| 18 | converts user's type to opponent's. | | 2.248 +| 19 | (haze) | | 2.249 +| 1A | (bide) | | 2.250 +| 1B | (thrash) | | 2.251 +| 1C | (teleport) | | 2.252 +| 1D | (fury swipes) | | 2.253 +| 1E | attacks 2-5 turns | Unused. TODO: find out what it does. | 2.254 +| 1F | 0x19 chance of flinching | | 2.255 +| 20 | opponent sleep for 1-7 turns | | 2.256 +| 21 | 0x66 chance of poison | | 2.257 +| 22 | 0x4D chance of burn | | 2.258 +| 23 | 0x4D chance of freeze | | 2.259 +| 24 | 0x4D chance of paralysis | | 2.260 +| 25 | 0x4D chance of flinching | | 2.261 +| 26 | one-hit KO | | 2.262 +| 27 | charge one turn, atk next. | | 2.263 +| 28 | fixed damage, leaves 1HP. | Is the fixed damage the power of the move? | 2.264 +| 29 | fixed damage. | Like seismic toss, dragon rage, psywave. | 2.265 +| 2A | atk 2-5 turns; opponent can't attack | The odds of attacking for /n/ turns are: (0 0x60 0x60 0x20 0x20) | 2.266 +| 2B | charge one turn, atk next. (can't be hit when charging) | | 2.267 +| 2C | atk hits twice. | | 2.268 +| 2D | user takes 1 damage if misses. | | 2.269 +| 2E | evade status-lowering effects | Caused by you or also your opponent? | 2.270 +| 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. | 2.271 +| 30 | atk causes recoil dmg = 1/4 dmg dealt | | 2.272 +| 31 | confuses opponent | | 2.273 +| 32 | user atk +2 | | 2.274 +| 33 | user def +2 | | 2.275 +| 34 | user spd +2 | | 2.276 +| 35 | user spc +2 | | 2.277 +| 36 | user acr +2 | This effect is unused. | 2.278 +| 37 | user evd +2 | This effect is unused. | 2.279 +| 38 | restores up to half of user's max hp. | | 2.280 +| 39 | (transform) | | 2.281 +| 3A | opponent atk -2 | | 2.282 +| 3B | opponent def -2 | | 2.283 +| 3C | opponent spd -2 | | 2.284 +| 3D | opponent spc -2 | | 2.285 +| 3E | opponent acr -2 | | 2.286 +| 3F | opponent evd -2 | | 2.287 +| 40 | doubles user spc when attacked | | 2.288 +| 41 | doubles user def when attacked | | 2.289 +| 42 | just poisons opponent | | 2.290 +| 43 | just paralyzes opponent | | 2.291 +| 44 | 0x19 chance opponent atk -1 | | 2.292 +| 45 | 0x19 chance opponent def -1 | | 2.293 +| 46 | 0x19 chance opponent spd -1 | | 2.294 +| 47 | 0x4C chance opponent spc -1 | | 2.295 +| 48 | 0x19 chance opponent acr -1 | | 2.296 +| 49 | 0x19 chance opponent evd -1 | | 2.297 +| 4A | ??? | ;; unused? no effect? | 2.298 +| 4B | ??? | ;; unused? no effect? | 2.299 +| 4C | 0x19 chance of confusing the opponent | | 2.300 +| 4D | atk hits twice. 0x33 chance opponent poisioned. | | 2.301 +| 4E | broken. crash the game after attack. | | 2.302 +| 4F | (substitute) | | 2.303 +| 50 | unless opponent faints, user must recharge after atk. some exceptions apply | | 2.304 +| 51 | (rage) | | 2.305 +| 52 | (mimic) | | 2.306 +| 53 | (metronome) | | 2.307 +| 54 | (leech seed) | | 2.308 +| 55 | does nothing (splash) | | 2.309 +| 56 | (disable) | | 2.310 +#+end_src 2.311 + 2.312 +*** Source 2.313 +#+name: move-effects 2.314 +#+begin_src clojure 2.315 +(def move-effects 2.316 + ["normal damage" 2.317 + "no damage, just opponent sleep" ;; how many turns? is atk power ignored? 2.318 + "0x4C chance of poison" 2.319 + "leech half of inflicted damage" 2.320 + "0x19 chance of burn" 2.321 + "0x19 chance of freeze" 2.322 + "0x19 chance of paralyze" 2.323 + "user faints; opponent defense halved during attack." 2.324 + "leech half of inflicted damage ONLY if sleeping opponent." 2.325 + "imitate last attack" 2.326 + "user atk +1" 2.327 + "user def +1" 2.328 + "user spd +1" 2.329 + "user spc +1" 2.330 + "user acr +1" ;; unused?! 2.331 + "user evd +1" 2.332 + "get post-battle $ = 2*level*uses" 2.333 + "0xFE acr, no matter what." 2.334 + "opponent atk -1" ;; acr taken from move acr? 2.335 + "opponent def -1" ;; 2.336 + "opponent spd -1" ;; 2.337 + "opponent spc -1" ;; 2.338 + "opponent acr -1";; 2.339 + "opponent evd -1" 2.340 + "converts user's type to opponent's." 2.341 + "(haze)" 2.342 + "(bide)" 2.343 + "(thrash)" 2.344 + "(teleport)" 2.345 + "(fury swipes)" 2.346 + "attacks 2-5 turns" ;; unused? like rollout? 2.347 + "0x19 chance of flinch" 2.348 + "opponent sleep for 1-7 turns" 2.349 + "0x66 chance of poison" 2.350 + "0x4D chance of burn" 2.351 + "0x4D chance of freeze" 2.352 + "0x4D chance of paralyze" 2.353 + "0x4D chance of flinch" 2.354 + "one-hit KO" 2.355 + "charge one turn, atk next." 2.356 + "fixed damage, leaves 1HP." ;; how is dmg determined? 2.357 + "fixed damage." ;; cf seismic toss, dragon rage, psywave. 2.358 + "atk 2-5 turns; opponent can't attack" ;; unnormalized? (0 0x60 0x60 0x20 0x20) 2.359 + "charge one turn, atk next. (can't be hit when charging)" 2.360 + "atk hits twice." 2.361 + "user takes 1 damage if misses." 2.362 + "evade status-lowering effects" ;;caused by you or also your opponent? 2.363 + "(broken) if user is slower than opponent, makes critical hit impossible, otherwise has no effect" 2.364 + "atk causes recoil dmg = 1/4 dmg dealt" 2.365 + "confuses opponent" ;; acr taken from move acr 2.366 + "user atk +2" 2.367 + "user def +2" 2.368 + "user spd +2" 2.369 + "user spc +2" 2.370 + "user acr +2" ;; unused! 2.371 + "user evd +2" ;; unused! 2.372 + "restores up to half of user's max hp." ;; broken: fails if the difference 2.373 + ;; b/w max and current hp is one less than a multiple of 256. 2.374 + "(transform)" 2.375 + "opponent atk -2" 2.376 + "opponent def -2" 2.377 + "opponent spd -2" 2.378 + "opponent spc -2" 2.379 + "opponent acr -2" 2.380 + "opponent evd -2" 2.381 + "doubles user spc when attacked" 2.382 + "doubles user def when attacked" 2.383 + "just poisons opponent" ;;acr taken from move acr 2.384 + "just paralyzes opponent" ;; 2.385 + "0x19 chance opponent atk -1" 2.386 + "0x19 chance opponent def -1" 2.387 + "0x19 chance opponent spd -1" 2.388 + "0x4C chance opponent spc -1" ;; context suggest chance is 0x19 2.389 + "0x19 chance opponent acr -1" 2.390 + "0x19 chance opponent evd -1" 2.391 + "???" ;; unused? no effect? 2.392 + "???" ;; unused? no effect? 2.393 + "0x19 chance opponent confused" 2.394 + "atk hits twice. 0x33 chance opponent poisioned." 2.395 + "broken. crash the game after attack." 2.396 + "(substitute)" 2.397 + "unless opponent faints, user must recharge after atk. some 2.398 + exceptions apply." 2.399 + "(rage)" 2.400 + "(mimic)" 2.401 + "(metronome)" 2.402 + "(leech seed)" 2.403 + "does nothing (splash)" 2.404 + "(disable)" 2.405 + ]) 2.406 +#+end_src 2.407 + 2.408 + 2.409 ** Alphabet code 2.410 + 2.411 +#+begin_src clojure :tangle ../clojure/com/aurellem/gb/hxc.clj 2.412 + 2.413 +(ns com.aurellem.gb.hxc 2.414 + (:use (com.aurellem.gb assembly characters gb-driver util mem-util 2.415 + constants species)) 2.416 + (:import [com.aurellem.gb.gb_driver SaveState])) 2.417 + 2.418 + 2.419 + 2.420 + 2.421 +; ************* HANDWRITTEN CONSTANTS 2.422 + 2.423 +<<type-ids>> 2.424 + 2.425 + 2.426 +;; question: when status effects claim to take 2.427 +;; their accuracy from the move accuracy, does 2.428 +;; this mean that the move always "hits" but the 2.429 +;; status effect may not? 2.430 + 2.431 +<<move-effects>> 2.432 + 2.433 +;; ************** HARDCODED DATA 2.434 + 2.435 +<<hxc-thunks>> 2.436 +;; -------------------------------------------------- 2.437 + 2.438 + 2.439 +<<pokenames>> 2.440 + 2.441 +;; http://hax.iimarck.us/topic/581/ 2.442 +(defn hxc-cry 2.443 + "The pokemon cry data in internal order. List begins at ROM@39462" 2.444 + ([](hxc-cry com.aurellem.gb.gb-driver/original-rom)) 2.445 + ([rom] 2.446 + (zipmap 2.447 + (hxc-pokenames rom) 2.448 + (map 2.449 + (fn [[cry-id pitch length]] 2.450 + {:cry-id cry-id 2.451 + :pitch pitch 2.452 + :length length} 2.453 + ) 2.454 + (partition 3 2.455 + (drop 0x39462 rom)))))) 2.456 + 2.457 +(defn hxc-cry-groups 2.458 + ([] (hxc-cry-groups com.aurellem.gb.gb-driver/original-rom)) 2.459 + ([rom] 2.460 + (map #(mapv first 2.461 + (filter 2.462 + (fn [[k v]] 2.463 + (= % (:cry-id v))) 2.464 + (hxc-cry))) 2.465 + ((comp 2.466 + range 2.467 + count 2.468 + set 2.469 + (partial map :cry-id) 2.470 + vals 2.471 + hxc-cry) 2.472 + rom)))) 2.473 + 2.474 + 2.475 +(defn cry-conversion! 2.476 + "Convert Porygon's cry in ROM to be the cry of the given pokemon." 2.477 + [pkmn] 2.478 + (write-rom! 2.479 + (rewrite-memory 2.480 + (vec(rom)) 2.481 + 0x3965D 2.482 + (map second 2.483 + ((hxc-cry) pkmn))))) 2.484 + 2.485 +(def hxc-items-raw 2.486 + "The hardcoded names of the items in memory. List begins at 2.487 +ROM@045B7" 2.488 + (hxc-thunk-words 0x45B7 870)) 2.489 + 2.490 +(def hxc-types 2.491 + "The hardcoded type names in memory. List begins at ROM@27D99, 2.492 + shortly before hxc-titles." 2.493 + (hxc-thunk-words 0x27D99 102)) 2.494 + 2.495 +(def hxc-titles 2.496 + "The hardcoded names of the trainer titles in memory. List begins at 2.497 +ROM@27E77" 2.498 + (hxc-thunk-words 0x27E77 196)) 2.499 + 2.500 + 2.501 +(def hxc-pokedex-text-raw 2.502 + "The hardcoded pokedex entries in memory. List begins at 2.503 +ROM@B8000, shortly before move names." 2.504 + (hxc-thunk-words 0xB8000 14754)) 2.505 + 2.506 + 2.507 + 2.508 +(def hxc-items 2.509 + "The hardcoded names of the items in memory, presented as 2.510 + keywords. List begins at ROM@045B7. See also, hxc-items-raw." 2.511 + (comp (partial map format-name) hxc-items-raw)) 2.512 + 2.513 +(defn hxc-pokedex-text 2.514 + "The hardcoded pokedex entries in memory, presented as an 2.515 +associative hash map. List begins at ROM@B8000." 2.516 + ([] (hxc-pokedex-text com.aurellem.gb.gb-driver/original-rom)) 2.517 + ([rom] 2.518 + (zipmap 2.519 + (hxc-pokedex-names rom) 2.520 + (cons nil ;; for missingno. 2.521 + (hxc-pokedex-text-raw rom))))) 2.522 + 2.523 +;; In red/blue, pokedex stats are in internal order. 2.524 +;; In yellow, pokedex stats are in pokedex order. 2.525 + 2.526 +(defn hxc-pokedex-stats 2.527 + "The hardcoded pokedex stats (species height weight) in memory. List 2.528 +begins at ROM@40687" 2.529 + ([] (hxc-pokedex-stats com.aurellem.gb.gb-driver/original-rom)) 2.530 + ([rom] 2.531 + (let [pokedex-names (zipmap (range) (hxc-pokedex-names rom)) 2.532 + pkmn-count (count pokedex-names) 2.533 + ] 2.534 + ((fn capture-stats 2.535 + [n stats data] 2.536 + (if (zero? n) stats 2.537 + (let [[species 2.538 + [_ 2.539 + height-ft 2.540 + height-in 2.541 + weight-1 2.542 + weight-2 2.543 + _ 2.544 + dex-ptr-1 2.545 + dex-ptr-2 2.546 + dex-bank 2.547 + _ 2.548 + & data]] 2.549 + (split-with (partial not= 0x50) data)] 2.550 + (recur (dec n) 2.551 + (assoc stats 2.552 + (pokedex-names (- pkmn-count (dec n))) 2.553 + {:species 2.554 + (format-name (character-codes->str species)) 2.555 + :height-ft 2.556 + height-ft 2.557 + :height-in 2.558 + height-in 2.559 + :weight 2.560 + (/ (low-high weight-1 weight-2) 10.) 2.561 + 2.562 + ;; :text 2.563 + ;; (character-codes->str 2.564 + ;; (take-while 2.565 + ;; (partial not= 0x50) 2.566 + ;; (drop 2.567 + ;; (+ 0xB8000 2.568 + ;; -0x4000 2.569 + ;; (low-high dex-ptr-1 dex-ptr-2)) 2.570 + ;; rom))) 2.571 + }) 2.572 + 2.573 + data) 2.574 + 2.575 + 2.576 + ))) 2.577 + 2.578 + pkmn-count 2.579 + {} 2.580 + (drop 0x40687 rom))) )) 2.581 + 2.582 + 2.583 + 2.584 + 2.585 + 2.586 + 2.587 + 2.588 +(def hxc-places 2.589 + "The hardcoded place names in memory. List begins at 2.590 +ROM@71500. [Cinnabar] Mansion seems to be dynamically calculated." 2.591 + (hxc-thunk-words 0x71500 560)) 2.592 + 2.593 + 2.594 +(defn hxc-dialog 2.595 + "The hardcoded dialogue in memory, including in-game alerts. Dialog 2.596 + seems to be separated by 0x57 instead of 0x50 (END). Begins at ROM@98000." 2.597 + ([rom] 2.598 + (map character-codes->str 2.599 + (take-nth 2 2.600 + (partition-by #(= % 0x57) 2.601 + (take 0x0F728 2.602 + (drop 0x98000 rom)))))) 2.603 + ([] 2.604 + (hxc-dialog com.aurellem.gb.gb-driver/original-rom))) 2.605 + 2.606 + 2.607 +(def hxc-move-names 2.608 + "The hardcoded move names in memory. List begins at ROM@BC000" 2.609 + (hxc-thunk-words 0xBC000 1551)) 2.610 + 2.611 + 2.612 +(defn hxc-move-data 2.613 + "The hardcoded (basic (move effects)) in memory. List begins at 2.614 +0x38000. Returns a map of {:name :power :accuracy :pp :fx-id 2.615 + :fx-txt}. The move descriptions are handwritten, not hardcoded." 2.616 + ([] 2.617 + (hxc-move-data com.aurellem.gb.gb-driver/original-rom)) 2.618 + ([rom] 2.619 + (let [names (vec (hxc-move-names rom)) 2.620 + move-count (count names) 2.621 + move-size 6 2.622 + types pkmn-types ;;; !! hardcoded types 2.623 + ] 2.624 + (zipmap (map format-name names) 2.625 + (map 2.626 + (fn [[idx effect power type-id accuracy pp]] 2.627 + {:name (names (dec idx)) 2.628 + :power power 2.629 + :accuracy accuracy 2.630 + :pp pp 2.631 + :type (types type-id) 2.632 + :fx-id effect 2.633 + :fx-txt (get move-effects effect) 2.634 + } 2.635 + ) 2.636 + 2.637 + (partition move-size 2.638 + (take (* move-size move-count) 2.639 + (drop 0x38000 rom)))))))) 2.640 + 2.641 + 2.642 + 2.643 +(defn hxc-move-data* 2.644 + "Like hxc-move-data, but reports numbers as hexadecimal symbols instead." 2.645 + ([] 2.646 + (hxc-move-data* com.aurellem.gb.gb-driver/original-rom)) 2.647 + ([rom] 2.648 + (let [names (vec (hxc-move-names rom)) 2.649 + move-count (count names) 2.650 + move-size 6 2.651 + format-name (fn [s] 2.652 + (keyword (.toLowerCase 2.653 + (apply str 2.654 + (map #(if (= % \space) "-" %) s))))) 2.655 + ] 2.656 + (zipmap (map format-name names) 2.657 + (map 2.658 + (fn [[idx effect power type accuracy pp]] 2.659 + {:name (names (dec idx)) 2.660 + :power power 2.661 + :accuracy (hex accuracy) 2.662 + :pp pp 2.663 + :fx-id (hex effect) 2.664 + :fx-txt (get move-effects effect) 2.665 + } 2.666 + ) 2.667 + 2.668 + (partition move-size 2.669 + (take (* move-size move-count) 2.670 + (drop 0x38000 rom)))))))) 2.671 + 2.672 + 2.673 +(defn hxc-machines 2.674 + "The hardcoded moves taught by TMs and HMs. List begins at ROM@1232D." 2.675 + ([] (hxc-machines 2.676 + com.aurellem.gb.gb-driver/original-rom)) 2.677 + ([rom] 2.678 + (let [moves (hxc-move-names rom)] 2.679 + (zipmap 2.680 + (range) 2.681 + (take-while 2.682 + (comp not nil?) 2.683 + (map (comp 2.684 + format-name 2.685 + (zipmap 2.686 + (range) 2.687 + moves) 2.688 + dec) 2.689 + (take 100 2.690 + (drop 0x1232D rom)))))))) 2.691 + 2.692 + 2.693 + 2.694 +(defn internal-id 2.695 + ([rom] 2.696 + (zipmap 2.697 + (hxc-pokenames rom) 2.698 + (range))) 2.699 + ([] 2.700 + (internal-id com.aurellem.gb.gb-driver/original-rom))) 2.701 + 2.702 + 2.703 + 2.704 + 2.705 + 2.706 +;; nidoran gender change upon levelup 2.707 +;; (-> 2.708 +;; @current-state 2.709 +;; rom 2.710 +;; vec 2.711 +;; (rewrite-memory 2.712 +;; (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♂)) 2.713 +;; [1 1 15]) 2.714 +;; (rewrite-memory 2.715 +;; (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♀)) 2.716 +;; [1 1 3]) 2.717 +;; (write-rom!) 2.718 + 2.719 +;; ) 2.720 + 2.721 + 2.722 + 2.723 + 2.724 +(defn hxc-advantage 2.725 + ;; in-game multipliers are stored as 10x their effective value 2.726 + ;; to allow for fractional multipliers like 1/2 2.727 + 2.728 + "The hardcoded type advantages in memory, returned as tuples of 2.729 + atk-type def-type multiplier. By default (i.e. if not listed here), 2.730 +the multiplier is 1. List begins at 0x3E62D." 2.731 + ([] (hxc-advantage com.aurellem.gb.gb-driver/original-rom)) 2.732 + ([rom] 2.733 + (map 2.734 + (fn [[atk def mult]] [(get pkmn-types atk (hex atk)) 2.735 + (get pkmn-types def (hex def)) 2.736 + (/ mult 10)]) 2.737 + (partition 3 2.738 + (take-while (partial not= 0xFF) 2.739 + (drop 0x3E62D rom)))))) 2.740 + 2.741 + 2.742 + 2.743 +(defn format-evo 2.744 + "Parse a sequence of evolution data, returning a map. First is the 2.745 +method: 0 = end-evolution-data. 1 = level-up, 2 = item, 3 = trade. Next is an item id, if the 2.746 + method of evolution is by item (only stones will actually make pokemon 2.747 + evolve, for some auxillary reason.) Finally, the minimum level for 2.748 + evolution to occur (level 1 means no limit, which is used for trade 2.749 + and item evolutions), followed by the internal id of the pokemon 2.750 + into which to evolve. Hence, level up and trade evolutions are 2.751 + described with 3 2.752 + bytes; item evolutions with four." 2.753 + [coll] 2.754 + (let [method (first coll)] 2.755 + (cond (empty? coll) [] 2.756 + (= 0 method) [] ;; just in case 2.757 + (= 1 method) ;; level-up evolution 2.758 + (conj (format-evo (drop 3 coll)) 2.759 + {:method :level-up 2.760 + :min-level (nth coll 1) 2.761 + :into (dec (nth coll 2))}) 2.762 + 2.763 + (= 2 method) ;; item evolution 2.764 + (conj (format-evo (drop 4 coll)) 2.765 + {:method :item 2.766 + :item (dec (nth coll 1)) 2.767 + :min-level (nth coll 2) 2.768 + :into (dec (nth coll 3))}) 2.769 + 2.770 + (= 3 method) ;; trade evolution 2.771 + (conj (format-evo (drop 3 coll)) 2.772 + {:method :trade 2.773 + :min-level (nth coll 1) ;; always 1 for trade. 2.774 + :into (dec (nth coll 2))})))) 2.775 + 2.776 + 2.777 +(defn hxc-ptrs-evolve 2.778 + "A hardcoded collection of 190 pointers to alternating evolution/learnset data, 2.779 +in internal order." 2.780 + ([] 2.781 + (hxc-ptrs-evolve com.aurellem.gb.gb-driver/original-rom)) 2.782 + ([rom] 2.783 + (let [ 2.784 + pkmn-count (count (hxc-pokenames-raw)) ;; 190 2.785 + ptrs 2.786 + (map (fn [[a b]] (low-high a b)) 2.787 + (partition 2 2.788 + (take (* 2 pkmn-count) 2.789 + (drop 0x3b1e5 rom))))] 2.790 + (map (partial + 0x34000) ptrs) 2.791 + 2.792 + ))) 2.793 + 2.794 + 2.795 +(defn hxc-learnsets 2.796 + "Hardcoded map associating pokemon names to lists of pairs [lvl 2.797 + move] of abilities they learn as they level up. The data 2.798 +exists at ROM@34000, sorted by internal order. Pointers to the data 2.799 + exist at ROM@3B1E5; see also, hxc-ptrs-evolve" 2.800 + ([] (hxc-learnsets com.aurellem.gb.gb-driver/original-rom)) 2.801 + ([rom] 2.802 + (apply assoc 2.803 + {} 2.804 + (interleave 2.805 + (hxc-pokenames rom) 2.806 + (map (comp 2.807 + (partial map 2.808 + (fn [[lvl mv]] [lvl (dec mv)])) 2.809 + (partial partition 2) 2.810 + ;; keep the learnset data 2.811 + (partial take-while (comp not zero?)) 2.812 + ;; skip the evolution data 2.813 + rest 2.814 + (partial drop-while (comp not zero?))) 2.815 + (map #(drop % rom) 2.816 + (hxc-ptrs-evolve rom))))))) 2.817 + 2.818 +(defn hxc-learnsets-pretty 2.819 + "Live hxc-learnsets except it reports the name of each move --- as 2.820 +it appears in rom --- rather than the move index." 2.821 + ([] (hxc-learnsets-pretty com.aurellem.gb.gb-driver/original-rom)) 2.822 + ([rom] 2.823 + (let [moves (vec(map format-name (hxc-move-names)))] 2.824 + (into {} 2.825 + (map (fn [[pkmn learnset]] 2.826 + [pkmn (map (fn [[lvl mv]] [lvl (moves mv)]) 2.827 + learnset)]) 2.828 + (hxc-learnsets rom)))))) 2.829 + 2.830 + 2.831 + 2.832 + 2.833 +(defn hxc-evolution 2.834 + "Hardcoded evolution data in memory. The data exists at ROM@34000, 2.835 + sorted by internal order. Pointers to the data exist at ROM@3B1E5; see also, hxc-ptrs-evolve." 2.836 + ([] (hxc-evolution com.aurellem.gb.gb-driver/original-rom)) 2.837 + ([rom] 2.838 + (apply assoc {} 2.839 + (interleave 2.840 + (hxc-pokenames rom) 2.841 + (map 2.842 + (comp 2.843 + format-evo 2.844 + (partial take-while (comp not zero?)) 2.845 + #(drop % rom)) 2.846 + (hxc-ptrs-evolve rom) 2.847 + ))))) 2.848 + 2.849 +(defn hxc-evolution-pretty 2.850 + "Like hxc-evolution, except it uses the names of items and pokemon 2.851 +--- grabbed from ROM --- rather than their numerical identifiers." 2.852 + ([] (hxc-evolution-pretty com.aurellem.gb.gb-driver/original-rom)) 2.853 + ([rom] 2.854 + (let 2.855 + [poke-names (vec (hxc-pokenames rom)) 2.856 + item-names (vec (hxc-items rom)) 2.857 + use-names 2.858 + (fn [m] 2.859 + (loop [ks (keys m) new-map m] 2.860 + (let [k (first ks)] 2.861 + (cond (nil? ks) new-map 2.862 + (= k :into) 2.863 + (recur 2.864 + (next ks) 2.865 + (assoc new-map 2.866 + :into 2.867 + (poke-names 2.868 + (:into 2.869 + new-map)))) 2.870 + (= k :item) 2.871 + (recur 2.872 + (next ks) 2.873 + (assoc new-map 2.874 + :item 2.875 + (item-names 2.876 + (:item new-map)))) 2.877 + :else 2.878 + (recur 2.879 + (next ks) 2.880 + new-map) 2.881 + ))))] 2.882 + 2.883 + (into {} 2.884 + (map (fn [[pkmn evo-coll]] 2.885 + [pkmn (map use-names evo-coll)]) 2.886 + (hxc-evolution rom)))))) 2.887 + 2.888 + 2.889 +(defn hxc-pokemon-base 2.890 + ([] (hxc-pokemon-base com.aurellem.gb.gb-driver/original-rom)) 2.891 + ([rom] 2.892 + (let [entry-size 28 2.893 + pkmn-count (count (hxc-pokedex-text rom)) 2.894 + pokemon (rest (hxc-pokedex-names)) 2.895 + types (apply assoc {} 2.896 + (interleave 2.897 + (range) 2.898 + pkmn-types)) ;;!! softcoded 2.899 + moves (apply assoc {} 2.900 + (interleave 2.901 + (range) 2.902 + (map format-name 2.903 + (hxc-move-names rom)))) 2.904 + machines (hxc-machines) 2.905 + ] 2.906 + (zipmap 2.907 + pokemon 2.908 + (map 2.909 + (fn [[n 2.910 + rating-hp 2.911 + rating-atk 2.912 + rating-def 2.913 + rating-speed 2.914 + rating-special 2.915 + type-1 2.916 + type-2 2.917 + rarity 2.918 + rating-xp 2.919 + pic-dimensions ;; tile_width|tile_height (8px/tile) 2.920 + ptr-pic-obverse-1 2.921 + ptr-pic-obverse-2 2.922 + ptr-pic-reverse-1 2.923 + ptr-pic-reverse-2 2.924 + move-1 2.925 + move-2 2.926 + move-3 2.927 + move-4 2.928 + growth-rate 2.929 + & 2.930 + TMs|HMs]] 2.931 + (let 2.932 + [base-moves 2.933 + (mapv moves 2.934 + ((comp 2.935 + ;; since the game uses zero as a delimiter, 2.936 + ;; it must also increment all move indices by 1. 2.937 + ;; heren we decrement to correct this. 2.938 + (partial map dec) 2.939 + (partial take-while (comp not zero?))) 2.940 + [move-1 move-2 move-3 move-4])) 2.941 + 2.942 + types 2.943 + (set (list (types type-1) 2.944 + (types type-2))) 2.945 + TMs|HMs 2.946 + (map 2.947 + (comp 2.948 + (partial map first) 2.949 + (partial remove (comp zero? second))) 2.950 + (split-at 2.951 + 50 2.952 + (map vector 2.953 + (rest(range)) 2.954 + (reduce concat 2.955 + (map 2.956 + #(take 8 2.957 + (concat (bit-list %) 2.958 + (repeat 0))) 2.959 + 2.960 + TMs|HMs))))) 2.961 + 2.962 + TMs (vec (first TMs|HMs)) 2.963 + HMs (take 5 (map (partial + -50) (vec (second TMs|HMs)))) 2.964 + 2.965 + 2.966 + ] 2.967 + 2.968 + 2.969 + {:dex# n 2.970 + :base-moves base-moves 2.971 + :types types 2.972 + :TMs TMs 2.973 + :HMs HMs 2.974 + :base-hp rating-hp 2.975 + :base-atk rating-atk 2.976 + :base-def rating-def 2.977 + :base-speed rating-speed 2.978 + :base-special rating-special 2.979 + :o0 pic-dimensions 2.980 + :o1 ptr-pic-obverse-1 2.981 + :o2 ptr-pic-obverse-2 2.982 + })) 2.983 + 2.984 + (partition entry-size 2.985 + (take (* entry-size pkmn-count) 2.986 + (drop 0x383DE 2.987 + rom)))))))) 2.988 + 2.989 + 2.990 +(defn hxc-intro-pkmn 2.991 + "The hardcoded pokemon to display in Prof. Oak's introduction; the pokemon's 2.992 +internal id is stored at ROM@5EDB." 2.993 + ([] (hxc-intro-pkmn 2.994 + com.aurellem.gb.gb-driver/original-rom)) 2.995 + ([rom] 2.996 + (nth (hxc-pokenames rom) (nth rom 0x5EDB)))) 2.997 + 2.998 +(defn sxc-intro-pkmn! 2.999 + "Set the hardcoded pokemon to display in Prof. Oak's introduction." 2.1000 + [pokemon] 2.1001 + (write-rom! 2.1002 + (rewrite-rom 0x5EDB 2.1003 + [ 2.1004 + (inc 2.1005 + ((zipmap 2.1006 + (hxc-pokenames) 2.1007 + (range)) 2.1008 + pokemon))]))) 2.1009 + 2.1010 + 2.1011 +(defn hxc-item-prices 2.1012 + "The hardcoded list of item prices in memory. List begins at ROM@4495" 2.1013 + ([] (hxc-item-prices com.aurellem.gb.gb-driver/original-rom)) 2.1014 + ([rom] 2.1015 + (let [items (hxc-items rom) 2.1016 + price-size 3] 2.1017 + (zipmap items 2.1018 + (map (comp 2.1019 + ;; zero-cost items are "priceless" 2.1020 + #(if (zero? %) :priceless %) 2.1021 + decode-bcd butlast) 2.1022 + (partition price-size 2.1023 + (take (* price-size (count items)) 2.1024 + (drop 0x4495 rom)))))))) 2.1025 + 2.1026 +(defn hxc-shops 2.1027 + ([] (hxc-shops com.aurellem.gb.gb-driver/original-rom)) 2.1028 + ([rom] 2.1029 + (let [items (zipmap (range) (hxc-items rom)) 2.1030 + 2.1031 + ;; temporarily softcode the TM items 2.1032 + items (into 2.1033 + items 2.1034 + (map (juxt identity 2.1035 + (comp keyword 2.1036 + (partial str "tm-") 2.1037 + (partial + 1 -200) 2.1038 + )) 2.1039 + (take 200 (drop 200 (range))))) 2.1040 + 2.1041 + ] 2.1042 + 2.1043 + ((fn parse-shop [coll [num-items & items-etc]] 2.1044 + (let [inventory (take-while 2.1045 + (partial not= 0xFF) 2.1046 + items-etc) 2.1047 + [separator & items-etc] (drop num-items (rest items-etc))] 2.1048 + (if (= separator 0x50) 2.1049 + (map (partial mapv (comp items dec)) (conj coll inventory)) 2.1050 + (recur (conj coll inventory) items-etc) 2.1051 + ) 2.1052 + )) 2.1053 + 2.1054 + '() 2.1055 + (drop 0x233C rom)) 2.1056 + 2.1057 + 2.1058 + ))) 2.1059 + 2.1060 + 2.1061 + 2.1062 + 2.1063 + 2.1064 +(defn hxc-ptrs-wild 2.1065 + "A list of the hardcoded wild encounter data in memory. Pointers 2.1066 + begin at ROM@0CB95; data begins at ROM@0x04D89" 2.1067 + ([] (hxc-ptrs-wild com.aurellem.gb.gb-driver/original-rom)) 2.1068 + ([rom] 2.1069 + (let [ptrs 2.1070 + (map (fn [[a b]] (+ a (* 0x100 b))) 2.1071 + (take-while (partial not= (list 0xFF 0xFF)) 2.1072 + (partition 2 (drop 0xCB95 rom))))] 2.1073 + ptrs))) 2.1074 + 2.1075 + 2.1076 + 2.1077 +(defn hxc-wilds 2.1078 + "A list of the hardcoded wild encounter data in memory. Pointers 2.1079 + begin at ROM@0CB95; data begins at ROM@0x04D89" 2.1080 + ([] (hxc-wilds com.aurellem.gb.gb-driver/original-rom)) 2.1081 + ([rom] 2.1082 + (let [pokenames (zipmap (range) (hxc-pokenames rom))] 2.1083 + (map 2.1084 + (partial map (fn [[a b]] {:species (pokenames (dec b)) :level 2.1085 + a})) 2.1086 + (partition 10 2.1087 + 2.1088 + (take-while (comp (partial not= 1) 2.1089 + first) 2.1090 + (partition 2 2.1091 + (drop 0xCD8C rom)) 2.1092 + 2.1093 + )))))) 2.1094 + 2.1095 + 2.1096 + 2.1097 + 2.1098 + 2.1099 + 2.1100 + 2.1101 + 2.1102 + 2.1103 + 2.1104 + 2.1105 + 2.1106 + 2.1107 + 2.1108 +;; ********************** MANIPULATION FNS 2.1109 + 2.1110 + 2.1111 +(defn same-type 2.1112 + ([pkmn move] 2.1113 + (same-type 2.1114 + com.aurellem.gb.gb-driver/original-rom pkmn move)) 2.1115 + ([rom pkmn move] 2.1116 + (((comp :types (hxc-pokemon-base rom)) pkmn) 2.1117 + ((comp :type (hxc-move-data rom)) move)))) 2.1118 + 2.1119 + 2.1120 + 2.1121 + 2.1122 +(defn submap? 2.1123 + "Compares the two maps. Returns true if map-big has the same associations as map-small, otherwise false." 2.1124 + [map-small map-big] 2.1125 + (cond (empty? map-small) true 2.1126 + (and 2.1127 + (contains? map-big (ffirst map-small)) 2.1128 + (= (get map-big (ffirst map-small)) 2.1129 + (second (first map-small)))) 2.1130 + (recur (next map-small) map-big) 2.1131 + 2.1132 + :else false)) 2.1133 + 2.1134 + 2.1135 +(defn search-map [proto-map maps] 2.1136 + "Returns all the maps that make the same associations as proto-map." 2.1137 + (some (partial submap? proto-map) maps)) 2.1138 + 2.1139 +(defn filter-vals 2.1140 + "Returns a map consisting of all the pairs [key val] for 2.1141 + which (pred key) returns true." 2.1142 + [pred map] 2.1143 + (reduce (partial apply assoc) {} 2.1144 + (filter (fn [[k v]] (pred v)) map))) 2.1145 + 2.1146 + 2.1147 +(defn search-moves 2.1148 + "Returns a subcollection of all hardcoded moves with the 2.1149 + given attributes. Attributes consist of :name :power 2.1150 + :accuracy :pp :fx-id 2.1151 + (and also :fx-txt, but it contains the same information 2.1152 + as :fx-id)" 2.1153 + ([attribute-map] 2.1154 + (search-moves 2.1155 + com.aurellem.gb.gb-driver/original-rom attribute-map)) 2.1156 + ([rom attribute-map] 2.1157 + (filter-vals (partial submap? attribute-map) 2.1158 + (hxc-move-data rom)))) 2.1159 + 2.1160 + 2.1161 + 2.1162 + 2.1163 + 2.1164 +;; note: 0x2f31 contains the names "TM" "HM"? 2.1165 + 2.1166 +;; note for later: credits start at F1290 2.1167 + 2.1168 +;; note: DADB hyper-potion-hp _ _ _ super-potion-hp _ _ _ potion-hp ?? 2.1169 + 2.1170 +;; note: DD4D spells out pokemon vital stat names ("speed", etc.) 2.1171 + 2.1172 +;; note: 1195C-6A says ABLE#NOT ABLE#, but so does 119C0-119CE. 2.1173 +;; The first instance is for Machines; the second, for stones. 2.1174 + 2.1175 +;; 0x251A (in indexable mem): image decompression routine seems to begin here. 2.1176 + 2.1177 + 2.1178 +(comment 2.1179 + 2.1180 +(def hxc-later 2.1181 + "Running this code produces, e.g. hardcoded names NPCs give 2.1182 +their pokemon. Will sort through it later." 2.1183 +(print (character-codes->str(take 10000 2.1184 + (drop 0x71597 2.1185 + (rom (root))))))) 2.1186 + 2.1187 +(let [dex 2.1188 + (partition-by #(= 0x50 %) 2.1189 + (take 2540 2.1190 + (drop 0x40687 2.1191 + (rom (root)))))] 2.1192 + (def dex dex) 2.1193 + (def hxc-species 2.1194 + (map character-codes->str 2.1195 + (take-nth 4 dex)))) 2.1196 +) 2.1197 + 2.1198 + 2.1199 +#+end_src 2.1200 +