comparison org/rom.org @ 348:497ca041f5af

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