Mercurial > vba-clojure
comparison org/rom.org @ 419:4901ba2d3860
Figured out how NPC Pokemon teams are encoded.
author | Dylan Holmes <ocsenave@gmail.com> |
---|---|
date | Sat, 14 Apr 2012 05:20:28 -0500 |
parents | 543a78679971 |
children | acc3d1ad24e8 |
comparison
equal
deleted
inserted
replaced
416:21b8b3350b20 | 419:4901ba2d3860 |
---|---|
1 #+title: Notes on Deconstructing Pokemon Yellow | 1 #+title: Notes on Deconstructing Pokemon Yellow |
2 #+author: Dylan Holmes | 2 #+author: Dylan Holmes |
3 #+email: rlm@mit.edu | 3 #+email: rlm@mit.edu |
4 #+description: | 4 #+description: A detailed explication of Pok\eacute{}mon Yellow, helped by Clojure. |
5 #+keywords: | 5 #+keywords: pokemon, pokemon yellow, rom, gameboy, assembly, hex, pointers, clojure |
6 #+SETUPFILE: ../../aurellem/org/setup.org | 6 #+SETUPFILE: ../../aurellem/org/setup.org |
7 #+INCLUDE: ../../aurellem/org/level-0.org | 7 #+INCLUDE: ../../aurellem/org/level-0.org |
8 #+BABEL: :exports both :noweb yes :cache no :mkdirp yes | 8 #+BABEL: :exports both :noweb yes :cache no :mkdirp yes |
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 | 14 |
16 ** COMMENT Getting linguistic data: names, words, etc. | 15 ** COMMENT Getting linguistic data: names, words, etc. |
17 | 16 |
18 Some of the simplest data | 17 Some of the simplest data |
19 | 18 |
1009 | 1008 |
1010 | 1009 |
1011 | 1010 |
1012 ** COMMENT Status ailments | 1011 ** COMMENT Status ailments |
1013 | 1012 |
1013 | |
1014 * NPC Trainers | |
1015 | |
1016 ** Trainer Pok\eacute{}mon | |
1017 # http://hax.iimarck.us/topic/103/ | |
1018 There are two formats for specifying lists of NPC PPok\eacute{}mon: | |
1019 - If all the Pok\eacute{}mon will have the same level, the format is | |
1020 - Level (used for all the Pok\eacute{}mon) | |
1021 - Any number of Pok\eacute{}mon internal ids. | |
1022 - 0x00, to indicate end-of-list. | |
1023 - Otherwise, all the Pok\eacute{}mon will have their level | |
1024 specified. The format is | |
1025 - 0xFF, to indicate that we will be specifying the levels individually[fn::Because 0xFF is a | |
1026 forbidden level within the usual gameplay discipline, the game | |
1027 makers could safely use 0xFF as a mode indicator.]. | |
1028 - Any number of alternating Level/Pokemon pairs | |
1029 - 0x00, to indicate end-of-list. | |
1030 | |
1031 *** Get the pointers | |
1032 *** See the data | |
1033 #+begin_src clojure :exports both :results output | |
1034 (ns com.aurellem.gb.hxc | |
1035 (:use (com.aurellem.gb assembly characters gb-driver util mem-util | |
1036 constants)) | |
1037 (:import [com.aurellem.gb.gb_driver SaveState])) | |
1038 | |
1039 (->> | |
1040 (rom) | |
1041 (drop 0x39E2F) | |
1042 (take 21) | |
1043 (println)) | |
1044 | |
1045 | |
1046 (->> | |
1047 (rom) | |
1048 (drop 0x39E2F) | |
1049 (take 21) | |
1050 (partition-by zero?) | |
1051 (take-nth 2) | |
1052 (println)) | |
1053 | |
1054 | |
1055 | |
1056 (let | |
1057 [pokenames | |
1058 (zipmap | |
1059 (rest (range)) | |
1060 (hxc-pokenames-raw))] | |
1061 | |
1062 (->> | |
1063 (rom) | |
1064 (drop 0x39E2F) | |
1065 (take 21) ;; (1922 in all) | |
1066 (partition-by zero?) | |
1067 (take-nth 2) | |
1068 (map | |
1069 (fn parse-team [[mode & team]] | |
1070 (if (not= 0xFF mode) | |
1071 (mapv | |
1072 #(hash-map :level mode :species (pokenames %)) | |
1073 team) | |
1074 | |
1075 (mapv | |
1076 (fn [[lvl id]] (hash-map :level lvl :species (pokenames id))) | |
1077 (partition 2 team))))) | |
1078 | |
1079 (println))) | |
1080 | |
1081 | |
1082 | |
1083 #+end_src | |
1084 | |
1085 #+results: | |
1086 : (11 165 108 0 14 5 0 10 165 165 107 0 14 165 108 107 0 15 165 5 0) | |
1087 : ((11 165 108) (14 5) (10 165 165 107) (14 165 108 107) (15 165 5)) | |
1088 : ([{:species RATTATA, :level 11} {:species EKANS, :level 11}] [{:species SPEAROW, :level 14}] [{:species RATTATA, :level 10} {:species RATTATA, :level 10} {:species ZUBAT, :level 10}] [{:species RATTATA, :level 14} {:species EKANS, :level 14} {:species ZUBAT, :level 14}] [{:species RATTATA, :level 15} {:species SPEAROW, :level 15}]) | |
1089 | |
1014 * Places | 1090 * Places |
1015 ** Names of places | 1091 ** Names of places |
1016 | 1092 |
1017 #+name: places | 1093 #+name: places |
1018 #+begin_src clojure | 1094 #+begin_src clojure |
1019 (def hxc-places | 1095 (def hxc-places |
1020 "The hardcoded place names in memory. List begins at | 1096 "The hardcoded place names in memory. List begins at |
1021 ROM@71500. [Cinnabar] Mansion seems to be dynamically calculated." | 1097 ROM@71500. [Cinnabar/Cerulean] Mansion seems to be dynamically calculated." |
1022 (hxc-thunk-words 0x71500 560)) | 1098 (hxc-thunk-words 0x71500 560)) |
1023 | 1099 #+end_src |
1024 #+end_src | 1100 |
1101 *** See it work | |
1102 #+begin_src clojure :exports both :results output | |
1103 (println (hxc-places)) | |
1104 #+end_src | |
1105 | |
1106 #+results: | |
1107 : (PALLET TOWN VIRIDIAN CITY PEWTER CITY CERULEAN CITY LAVENDER TOWN VERMILION CITY CELADON CITY FUCHSIA CITY CINNABAR ISLAND INDIGO PLATEAU SAFFRON CITY ROUTE 1 ROUTE 2 ROUTE 3 ROUTE 4 ROUTE 5 ROUTE 6 ROUTE 7 ROUTE 8 ROUTE 9 ROUTE 10 ROUTE 11 ROUTE 12 ROUTE 13 ROUTE 14 ROUTE 15 ROUTE 16 ROUTE 17 ROUTE 18 SEA ROUTE 19 SEA ROUTE 20 SEA ROUTE 21 ROUTE 22 ROUTE 23 ROUTE 24 ROUTE 25 VIRIDIAN FOREST MT.MOON ROCK TUNNEL SEA COTTAGE S.S.ANNE [POKE]MON LEAGUE UNDERGROUND PATH [POKE]MON TOWER SEAFOAM ISLANDS VICTORY ROAD DIGLETT's CAVE ROCKET HQ SILPH CO. [0x4A] MANSION SAFARI ZONE) | |
1025 | 1108 |
1026 ** Wild Pok\eacute{}mon demographics | 1109 ** Wild Pok\eacute{}mon demographics |
1027 #+name: wilds | 1110 #+name: wilds |
1028 #+begin_src clojure | 1111 #+begin_src clojure |
1029 | 1112 |
1065 | 1148 |
1066 | 1149 |
1067 | 1150 |
1068 | 1151 |
1069 * Appendices | 1152 * Appendices |
1070 | |
1071 | |
1072 | |
1073 ** Mapping the ROM | 1153 ** Mapping the ROM |
1074 | 1154 |
1075 | ROM address (hex) | Description | Format | Example | | 1155 | ROM address (hex) | Description | Format | Example | |
1076 |-----------------------+-----------------+-----------------+-----------------| | 1156 |-----------------------+-----------------+-----------------+-----------------| |
1077 | | <15> | <15> | <15> | | 1157 | | <15> | <15> | <15> | |
1116 | 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. | | | | 1196 | 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. | | | |
1117 | 39462- | The Pok\eacute{}mon cry data. | Fixed-length (3 byte) descriptions of cries. | | | 1197 | 39462- | The Pok\eacute{}mon cry data. | Fixed-length (3 byte) descriptions of cries. | | |
1118 |-----------------------+-----------------+-----------------+-----------------| | 1198 |-----------------------+-----------------+-----------------+-----------------| |
1119 | 3997D-39B05 | Trainer titles (extended; see 27E77). This list includes strictly more trainers, seemingly at random inserted into the list from 27E77.[fn::The names added are in bold: YOUNGSTER, BUG CATCHER, LASS, *SAILOR*, JR TRAINER(m), JR TRAINER(f), POK\eacute{}MANIAC, SUPER NERD, *HIKER*, *BIKER*, BURGLAR, ENGINEER, JUGGLER, *FISHERMAN*, SWIMMER, *CUE BALL*, *GAMBLER*, BEAUTY, *PSYCHIC*, ROCKER, JUGGLER (again), *TAMER*, *BIRDKEEPER*, BLACKBELT, *RIVAL1*, PROF OAK, CHIEF, SCIENTIST, *GIOVANNI*, ROCKET, COOLTRAINER(m), COOLTRAINER(f), *BRUNO*, *BROCK*, *MISTY*, *LT. SURGE*, *ERIKA*, *KOGA*, *BLAINE*, *SABRINA*, *GENTLEMAN*, *RIVAL2*, *RIVAL3*, *LORELEI*, *CHANNELER*, *AGATHA*, *LANCE*.] | | | | 1199 | 3997D-39B05 | Trainer titles (extended; see 27E77). This list includes strictly more trainers, seemingly at random inserted into the list from 27E77.[fn::The names added are in bold: YOUNGSTER, BUG CATCHER, LASS, *SAILOR*, JR TRAINER(m), JR TRAINER(f), POK\eacute{}MANIAC, SUPER NERD, *HIKER*, *BIKER*, BURGLAR, ENGINEER, JUGGLER, *FISHERMAN*, SWIMMER, *CUE BALL*, *GAMBLER*, BEAUTY, *PSYCHIC*, ROCKER, JUGGLER (again), *TAMER*, *BIRDKEEPER*, BLACKBELT, *RIVAL1*, PROF OAK, CHIEF, SCIENTIST, *GIOVANNI*, ROCKET, COOLTRAINER(m), COOLTRAINER(f), *BRUNO*, *BROCK*, *MISTY*, *LT. SURGE*, *ERIKA*, *KOGA*, *BLAINE*, *SABRINA*, *GENTLEMAN*, *RIVAL2*, *RIVAL3*, *LORELEI*, *CHANNELER*, *AGATHA*, *LANCE*.] | | | |
1120 | 39B05-39DD0. | unknown | | | | 1200 | 39B05-39DD0. | unknown | | | |
1121 | 39DD1- | (?) Pointers to trainer Pok\eacute{}mon | | | | 1201 | 39DD1-39E2E | Pointers to trainer Pok\eacute{}mon | Pairs of low-high bits. | The first pair is 0x2F 0x5E, which corresponds to memory location 5E2F relative to this 38000-3C000 bank, i.e.[fn::For details about how relative bank pointers work, see the relevant Appendix.] position 39E2F overall. | |
1122 | 3A289-3A540 (approx) | Trainer Pok\eacute{}mon | Consecutive level/internal-id pairs (as with wild Pok\eacute{}mon; see 04D89) with irregular spacing \mdash{} the separators seem to have some metadata purpose. | The first entry is 0x05 0x66, representing level 5 Eevee (from your first battle in the game[fn::Incidentally, to change your rival's starter Pok\eacute{}mon, it's enough just to change its species in all of your battles with him.].) | | 1202 | 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.].) | |
1123 | 3B1E5-3B361 | Pointers to evolution/learnset data. | One high-low byte pair for each of the 190 Pok\eacute{}mon in internal order. | | | 1203 | 3B1E5-3B361 | Pointers to evolution/learnset data. | One high-low byte pair for each of the 190 Pok\eacute{}mon in internal order. | | |
1124 |-----------------------+-----------------+-----------------+-----------------| | 1204 |-----------------------+-----------------+-----------------+-----------------| |
1125 | 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. | | | 1205 | 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. | | |
1126 | 3BBAA-3C000 | (empty) | | 0 0 0 0 ... | | 1206 | 3BBAA-3C000 | (empty) | | 0 0 0 0 ... | |
1127 |-----------------------+-----------------+-----------------+-----------------| | 1207 |-----------------------+-----------------+-----------------+-----------------| |
1141 | 70442- | Play time/money | The text "PLAY TIME [0x50] MONEY" | | | 1221 | 70442- | Play time/money | The text "PLAY TIME [0x50] MONEY" | | |
1142 | 71500-7174B | Names of places. | Variable-length place names (strings), separated by 0x50. | PALLET TOWN#VIRIDIAN CITY#PEWTER CITY#CERULEAN CITY#... | | 1222 | 71500-7174B | Names of places. | Variable-length place names (strings), separated by 0x50. | PALLET TOWN#VIRIDIAN CITY#PEWTER CITY#CERULEAN CITY#... | |
1143 | 71C1E-71CAA (approx.) | Tradeable NPC Pok\eacute{}mon. | Internal ID, followed by nickname (11 chars; extra space padded by 0x50). Some of the Pokemon have unknown extra data around the id. | The first entry is [0x76] "GURIO######", corresponding to a Dugtrio named "GURIO". | | 1223 | 71C1E-71CAA (approx.) | Tradeable NPC Pok\eacute{}mon. | Internal ID, followed by nickname (11 chars; extra space padded by 0x50). Some of the Pokemon have unknown extra data around the id. | The first entry is [0x76] "GURIO######", corresponding to a Dugtrio named "GURIO". | |
1144 | 7C249-7C2?? | Pointers to background music, pt II. | | | | 1224 | 7C249-7C2?? | Pointers to background music, pt II. | | | |
1145 |-----------------------+-----------------+-----------------+-----------------| | 1225 |-----------------------+-----------------+-----------------+-----------------| |
1146 | 98000-B8000 | Dialogue and other messsages. | Variable-length strings. | | | 1226 | 98000-B7190 | Dialogue and other messsages. | Variable-length strings. | | |
1227 | B7190-B8000 | (empty space) | | 0 0 0 0 0 ... | | |
1147 | B8000-BC000 | The text of each Pok\eacute{}mon's Pok\eacute{}dex entry. | Variable-length descriptions (strings) in Pok\eacute{}dex order, separated by 0x50. These entries use the special characters *0x49* (new page), *0x4E* (new line), and *0x5F* (end entry). | The first entry (Bulbasaur's) is: "It can go for days [0x4E] without eating a [0x4E] single morsel. [0x49] In the bulb on [0x4E] its back, it [0x4E] stores energy [0x5F] [0x50]." | | 1228 | B8000-BC000 | The text of each Pok\eacute{}mon's Pok\eacute{}dex entry. | Variable-length descriptions (strings) in Pok\eacute{}dex order, separated by 0x50. These entries use the special characters *0x49* (new page), *0x4E* (new line), and *0x5F* (end entry). | The first entry (Bulbasaur's) is: "It can go for days [0x4E] without eating a [0x4E] single morsel. [0x49] In the bulb on [0x4E] its back, it [0x4E] stores energy [0x5F] [0x50]." | |
1148 | BC000-BC60E | Move names. | Variable-length move names, separated by 0x50. The moves are in internal order. | POUND#KARATE CHOP#DOUBLESLAP#COMET PUNCH#... | | 1229 | BC000-BC60F | Move names. | Variable-length move names, separated by 0x50. The moves are in internal order. | POUND#KARATE CHOP#DOUBLESLAP#COMET PUNCH#... | |
1230 | BC610-BD000 | (empty space) | | 0 0 0 0 0 ... | | |
1149 | E8000-E876C | Names of the \ldquo{}190\rdquo{} species of Pok\eacute{}mon in memory. | Fixed length (10-letter) Pok\eacute{}mon names. Any extra space is padded with the character 0x50. The names are in \ldquo{}internal order\rdquo{}. | RHYDON####KANGASKHANNIDORAN♂#... | | 1231 | E8000-E876C | Names of the \ldquo{}190\rdquo{} species of Pok\eacute{}mon in memory. | Fixed length (10-letter) Pok\eacute{}mon names. Any extra space is padded with the character 0x50. The names are in \ldquo{}internal order\rdquo{}. | RHYDON####KANGASKHANNIDORAN♂#... | |
1150 |-----------------------+-----------------+-----------------+-----------------| | 1232 |-----------------------+-----------------+-----------------+-----------------| |
1151 | E9BD5- | The text PLAY TIME (see above, 70442) | | | | 1233 | E9BD5- | The text PLAY TIME (see above, 70442) | | | |
1152 #+TBLFM: | 1234 #+TBLFM: |
1153 | 1235 |
1236 | |
1237 ** Understanding memory banks and pointers | |
1238 #+begin_src clojure | |
1239 | |
1240 (defn endian-flip | |
1241 "Flip the bytes of the two-byte number." | |
1242 [n] | |
1243 (assert (< n 0xFFFF)) | |
1244 (+ (* 0x100 (rem n 0x100)) | |
1245 (int (/ n 0x100)))) | |
1246 | |
1247 | |
1248 (defn offset->ptr | |
1249 "Convert an offset into a little-endian pointer." | |
1250 [n] | |
1251 (-> | |
1252 n | |
1253 (rem 0x10000) ;; take last four bytes | |
1254 (rem 0x4000) ;; get relative offset from the start of the bank | |
1255 (+ 0x4000) | |
1256 endian-flip)) | |
1257 | |
1258 (defn offset->bank | |
1259 "Get the bank of the offset." | |
1260 [n] | |
1261 (int (/ n 0x4000))) | |
1262 | |
1263 (defn ptr->offset | |
1264 "Convert a two-byte little-endian pointer into an offset." | |
1265 [bank ptr] | |
1266 (-> | |
1267 ptr | |
1268 endian-flip | |
1269 (- 0x4000) | |
1270 (+ (* 0x4000 bank)) | |
1271 )) | |
1272 | |
1273 (defn same-bank-offset | |
1274 "Convert a ptr into an absolute offset by using the bank of the reference." | |
1275 [reference ptr] | |
1276 (ptr->offset | |
1277 (offset->bank reference) | |
1278 ptr)) | |
1279 #+end_src | |
1154 | 1280 |
1155 | 1281 |
1156 ** Internal Pok\eacute{}mon IDs | 1282 ** Internal Pok\eacute{}mon IDs |
1157 ** Type IDs | 1283 ** Type IDs |
1158 | 1284 |
1661 reverse bit-list) | 1787 reverse bit-list) |
1662 | 1788 |
1663 (take 0xFFF (drop 0x8800 (memory state)))))) | 1789 (take 0xFFF (drop 0x8800 (memory state)))))) |
1664 | 1790 |
1665 | 1791 |
1666 (defn test-2 [] | 1792 ;; (defn test-2 [] |
1667 (loop [n 0 | 1793 ;; (loop [n 0 |
1668 pc-1 (pc-trail (-> state-defend (tick) (step [:a]) (step [:a]) (step []) (nstep 100)) 100000) | 1794 ;; pc-1 (pc-trail (-> state-defend (tick) (step [:a]) (step [:a]) (step []) (nstep 100)) 100000) |
1669 pc-2 (pc-trail (-> state-speed (tick) (step [:a]) (step [:a]) | 1795 ;; pc-2 (pc-trail (-> state-speed (tick) (step [:a]) (step [:a]) |
1670 (step []) (nstep 100)) 100000)] | 1796 ;; (step []) (nstep 100)) 100000)] |
1671 (cond (empty? (drop n pc-1)) [pc-1 n] | 1797 ;; (cond (empty? (drop n pc-1)) [pc-1 n] |
1672 (not= (take 10 (drop n pc-1)) (take 10 pc-2)) | 1798 ;; (not= (take 10 (drop n pc-1)) (take 10 pc-2)) |
1673 (recur pc-1 pc-2 (inc n)) | 1799 ;; (recur pc-1 pc-2 (inc n)) |
1674 :else | 1800 ;; :else |
1675 [(take 1000 pc-2) n]))) | 1801 ;; [(take 1000 pc-2) n]))) |
1676 | 1802 |
1677 | 1803 |
1678 | 1804 |
1679 | 1805 |
1680 (defn test-3 | 1806 (defn test-3 |
1681 "Explore trainer data" | 1807 "Explore trainer data" |
1682 [] | 1808 ([] (test-3 0x3A289)) |
1809 ([start] | |
1683 (let [pokenames (vec(hxc-pokenames-raw))] | 1810 (let [pokenames (vec(hxc-pokenames-raw))] |
1684 (println | 1811 (println |
1685 (reduce | 1812 (reduce |
1686 str | 1813 str |
1687 (map | 1814 (map |
1688 (fn [[lvl pkmn]] | 1815 (fn [[adr lvl pkmn]] |
1689 (str (format "%-11s %4d %02X %02X" | 1816 (str (format "%-11s %4d %02X %02X \t %05X\n" |
1817 | |
1690 (cond | 1818 (cond |
1691 (zero? lvl) "+" | 1819 (zero? lvl) "+" |
1692 (nil? (get pokenames (dec pkmn))) | 1820 (nil? (get pokenames (dec pkmn))) |
1693 "-" | 1821 "-" |
1694 :else | 1822 :else |
1695 (get pokenames (dec pkmn))) | 1823 (get pokenames (dec pkmn))) |
1696 lvl | 1824 lvl |
1697 pkmn | 1825 pkmn |
1698 lvl | 1826 lvl |
1699 ) "\n")) | 1827 adr |
1700 | 1828 ))) |
1701 (partition 2 | 1829 (map cons |
1702 (take 100;;703 | 1830 (take-nth 2 (drop start (range))) |
1703 (drop | 1831 (partition 2 |
1704 0x3A281 | 1832 (take 400;;703 |
1705 ;; 0x3A75D | 1833 (drop |
1706 (rom))))))))) | 1834 start |
1835 ;; 0x3A75D | |
1836 (rom))))))))))) | |
1707 | 1837 |
1708 (defn search-memory* [mem codes k] | 1838 (defn search-memory* [mem codes k] |
1709 (loop [index 0 | 1839 (loop [index 0 |
1710 index-next 1 | 1840 index-next 1 |
1711 start-match 0 | 1841 start-match 0 |