rlm@218
|
1 (ns com.aurellem.gb.hxc
|
rlm@218
|
2 (:use (com.aurellem.gb assembly characters gb-driver util
|
rlm@218
|
3 constants))
|
rlm@218
|
4 (:use (com.aurellem.world practice))
|
rlm@218
|
5 (:import [com.aurellem.gb.gb_driver SaveState]))
|
rlm@218
|
6
|
rlm@218
|
7
|
ocsenave@243
|
8
|
ocsenave@249
|
9
|
ocsenave@249
|
10 ; ************* HANDWRITTEN CONSTANTS
|
ocsenave@249
|
11
|
ocsenave@243
|
12 (def pkmn-types
|
ocsenave@244
|
13 [:normal
|
ocsenave@244
|
14 :fighting
|
ocsenave@244
|
15 :flying
|
ocsenave@244
|
16 :poison
|
ocsenave@244
|
17 :ground
|
ocsenave@244
|
18 :rock
|
ocsenave@245
|
19 :bird
|
ocsenave@244
|
20 :bug
|
ocsenave@244
|
21 :ghost
|
ocsenave@244
|
22 :A
|
ocsenave@244
|
23 :B
|
ocsenave@244
|
24 :C
|
ocsenave@244
|
25 :D
|
ocsenave@244
|
26 :E
|
ocsenave@244
|
27 :F
|
ocsenave@244
|
28 :G
|
ocsenave@244
|
29 :H
|
ocsenave@244
|
30 :I
|
ocsenave@244
|
31 :J
|
ocsenave@244
|
32 :K
|
ocsenave@244
|
33 :fire
|
ocsenave@244
|
34 :water
|
ocsenave@244
|
35 :grass
|
ocsenave@244
|
36 :electric
|
ocsenave@244
|
37 :psychic
|
ocsenave@244
|
38 :ice
|
ocsenave@244
|
39 :dragon
|
ocsenave@244
|
40 ])
|
ocsenave@243
|
41
|
ocsenave@243
|
42
|
ocsenave@246
|
43 ;; question: when status effects claim to take
|
ocsenave@246
|
44 ;; their accuracy from the move accuracy, does
|
ocsenave@246
|
45 ;; this mean that the move always "hits" but the
|
ocsenave@246
|
46 ;; status effect may not?
|
ocsenave@246
|
47
|
ocsenave@246
|
48 (def move-effects
|
ocsenave@246
|
49 ["normal damage"
|
ocsenave@246
|
50 "no damage, just opponent sleep" ;; how many turns? is atk power ignored?
|
ocsenave@246
|
51 "0x4C chance of poison"
|
ocsenave@246
|
52 "leech half of inflicted damage"
|
ocsenave@246
|
53 "0x19 chance of burn"
|
ocsenave@246
|
54 "0x19 chance of freeze"
|
ocsenave@246
|
55 "0x19 chance of paralyze"
|
ocsenave@246
|
56 "user faints; opponent defense halved."
|
ocsenave@246
|
57 "leech half of inflicted damage ONLY if sleeping opponent."
|
ocsenave@246
|
58 "imitate last attack"
|
ocsenave@246
|
59 "user atk +1"
|
ocsenave@246
|
60 "user def +1"
|
ocsenave@246
|
61 "user spd +1"
|
ocsenave@246
|
62 "user spc +1"
|
ocsenave@246
|
63 "user acr +1" ;; unused?!
|
ocsenave@246
|
64 "user evd +1"
|
ocsenave@246
|
65 "get post-battle $ = 2*level*uses"
|
ocsenave@246
|
66 "0xFE acr, no matter what."
|
ocsenave@246
|
67 "opponent atk -1" ;; acr taken from move acr?
|
ocsenave@246
|
68 "opponent def -1" ;;
|
ocsenave@246
|
69 "opponent spd -1" ;;
|
ocsenave@246
|
70 "opponent spc -1" ;;
|
ocsenave@246
|
71 "opponent acr -1";;
|
ocsenave@246
|
72 "opponent evd -1"
|
ocsenave@246
|
73 "converts user's type to opponent's."
|
ocsenave@246
|
74 "(haze)"
|
ocsenave@246
|
75 "(bide)"
|
ocsenave@246
|
76 "(thrash)"
|
ocsenave@246
|
77 "(teleport)"
|
ocsenave@246
|
78 "(fury swipes)"
|
ocsenave@246
|
79 "attacks 2-5 turns" ;; unused? like rollout?
|
ocsenave@246
|
80 "0x19 chance of flinch"
|
ocsenave@246
|
81 "opponent sleep for 1-7 turns"
|
ocsenave@246
|
82 "0x66 chance of poison"
|
ocsenave@246
|
83 "0x4D chance of burn"
|
ocsenave@246
|
84 "0x4D chance of freeze"
|
ocsenave@246
|
85 "0x4D chance of paralyze"
|
ocsenave@246
|
86 "0x4D chance of flinch"
|
ocsenave@246
|
87 "one-hit KO"
|
ocsenave@246
|
88 "charge one turn, atk next."
|
ocsenave@246
|
89 "fixed damage, leaves 1HP." ;; how is dmg determined?
|
ocsenave@246
|
90 "fixed damage." ;; cf seismic toss, dragon rage, psywave.
|
ocsenave@246
|
91 "atk 2-5 turns; opponent can't attack" ;; unnormalized? (0 0x60 0x60 0x20 0x20)
|
ocsenave@246
|
92 "charge one turn, atk next. (can't be hit when charging)"
|
ocsenave@246
|
93 "atk hits twice."
|
ocsenave@246
|
94 "user takes 1 damage if misses."
|
ocsenave@246
|
95 "evade status-lowering effects" ;;caused by you or also your opponent?
|
ocsenave@246
|
96 "(broken) if user is slower than opponent, makes critical hit impossible, otherwise has no effect"
|
ocsenave@246
|
97 "atk causes recoil dmg = 1/4 dmg dealt"
|
ocsenave@246
|
98 "confuses opponent" ;; acr taken from move acr
|
ocsenave@246
|
99 "user atk +2"
|
ocsenave@246
|
100 "user def +2"
|
ocsenave@246
|
101 "user spd +2"
|
ocsenave@246
|
102 "user spc +2"
|
ocsenave@246
|
103 "user acr +2" ;; unused!
|
ocsenave@246
|
104 "user evd +2" ;; unused!
|
ocsenave@246
|
105 "restores up to half of user's max hp." ;; broken: fails if the difference
|
ocsenave@246
|
106 ;; b/w max and current hp is one less than a multiple of 256.
|
ocsenave@246
|
107 "(transform)"
|
ocsenave@246
|
108 "opponent atk -2"
|
ocsenave@246
|
109 "opponent def -2"
|
ocsenave@246
|
110 "opponent spd -2"
|
ocsenave@246
|
111 "opponent spc -2"
|
ocsenave@246
|
112 "opponent acr -2"
|
ocsenave@246
|
113 "opponent evd -2"
|
ocsenave@246
|
114 "doubles user spc when attacked"
|
ocsenave@246
|
115 "doubles user def when attacked"
|
ocsenave@249
|
116 "just poisons opponent" ;;acr taken from move acr
|
ocsenave@249
|
117 "just paralyzes opponent" ;;
|
ocsenave@246
|
118 "0x19 chance opponent atk -1"
|
ocsenave@246
|
119 "0x19 chance opponent def -1"
|
ocsenave@246
|
120 "0x19 chance opponent spd -1"
|
ocsenave@246
|
121 "0x4C chance opponent spc -1" ;; context suggest chance is 0x19
|
ocsenave@246
|
122 "0x19 chance opponent acr -1"
|
ocsenave@246
|
123 "0x19 chance opponent evd -1"
|
ocsenave@246
|
124 "???" ;; unused? no effect?
|
ocsenave@246
|
125 "???" ;; unused? no effect?
|
ocsenave@246
|
126 "0x19 chance opponent confused"
|
ocsenave@246
|
127 "atk hits twice. 0x33 chance opponent poisioned."
|
ocsenave@246
|
128 "broken. crash the game after attack."
|
ocsenave@246
|
129 "(substitute)"
|
ocsenave@246
|
130 "unless opponent faints, user must recharge after atk. some
|
ocsenave@246
|
131 exceptions apply."
|
ocsenave@246
|
132 "(rage)"
|
ocsenave@246
|
133 "(mimic)"
|
ocsenave@246
|
134 "(metronome)"
|
ocsenave@246
|
135 "(leech seed)"
|
ocsenave@246
|
136 "does nothing (splash)"
|
ocsenave@246
|
137 "(disable)"
|
ocsenave@246
|
138 ])
|
ocsenave@246
|
139
|
ocsenave@246
|
140
|
ocsenave@249
|
141 ;; ************** HARDCODED DATA
|
ocsenave@246
|
142
|
ocsenave@249
|
143 (defn hxc-thunk
|
ocsenave@249
|
144 "Creates a thunk (unary fn) that grabs data in a certain region of rom and
|
ocsenave@249
|
145 splits it into a collection by 0x50. If rom is not supplied, uses the
|
ocsenave@249
|
146 original rom data."
|
ocsenave@249
|
147 [start length]
|
ocsenave@249
|
148 (fn self
|
ocsenave@249
|
149 ([rom]
|
ocsenave@249
|
150 (take-nth 2
|
ocsenave@249
|
151 (partition-by #(= % 0x50)
|
ocsenave@249
|
152 (take length
|
ocsenave@249
|
153 (drop start rom)))))
|
ocsenave@249
|
154 ([]
|
ocsenave@249
|
155 (self com.aurellem.gb.gb-driver/original-rom))))
|
ocsenave@246
|
156
|
ocsenave@249
|
157 (def hxc-thunk-words
|
ocsenave@249
|
158 "Same as hxc-thunk, except it interprets the rom data as characters,
|
ocsenave@249
|
159 returning a collection of strings."
|
ocsenave@249
|
160 (comp
|
ocsenave@249
|
161 (partial comp (partial map character-codes->str))
|
ocsenave@249
|
162 hxc-thunk))
|
ocsenave@249
|
163
|
ocsenave@249
|
164
|
ocsenave@249
|
165 ;; --------------------------------------------------
|
ocsenave@246
|
166
|
ocsenave@246
|
167 (def hxc-items
|
ocsenave@249
|
168 "The hardcoded names of the items in memory. List begins at
|
ocsenave@249
|
169 ROM@045B7"
|
ocsenave@249
|
170 (hxc-thunk-words 0x45B7 870))
|
ocsenave@246
|
171
|
ocsenave@246
|
172 (def hxc-types
|
ocsenave@246
|
173 "The hardcoded type names in memory. List begins at ROM@27D99,
|
ocsenave@246
|
174 shortly before hxc-titles."
|
ocsenave@249
|
175 (hxc-thunk-words 0x27D99 102))
|
ocsenave@246
|
176
|
ocsenave@246
|
177 (def hxc-titles
|
ocsenave@246
|
178 "The hardcoded names of the trainer titles in memory. List begins at
|
ocsenave@246
|
179 ROM@27E77"
|
ocsenave@249
|
180 (hxc-thunk-words 0x27E77 196))
|
ocsenave@246
|
181
|
ocsenave@246
|
182 (def hxc-places
|
ocsenave@246
|
183 "The hardcoded place names in memory. List begins at
|
ocsenave@249
|
184 ROM@71500. [Cinnabar] Mansion seems to be dynamically calculated."
|
ocsenave@249
|
185 (hxc-thunk-words 0x71500 560))
|
ocsenave@246
|
186
|
ocsenave@246
|
187
|
ocsenave@249
|
188 (defn hxc-dialog
|
ocsenave@249
|
189 "The hardcoded dialogue in memory, including in-game alerts. Dialog
|
ocsenave@249
|
190 seems to be separated by 0x57 instead of 0x50 (END). Begins at ROM@98000."
|
ocsenave@249
|
191 ([rom]
|
ocsenave@249
|
192 (map character-codes->str
|
ocsenave@249
|
193 (take-nth 2
|
ocsenave@249
|
194 (partition-by #(= % 0x57)
|
ocsenave@249
|
195 (take 0x0F728
|
ocsenave@249
|
196 (drop 0x98000 rom))))))
|
ocsenave@249
|
197 ([]
|
ocsenave@249
|
198 (hxc-dialog com.aurellem.gb.gb-driver/original-rom)))
|
ocsenave@249
|
199
|
ocsenave@246
|
200
|
ocsenave@246
|
201 (def hxc-pokedex
|
ocsenave@246
|
202 "The hardcoded pokedex entries in memory. List begins at
|
ocsenave@246
|
203 ROM@B8000, shortly before move names."
|
ocsenave@249
|
204 (hxc-thunk-words 0xB8000 14754))
|
ocsenave@249
|
205
|
ocsenave@246
|
206 (def hxc-move-names
|
ocsenave@246
|
207 "The hardcoded move names in memory. List begins at ROM@BC000"
|
ocsenave@249
|
208 (hxc-thunk-words 0xBC000 1551))
|
ocsenave@246
|
209
|
ocsenave@249
|
210
|
ocsenave@249
|
211 (defn hxc-move-data
|
ocsenave@246
|
212 "The hardcoded (basic (move effects)) in memory. List begins at
|
ocsenave@249
|
213 0x38000. Returns a map of {:name :power :accuracy :pp :fx-id
|
ocsenave@249
|
214 :fx-txt}. The move descriptions are handwritten, not hardcoded."
|
ocsenave@249
|
215 ([]
|
ocsenave@249
|
216 (hxc-move-data com.aurellem.gb.gb-driver/original-rom))
|
ocsenave@249
|
217 ([rom]
|
ocsenave@249
|
218 (let [names (vec (hxc-move-names rom))
|
ocsenave@249
|
219 move-count (count names)
|
ocsenave@249
|
220 move-size 6
|
ocsenave@249
|
221 format-name (fn [s]
|
ocsenave@246
|
222 (keyword (.toLowerCase
|
ocsenave@249
|
223 (apply str
|
ocsenave@249
|
224 (map #(if (= % \space) "-" %) s)))))]
|
ocsenave@249
|
225 (zipmap (map format-name names)
|
ocsenave@249
|
226 (map
|
ocsenave@249
|
227 (fn [[idx effect power type accuracy pp]]
|
ocsenave@249
|
228 {:name (names (dec idx))
|
ocsenave@249
|
229 :power power
|
ocsenave@249
|
230 :accuracy accuracy
|
ocsenave@249
|
231 :pp pp
|
ocsenave@249
|
232 :fx-id effect
|
ocsenave@249
|
233 :fx-txt (get move-effects effect)
|
ocsenave@249
|
234 }
|
ocsenave@249
|
235 )
|
ocsenave@249
|
236
|
ocsenave@249
|
237 (partition move-size
|
ocsenave@249
|
238 (take (* move-size move-count)
|
ocsenave@249
|
239 (drop 0x38000 rom))))))))
|
ocsenave@246
|
240
|
ocsenave@246
|
241
|
ocsenave@246
|
242
|
ocsenave@249
|
243 (defn hxc-move-data*
|
ocsenave@249
|
244 "Like hxc-move-data, but reports numbers as hexadecimal symbols instead."
|
ocsenave@249
|
245 ([]
|
ocsenave@249
|
246 (hxc-move-data* com.aurellem.gb.gb-driver/original-rom))
|
ocsenave@249
|
247 ([rom]
|
ocsenave@249
|
248 (let [names (vec (hxc-move-names rom))
|
ocsenave@249
|
249 move-count (count names)
|
ocsenave@249
|
250 move-size 6
|
ocsenave@249
|
251 format-name (fn [s]
|
ocsenave@249
|
252 (keyword (.toLowerCase
|
ocsenave@249
|
253 (apply str
|
ocsenave@249
|
254 (map #(if (= % \space) "-" %) s)))))
|
ocsenave@249
|
255 ]
|
ocsenave@249
|
256 (zipmap (map format-name names)
|
ocsenave@249
|
257 (map
|
ocsenave@249
|
258 (fn [[idx effect power type accuracy pp]]
|
ocsenave@249
|
259 {:name (names (dec idx))
|
ocsenave@249
|
260 :power power
|
ocsenave@249
|
261 :accuracy (hex accuracy)
|
ocsenave@249
|
262 :pp pp
|
ocsenave@249
|
263 :fx-id (hex effect)
|
ocsenave@249
|
264 :fx-txt (get move-effects effect)
|
ocsenave@249
|
265 }
|
ocsenave@249
|
266 )
|
ocsenave@249
|
267
|
ocsenave@249
|
268 (partition move-size
|
ocsenave@249
|
269 (take (* move-size move-count)
|
ocsenave@249
|
270 (drop 0x38000 rom))))))))
|
ocsenave@243
|
271
|
ocsenave@243
|
272
|
ocsenave@243
|
273
|
ocsenave@249
|
274 (defn hxc-pokenames
|
ocsenave@249
|
275 "The hardcoded names of the 190 species in memory. List begins at
|
ocsenave@249
|
276 ROM@E8000. Although names in memory are padded with 0x50 to be 10 characters
|
ocsenave@249
|
277 long, these names are stripped of padding."
|
ocsenave@249
|
278 ([]
|
ocsenave@249
|
279 (hxc-pokenames com.aurellem.gb.gb-driver/original-rom))
|
ocsenave@249
|
280 ([rom]
|
ocsenave@249
|
281 (let [count-species 190
|
ocsenave@249
|
282 name-length 10]
|
ocsenave@249
|
283 (map character-codes->str
|
ocsenave@249
|
284 (partition name-length
|
ocsenave@249
|
285 (map #(if (= 0x50 %) 0x00 %)
|
ocsenave@249
|
286 (take (* count-species name-length)
|
ocsenave@249
|
287 (drop 0xE8000
|
ocsenave@249
|
288 rom))))))))
|
ocsenave@243
|
289
|
ocsenave@249
|
290 (defn hxc-advantage
|
ocsenave@249
|
291 "The hardcoded type advantages in memory, returned as tuples of atk-type def-type multiplier. By default (i.e. if not listed here),
|
ocsenave@249
|
292 the multiplier is 1."
|
ocsenave@249
|
293 ([] (hxc-advantage com.aurellem.gb.gb-driver/original-rom))
|
ocsenave@249
|
294 ([rom]
|
ocsenave@249
|
295 (map
|
ocsenave@249
|
296 (fn [[atk def mult]] [(get pkmn-types atk (hex atk))
|
ocsenave@249
|
297 (get pkmn-types def (hex def))
|
ocsenave@249
|
298 (/ mult 10)])
|
ocsenave@249
|
299 (partition 3
|
ocsenave@249
|
300 (take-while (partial not= 0xFF)
|
ocsenave@249
|
301 (drop 0x3E62D rom))))))
|
ocsenave@243
|
302
|
ocsenave@243
|
303
|
ocsenave@243
|
304
|
ocsenave@243
|
305
|
ocsenave@243
|
306
|
ocsenave@243
|
307
|
ocsenave@243
|
308
|
ocsenave@243
|
309
|
ocsenave@243
|
310
|
ocsenave@243
|
311
|
ocsenave@249
|
312 ;; ********************** MANIPULATION FNS
|
ocsenave@249
|
313
|
ocsenave@249
|
314
|
ocsenave@249
|
315
|
ocsenave@249
|
316
|
ocsenave@249
|
317 (defn submap?
|
ocsenave@249
|
318 "Compares the two maps. Returns true if map-big has the same associations as map-small, otherwise false."
|
ocsenave@249
|
319 [map-small map-big]
|
ocsenave@249
|
320 (cond (empty? map-small) true
|
ocsenave@249
|
321 (and
|
ocsenave@249
|
322 (contains? map-big (ffirst map-small))
|
ocsenave@249
|
323 (= (get map-big (ffirst map-small))
|
ocsenave@249
|
324 (second (first map-small))))
|
ocsenave@249
|
325 (recur (next map-small) map-big)
|
ocsenave@249
|
326
|
ocsenave@249
|
327 :else false))
|
ocsenave@249
|
328
|
ocsenave@249
|
329
|
ocsenave@249
|
330 (defn search-map [proto-map maps]
|
ocsenave@249
|
331 "Returns all the maps that make the same associations as proto-map."
|
ocsenave@249
|
332 (some (partial submap? proto-map) maps))
|
ocsenave@249
|
333
|
ocsenave@249
|
334 ;; (I don't use this for anything so far.)
|
ocsenave@249
|
335 ;;
|
ocsenave@249
|
336 ;; (defn filter-vals
|
ocsenave@249
|
337 ;; "Returns a map consisting of all the pairs [key val] for which (pred
|
ocsenave@249
|
338 ;; key) returns true."
|
ocsenave@249
|
339 ;; [pred map]
|
ocsenave@249
|
340 ;; (reduce (partial apply assoc) {} (filter (fn [[k v]] (pred v)) map)))
|
ocsenave@249
|
341
|
ocsenave@249
|
342
|
ocsenave@249
|
343 (defn search-moves
|
ocsenave@249
|
344 "Returns a subcollection of all hardcoded moves with the given
|
ocsenave@249
|
345 attributes. Attributes consist of :name :power :accuracy :pp :fx-id
|
ocsenave@249
|
346 (and also :fx-txt, but it contains the same information as :fx-id)"
|
ocsenave@249
|
347 ([attribute-map]
|
ocsenave@249
|
348 (search-moves com.aurellem.gb.gb-driver/original-rom attribute-map))
|
ocsenave@249
|
349 ([rom attribute-map]
|
ocsenave@249
|
350 (filter-vals (partial submap? attribute-map) (hxc-move-data
|
ocsenave@249
|
351 rom))))
|
ocsenave@249
|
352
|
ocsenave@249
|
353
|
ocsenave@249
|
354
|
ocsenave@249
|
355
|
ocsenave@249
|
356
|
ocsenave@249
|
357
|
ocsenave@249
|
358
|
ocsenave@249
|
359
|
ocsenave@249
|
360
|
ocsenave@249
|
361
|
ocsenave@243
|
362
|
ocsenave@246
|
363 ;; note for later: credits start at F1290
|
ocsenave@243
|
364
|
ocsenave@243
|
365
|
ocsenave@243
|
366
|
ocsenave@246
|
367 (comment
|
ocsenave@243
|
368
|
rlm@218
|
369 (def hxc-later
|
rlm@218
|
370 "Running this code produces, e.g. hardcoded names NPCs give
|
rlm@218
|
371 their pokemon. Will sort through it later."
|
rlm@218
|
372 (print (character-codes->str(take 10000
|
rlm@218
|
373 (drop 0x71597
|
rlm@218
|
374 (rom (root)))))))
|
rlm@218
|
375
|
rlm@218
|
376 (let [dex
|
rlm@218
|
377 (partition-by #(= 0x50 %)
|
rlm@218
|
378 (take 2540
|
rlm@218
|
379 (drop 0x40687
|
rlm@218
|
380 (rom (root)))))]
|
rlm@218
|
381 (def dex dex)
|
rlm@218
|
382 (def hxc-species
|
rlm@218
|
383 (map character-codes->str
|
rlm@218
|
384 (take-nth 4 dex))))
|
ocsenave@246
|
385 ) |