Mercurial > vba-clojure
changeset 474:9a20581477c2
merge dylan's changes.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 04 May 2012 06:18:48 -0500 |
parents | 396065930208 (current diff) 9a7fae5afd8f (diff) |
children | f28a3baa4c56 |
files | |
diffstat | 1 files changed, 182 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
1.1 --- a/org/rom.org Fri May 04 06:15:47 2012 -0500 1.2 +++ b/org/rom.org Fri May 04 06:18:48 2012 -0500 1.3 @@ -6,11 +6,30 @@ 1.4 #+SETUPFILE: ../../aurellem/org/setup.org 1.5 #+INCLUDE: ../../aurellem/org/level-0.org 1.6 #+BABEL: :exports both :noweb yes :cache no :mkdirp yes 1.7 +#+OPTIONS: num:2 1.8 + 1.9 1.10 # about map headers http://datacrystal.romhacking.net/wiki/Pokemon_Red/Blue:Notes 1.11 # map headers Yellow http://www.pokecommunity.com/archive/index.php/t-235311.html 1.12 # pokedollar: U+20B1 1.13 * Introduction 1.14 +This article contains the results of my investigations with 1.15 +Pok\eacute{}mon Yellow as I searched for interesting 1.16 +data in the ROM. By using the Clojure language interface 1.17 +written by Robert[fn::This Clojure interface will be published to aurellem.org soon.], I 1.18 +was able to interact with the game in real-time, sending commands and 1.19 +gathering data. The result is a manifestly accurate map of 1.20 +Pok\eacute{}mon Yellow; every result 1.21 +comes with runnable code that /works/. You can see the code and the output of 1.22 +every function and confirm for yourself that they are all correct. I 1.23 +hope you like the result! 1.24 + 1.25 +To orient yourself, you can look for a specific topic in the table of contents 1.26 +above, or browse the [[#sec-9-1][map of the ROM]], below. 1.27 + 1.28 + 1.29 +If you have any questions or comments, please e-mail =rlm@mit.edu=. 1.30 + 1.31 1.32 ** COMMENT Getting linguistic data: names, words, etc. 1.33 1.34 @@ -183,15 +202,15 @@ 1.35 rating-special 1.36 type-1 1.37 type-2 1.38 - rarity 1.39 - rating-xp 1.40 + rarity ;; catch rate 1.41 + rating-xp ;; base exp yield 1.42 pic-dimensions ;; tile_width|tile_height (8px/tile) 1.43 ptr-pic-obverse-1 1.44 ptr-pic-obverse-2 1.45 ptr-pic-reverse-1 1.46 ptr-pic-reverse-2 1.47 - move-1 1.48 - move-2 1.49 + move-1 ;; attacks known at level 0 [i.e. by default] 1.50 + move-2 ;; (0 for none) 1.51 move-3 1.52 move-4 1.53 growth-rate 1.54 @@ -510,6 +529,134 @@ 1.55 1.56 1.57 ** Pok\eacute{}mon cries 1.58 +*** See the data 1.59 + 1.60 +Here, you can see that each Pok\eacute{}mon's cry data consists of 1.61 +three bytes: the =cry-id=, which is the basic sound byte to use, the 1.62 +=pitch=, which determines how high or low to make the sound byte, and 1.63 +the =length=, which is the amount of the sound byte to play. 1.64 + 1.65 +Even though there are only a few different basic sound bytes (cry 1.66 +ids) to build from, by varying the pitch and length, 1.67 +you can create a wide variety of different Pok\eacute{}mon cries. 1.68 + 1.69 +#+begin_src clojure :exports both :cache no :results output 1.70 +(ns com.aurellem.gb.hxc 1.71 + (:use (com.aurellem.gb assembly characters gb-driver util mem-util 1.72 + constants)) 1.73 + (:import [com.aurellem.gb.gb_driver SaveState])) 1.74 + 1.75 +(->> 1.76 + (rom) 1.77 + (drop 0x39462) 1.78 + (take 12) 1.79 + (println)) 1.80 + 1.81 +(->> 1.82 + (rom) 1.83 + (drop 0x39462) 1.84 + (take 12) 1.85 + (partition 3) 1.86 + (map vec) 1.87 + (println)) 1.88 + 1.89 +(->> 1.90 + (rom) 1.91 + (drop 0x39462) 1.92 + (take 12) 1.93 + (partition 3) 1.94 + (map 1.95 + (fn [[id pitch length]] 1.96 + {:cry-id id :pitch pitch :length length})) 1.97 + (println)) 1.98 + 1.99 +#+end_src 1.100 + 1.101 +#+results: 1.102 +: (17 0 128 3 0 128 0 0 128 25 204 1) 1.103 +: ([17 0 128] [3 0 128] [0 0 128] [25 204 1]) 1.104 +: ({:cry-id 17, :pitch 0, :length 128} {:cry-id 3, :pitch 0, :length 128} {:cry-id 0, :pitch 0, :length 128} {:cry-id 25, :pitch 204, :length 1}) 1.105 + 1.106 + 1.107 +It is interesting to note which Pok\eacute{}mon use the same basic 1.108 +=cry-id= --- I call these /cry groups/. Here, you can see which 1.109 +Pok\eacute{}mon belong to the same cry group. 1.110 + 1.111 +#+begin_src clojure :exports both :cache no :results output 1.112 +(ns com.aurellem.gb.hxc 1.113 + (:use (com.aurellem.gb assembly characters gb-driver util mem-util 1.114 + constants)) 1.115 + (:import [com.aurellem.gb.gb_driver SaveState])) 1.116 + 1.117 +(println "POKEMON CRY GROUPS") 1.118 +(doall 1.119 + (map println 1.120 + (let [cry-id 1.121 + (->> 1.122 + (rom) 1.123 + (drop 0x39462) ;; get the cry data 1.124 + (partition 3) ;; partition it into groups of three 1.125 + (map first) ;; keep only the first item, the cry-id 1.126 + (zipmap (hxc-pokenames)) ;; associate each pokemon with its cry-id 1.127 + )] 1.128 + 1.129 + (->> (hxc-pokenames) ;; start with the list of pokemon 1.130 + (remove (partial = :missingno.)) ;; remove missingnos 1.131 + (sort-by cry-id) 1.132 + (partition-by cry-id) 1.133 + (map vec))))) 1.134 + 1.135 +#+end_src 1.136 + 1.137 +#+results: 1.138 +#+begin_example 1.139 +POKEMON CRY GROUPS 1.140 +[:nidoran♂ :sandshrew :sandslash :nidorino] 1.141 +[:nidoran♀ :nidorina] 1.142 +[:slowpoke] 1.143 +[:kangaskhan] 1.144 +[:rhyhorn :magmar :charmander :charmeleon :charizard] 1.145 +[:grimer :snorlax] 1.146 +[:voltorb :electabuzz :electrode] 1.147 +[:gengar :muk] 1.148 +[:marowak :oddish :gloom] 1.149 +[:nidoking :moltres :articuno :raichu] 1.150 +[:nidoqueen :mankey :primeape] 1.151 +[:exeggcute :diglett :doduo :dodrio :dugtrio] 1.152 +[:lickitung :hitmonchan :seel :dewgong] 1.153 +[:exeggutor :drowzee :jynx :hypno] 1.154 +[:pidgey :poliwag :ditto :jigglypuff :wigglytuff :poliwhirl :poliwrath] 1.155 +[:ivysaur :dragonite :pikachu :dratini :dragonair :bulbasaur :venusaur] 1.156 +[:spearow :farfetch'd] 1.157 +[:rhydon] 1.158 +[:tangela :hitmonlee :golem :koffing :weezing] 1.159 +[:blastoise :kakuna :beedrill] 1.160 +[:pinsir :chansey :pidgeotto :pidgeot] 1.161 +[:arcanine :weedle] 1.162 +[:scyther :kabuto :caterpie :butterfree :goldeen :seaking] 1.163 +[:gyarados :onix :arbok :ekans :magikarp] 1.164 +[:shellder :fearow :zapdos :kabutops :cloyster] 1.165 +[:clefairy :cubone :meowth :horsea :seadra :clefable :persian] 1.166 +[:tentacool :venonat :eevee :flareon :jolteon :vaporeon :venomoth :tentacruel] 1.167 +[:lapras] 1.168 +[:gastly :kadabra :magneton :metapod :haunter :abra :alakazam :magnemite] 1.169 +[:tauros :zubat :golbat :squirtle :wartortle] 1.170 +[:mew :staryu :parasect :paras :mewtwo :starmie] 1.171 +[:slowbro :growlithe :machoke :omanyte :omastar :machop :machamp] 1.172 +[:mr.mime :krabby :kingler] 1.173 +[:psyduck :golduck :bellsprout] 1.174 +[:rattata :raticate] 1.175 +[:aerodactyl :vileplume] 1.176 +[:graveler :vulpix :ninetales :geodude] 1.177 +[:ponyta :rapidash :porygon :weepinbell :victreebel] 1.178 +#+end_example 1.179 + 1.180 + 1.181 + 1.182 + 1.183 + 1.184 + 1.185 +*** Automatically grab the data 1.186 #+name: pokecry 1.187 #+begin_src clojure 1.188 (defn hxc-cry 1.189 @@ -783,8 +930,8 @@ 1.190 1.191 ;;; TYPE EFFECTIVENESS 1.192 1.193 -(println (take 15 (drop 0x3E62D (rom)))) 1.194 -(println (partition 3 (take 15 (drop 0x3E62D (rom))))) 1.195 +(println (take 15 (drop 0x3E5FA (rom)))) 1.196 +(println (partition 3 (take 15 (drop 0x3E5FA (rom))))) 1.197 1.198 (println 1.199 (map 1.200 @@ -792,7 +939,7 @@ 1.201 (list atk-type def-type (/ multiplier 10.))) 1.202 1.203 (partition 3 1.204 - (take 15 (drop 0x3E62D (rom)))))) 1.205 + (take 15 (drop 0x3E5FA (rom)))))) 1.206 1.207 1.208 (println 1.209 @@ -805,7 +952,7 @@ 1.210 ]) 1.211 1.212 (partition 3 1.213 - (take 15 (drop 0x3E62D (rom)))))) 1.214 + (take 15 (drop 0x3E5FA (rom)))))) 1.215 1.216 #+end_src 1.217 1.218 @@ -813,10 +960,10 @@ 1.219 : [:normal :fighting :flying :poison :ground :rock :bird :bug :ghost :A :B :C :D :E :F :G :H :I :J :K :fire :water :grass :electric :psychic :ice :dragon] 1.220 : ([0 :normal] [1 :fighting] [2 :flying] [3 :poison] [4 :ground] [5 :rock] [6 :bird] [7 :bug] [8 :ghost] [9 :A] [10 :B] [11 :C] [12 :D] [13 :E] [14 :F] [15 :G] [16 :H] [17 :I] [18 :J] [19 :K] [20 :fire] [21 :water] [22 :grass] [23 :electric] [24 :psychic] [25 :ice] [26 :dragon]) 1.221 : 1.222 -: (0 5 5 0 8 0 8 8 20 20 7 20 20 5 5) 1.223 -: ((0 5 5) (0 8 0) (8 8 20) (20 7 20) (20 5 5)) 1.224 -: ((0 5 0.5) (0 8 0.0) (8 8 2.0) (20 7 2.0) (20 5 0.5)) 1.225 -: ([:normal :rock 0.5] [:normal :ghost 0.0] [:ghost :ghost 2.0] [:fire :bug 2.0] [:fire :rock 0.5]) 1.226 +: (21 20 20 20 22 20 20 25 20 22 21 20 23 21 20) 1.227 +: ((21 20 20) (20 22 20) (20 25 20) (22 21 20) (23 21 20)) 1.228 +: ((21 20 2.0) (20 22 2.0) (20 25 2.0) (22 21 2.0) (23 21 2.0)) 1.229 +: ([:water :fire 2.0] [:fire :grass 2.0] [:fire :ice 2.0] [:grass :water 2.0] [:electric :water 2.0]) 1.230 1.231 1.232 *** 1.233 @@ -838,11 +985,12 @@ 1.234 (/ mult 10)]) 1.235 (partition 3 1.236 (take-while (partial not= 0xFF) 1.237 - (drop 0x3E62D rom)))))) 1.238 + (drop 0x3E5FA rom)))))) 1.239 #+end_src 1.240 1.241 1.242 1.243 + 1.244 * Moves 1.245 ** Names of moves 1.246 *** See the data 1.247 @@ -1110,11 +1258,10 @@ 1.248 #+name: wilds 1.249 #+begin_src clojure 1.250 1.251 - 1.252 - 1.253 +;; 0x0489, relative to 0xCB95, points to 0xCD89. 1.254 (defn hxc-ptrs-wild 1.255 "A list of the hardcoded wild encounter data in memory. Pointers 1.256 - begin at ROM@0CB95; data begins at ROM@0x04D89" 1.257 + begin at ROM@0CB95; data begins at ROM@0x0CD89" 1.258 ([] (hxc-ptrs-wild com.aurellem.gb.gb-driver/original-rom)) 1.259 ([rom] 1.260 (let [ptrs 1.261 @@ -1127,19 +1274,20 @@ 1.262 1.263 (defn hxc-wilds 1.264 "A list of the hardcoded wild encounter data in memory. Pointers 1.265 - begin at ROM@0CB95; data begins at ROM@0x04D89" 1.266 + begin at ROM@0CB95; data begins at ROM@0x0CD89" 1.267 ([] (hxc-wilds com.aurellem.gb.gb-driver/original-rom)) 1.268 ([rom] 1.269 (let [pokenames (zipmap (range) (hxc-pokenames rom))] 1.270 (map 1.271 - (partial map (fn [[a b]] {:species (pokenames (dec b)) :level 1.272 - a})) 1.273 - (partition 10 1.274 - 1.275 - (take-while (comp (partial not= 1) 1.276 - first) 1.277 - (partition 2 1.278 - (drop 0xCD8C rom)) 1.279 + (partial map 1.280 + (fn [[a b]] 1.281 + {:species (pokenames (dec b)) 1.282 + :level a})) 1.283 + (partition 10 1.284 + (take-while 1.285 + (comp (partial not= 1) first) 1.286 + (partition 2 1.287 + (drop 0xCD8C rom)) 1.288 1.289 )))))) 1.290 1.291 @@ -1265,7 +1413,6 @@ 1.292 | 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. | 1.293 | 04524-04527 | (unconfirmed) possibly the bike price in Cerulean. | | | 1.294 | 045B7-0491E | Names of the items in memory. | Variable-length item names (strings of character codes). Names are separated by a single 0x50 character. | MASTER BALL#ULTRA BALL#... | 1.295 -| 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). | 1.296 |-----------------------+-----------------+-----------------+-----------------| 1.297 | 05DD2-05DF2 | Menu text for player info. | | PLAYER [newline] BADGES [nelwine] POK\Eacute{}DEX [newline] TIME [0x50] | 1.298 | 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. | 1.299 @@ -1277,7 +1424,8 @@ 1.300 | 7635- | Menu options for selected Pok\eacute{}mon (Includes names of out-of-battle moves). | Variable-length strings separated by 0x50. | CUT [0x50] FLY [0x50] SURF [0x50] STRENGTH [0x50] FLASH [0x50] DIG [0x50] TELEPORT [0x50] SOFTBOILED [0x50] STATS [newline] SWITCH [newline] CANCEL [0x50] | 1.301 | 7AF0-8000 | (empty space) | | 0 0 0 0 0 ... | 1.302 | 0822E-082F? | Pointers to background music, part I. | | | 1.303 -| 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). | 1.304 +| 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 relative to this memory bank, i.e. absolute address 0xCD89, the location of the first list of wild Pok\eacute{}mon. (For details on pointer addresses, see the relevant appendix.) | 1.305 +| 0CD89- | Lists of wild Pok\eacute{}mon to encounter in each region. | Lists of 12 bytes. First, an encounter rate[fn::I suspect this is an amount out of 256.]. Next, ten alternating Pok\eacute{}mon/level pairs. Each list ends with 0x00. If the encounter rate is zero, the list ends immediately. | The first nonempty list (located at ROM@0CD8B) is (25; 3 36 4 36 2 165 3 165 2 36 3 36 5 36 4 165 6 36 7 36; 0), i.e. 25 encounter rate; 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, 0 (i.e., end-of-list). | 1.306 |-----------------------+-----------------+-----------------+-----------------| 1.307 | 0DACB. | Amount of HP restored by Soda Pop | The HP consists of a single numerical byte. | 60 | 1.308 | 0DACF. | Amount of HP restored by Lemonade | " | 80 | 1.309 @@ -1323,7 +1471,7 @@ 1.310 | 39E2F-3A5B2 | Trainer Pok\eacute{}mon | Specially-formatted lists of various length, separated by 0x00. If the list starts with 0xFF, the rest of the list will alternate between levels and internal-ids. Otherwise, start of the list is the level of the whole team, and the rest of the list is internal-ids. | The first entry is (11 165 108 0), which means a level 11 team consisting of Rattata and Ekans. The entry for MISTY is (255 18 27 21 152 0), which means a team of various levels consisting of level 18 Staryu and level 21 Starmie. [fn::Incidentally, if you want to change your rival's starter Pok\eacute{}mon, it's enough just to change its species in all of your battles with him.].) | 1.311 | 3B1E5-3B361 | Pointers to evolution/learnset data. | One high-low byte pair for each of the 190 Pok\eacute{}mon in internal order. | | 1.312 |-----------------------+-----------------+-----------------+-----------------| 1.313 -| 3B361-3BBAA | Evolution and learnset data. [fn::Evolution data consists of how to make Pok\eacute{}mon evolve, and what they evolve into. Learnset data consists of the moves that Pok\eacute{}mon learn as they level up.] | Variable-length evolution information (see below), followed by a list of level/move-id learnset pairs. | | 1.314 +| 3B361-3BBAA | *Evolution and learnset data*. [fn::Evolution data consists of how to make Pok\eacute{}mon evolve, and what they evolve into. Learnset data consists of the moves that Pok\eacute{}mon learn as they level up.] | Variable-length evolution information (see below), followed by a list of level/move-id learnset pairs. | | 1.315 | 3BBAA-3C000 | (empty) | | 0 0 0 0 ... | 1.316 |-----------------------+-----------------+-----------------+-----------------| 1.317 | 3D131-3D133 | The inventory of both OLD MAN and PROF. OAK when they battle for you. | Pairs of [item-id quantity], terminated by 0xFF. | (0x04 0x01 0xFF) They only have one Pok\eacute{}ball [fn::If you give them any ball, OAK will catch the enemy Pok\eacute{}mon and OLD MAN will miss. (OLD MAN misses even if he throws a MASTER BALL, which is a sight to see!) If you give them some other item first in the list, you'll be able to use that item normally but then you'll trigger the Safari Zone message: Pa will claim you're out of SAFARI BALLs and the battle will end. If you engage in either an OLD MAN or OAK battle with a Gym Leader, you will [1] get reprimanded if you try to throw a ball [2] incur the Safari Zone message [3] automatically win no matter which item you use [4] earn whichever reward they give you as usual [5] permanently retain the name OLD MAN / PROF. OAK.]. | 1.318 @@ -1331,6 +1479,7 @@ 1.319 | 3E190-3E194 | Which moves have an increased critical-hit ratio? | List of move ids, terminated by 0xFF. | (0x02 0x4B 0x98 0xA3 0xFF) corresponding to karate-chop, razor-leaf, crabhammer, slash, end-of-list. | 1.320 | 3E200-3E204 | " (???) | " | " | 1.321 | 3E231. | Besides normal-type, which type of move can COUNTER counter? | A single byte representing a type id. | This is set to 1, the id of the FIGHTING type. | 1.322 +| 3E5FA-3E6F0. | *Type effectiveness* | Triples of bytes: =atk-type=, =def-type=, =multiplier=. The multiplier is stored as 10x its actual value to allow for fractions; so, 20 means 2.0x effective, 5 means 0.5x effective. Unlisted type combinations have 1.0x effectiveness by default. | The first few entries are (21 20 20) (20 22 20) (20 25 20) (22 21 20) (23 21 20), corresponding to [:water :fire 2.0] [:fire :grass 2.0] [:fire :ice 2.0] | 1.323 |-----------------------+-----------------+-----------------+-----------------| 1.324 | 40252-4027B | Pok\eacute{}dex menu text | Variable-length strings separated by 0x50. | SEEN#OWN#CONTENTS#... | 1.325 | 40370-40386 | Important constants for Pok\eacute{}dex entries | | HT _ _ *?′??″* [newline] WT _ _ _ *???* lb [0x50] *POK\Eacute{}* [0x50] | 1.326 @@ -1373,6 +1522,11 @@ 1.327 0x5C36B 1.328 0x7562E 1.329 1.330 +Find GivePokemon 1.331 +(search-memory* (vec(rom)) [120 234 \_ \_ 121 234 \_ \_ 175 234 \_ \_ 6] 10) 1.332 + 1.333 +F4011 : ASM script for asking if it's oak battle 1.334 + 1.335 1.336 ** Understanding memory banks and pointers 1.337 #+begin_src clojure