annotate clojure/com/aurellem/gb/hxc.clj @ 310:3d4f60b4a4af

added hxc-intro-pkmn for seeing which pokemon is displayed in oak's intro, and sxc-intro-pkmn! for modifying it.
author Dylan Holmes <ocsenave@gmail.com>
date Sun, 01 Apr 2012 01:50:34 -0500
parents de172acc5a03
children 2060219691fa
rev   line source
rlm@218 1 (ns com.aurellem.gb.hxc
ocsenave@308 2 (:use (com.aurellem.gb assembly characters gb-driver util mem-util
ocsenave@281 3 constants species))
rlm@218 4 (:import [com.aurellem.gb.gb_driver SaveState]))
rlm@218 5
rlm@218 6
ocsenave@243 7
ocsenave@249 8
ocsenave@249 9 ; ************* HANDWRITTEN CONSTANTS
ocsenave@249 10
ocsenave@259 11
ocsenave@259 12
ocsenave@243 13 (def pkmn-types
ocsenave@272 14 [:normal ;;0
ocsenave@272 15 :fighting ;;1
ocsenave@272 16 :flying ;;2
ocsenave@272 17 :poison ;;3
ocsenave@272 18 :ground ;;4
ocsenave@272 19 :rock ;;5
ocsenave@272 20 :bird ;;6
ocsenave@272 21 :bug ;;7
ocsenave@272 22 :ghost ;;8
ocsenave@244 23 :A
ocsenave@244 24 :B
ocsenave@244 25 :C
ocsenave@244 26 :D
ocsenave@244 27 :E
ocsenave@244 28 :F
ocsenave@244 29 :G
ocsenave@244 30 :H
ocsenave@244 31 :I
ocsenave@244 32 :J
ocsenave@244 33 :K
ocsenave@272 34 :fire ;;20 (0x14)
ocsenave@272 35 :water ;;21 (0x15)
ocsenave@272 36 :grass ;;22 (0x16)
ocsenave@272 37 :electric ;;23 (0x17)
ocsenave@272 38 :psychic ;;24 (0x18)
ocsenave@272 39 :ice ;;25 (0x19)
ocsenave@272 40 :dragon ;;26 (0x1A)
ocsenave@244 41 ])
ocsenave@243 42
ocsenave@243 43
ocsenave@246 44 ;; question: when status effects claim to take
ocsenave@246 45 ;; their accuracy from the move accuracy, does
ocsenave@246 46 ;; this mean that the move always "hits" but the
ocsenave@246 47 ;; status effect may not?
ocsenave@246 48
ocsenave@246 49 (def move-effects
ocsenave@246 50 ["normal damage"
ocsenave@246 51 "no damage, just opponent sleep" ;; how many turns? is atk power ignored?
ocsenave@246 52 "0x4C chance of poison"
ocsenave@246 53 "leech half of inflicted damage"
ocsenave@246 54 "0x19 chance of burn"
ocsenave@246 55 "0x19 chance of freeze"
ocsenave@246 56 "0x19 chance of paralyze"
ocsenave@259 57 "user faints; opponent defense halved during attack."
ocsenave@246 58 "leech half of inflicted damage ONLY if sleeping opponent."
ocsenave@246 59 "imitate last attack"
ocsenave@246 60 "user atk +1"
ocsenave@246 61 "user def +1"
ocsenave@246 62 "user spd +1"
ocsenave@246 63 "user spc +1"
ocsenave@246 64 "user acr +1" ;; unused?!
ocsenave@246 65 "user evd +1"
ocsenave@246 66 "get post-battle $ = 2*level*uses"
ocsenave@246 67 "0xFE acr, no matter what."
ocsenave@246 68 "opponent atk -1" ;; acr taken from move acr?
ocsenave@246 69 "opponent def -1" ;;
ocsenave@246 70 "opponent spd -1" ;;
ocsenave@246 71 "opponent spc -1" ;;
ocsenave@246 72 "opponent acr -1";;
ocsenave@246 73 "opponent evd -1"
ocsenave@246 74 "converts user's type to opponent's."
ocsenave@246 75 "(haze)"
ocsenave@246 76 "(bide)"
ocsenave@246 77 "(thrash)"
ocsenave@246 78 "(teleport)"
ocsenave@246 79 "(fury swipes)"
ocsenave@246 80 "attacks 2-5 turns" ;; unused? like rollout?
ocsenave@246 81 "0x19 chance of flinch"
ocsenave@246 82 "opponent sleep for 1-7 turns"
ocsenave@246 83 "0x66 chance of poison"
ocsenave@246 84 "0x4D chance of burn"
ocsenave@246 85 "0x4D chance of freeze"
ocsenave@246 86 "0x4D chance of paralyze"
ocsenave@246 87 "0x4D chance of flinch"
ocsenave@246 88 "one-hit KO"
ocsenave@246 89 "charge one turn, atk next."
ocsenave@246 90 "fixed damage, leaves 1HP." ;; how is dmg determined?
ocsenave@246 91 "fixed damage." ;; cf seismic toss, dragon rage, psywave.
ocsenave@246 92 "atk 2-5 turns; opponent can't attack" ;; unnormalized? (0 0x60 0x60 0x20 0x20)
ocsenave@246 93 "charge one turn, atk next. (can't be hit when charging)"
ocsenave@246 94 "atk hits twice."
ocsenave@246 95 "user takes 1 damage if misses."
ocsenave@246 96 "evade status-lowering effects" ;;caused by you or also your opponent?
ocsenave@246 97 "(broken) if user is slower than opponent, makes critical hit impossible, otherwise has no effect"
ocsenave@246 98 "atk causes recoil dmg = 1/4 dmg dealt"
ocsenave@246 99 "confuses opponent" ;; acr taken from move acr
ocsenave@246 100 "user atk +2"
ocsenave@246 101 "user def +2"
ocsenave@246 102 "user spd +2"
ocsenave@246 103 "user spc +2"
ocsenave@246 104 "user acr +2" ;; unused!
ocsenave@246 105 "user evd +2" ;; unused!
ocsenave@246 106 "restores up to half of user's max hp." ;; broken: fails if the difference
ocsenave@246 107 ;; b/w max and current hp is one less than a multiple of 256.
ocsenave@246 108 "(transform)"
ocsenave@246 109 "opponent atk -2"
ocsenave@246 110 "opponent def -2"
ocsenave@246 111 "opponent spd -2"
ocsenave@246 112 "opponent spc -2"
ocsenave@246 113 "opponent acr -2"
ocsenave@246 114 "opponent evd -2"
ocsenave@246 115 "doubles user spc when attacked"
ocsenave@246 116 "doubles user def when attacked"
ocsenave@249 117 "just poisons opponent" ;;acr taken from move acr
ocsenave@249 118 "just paralyzes opponent" ;;
ocsenave@246 119 "0x19 chance opponent atk -1"
ocsenave@246 120 "0x19 chance opponent def -1"
ocsenave@246 121 "0x19 chance opponent spd -1"
ocsenave@246 122 "0x4C chance opponent spc -1" ;; context suggest chance is 0x19
ocsenave@246 123 "0x19 chance opponent acr -1"
ocsenave@246 124 "0x19 chance opponent evd -1"
ocsenave@246 125 "???" ;; unused? no effect?
ocsenave@246 126 "???" ;; unused? no effect?
ocsenave@246 127 "0x19 chance opponent confused"
ocsenave@246 128 "atk hits twice. 0x33 chance opponent poisioned."
ocsenave@246 129 "broken. crash the game after attack."
ocsenave@246 130 "(substitute)"
ocsenave@246 131 "unless opponent faints, user must recharge after atk. some
ocsenave@246 132 exceptions apply."
ocsenave@246 133 "(rage)"
ocsenave@246 134 "(mimic)"
ocsenave@246 135 "(metronome)"
ocsenave@246 136 "(leech seed)"
ocsenave@246 137 "does nothing (splash)"
ocsenave@246 138 "(disable)"
ocsenave@246 139 ])
ocsenave@246 140
ocsenave@246 141
ocsenave@249 142 ;; ************** HARDCODED DATA
ocsenave@246 143
ocsenave@249 144 (defn hxc-thunk
ocsenave@259 145 "Creates a thunk (nullary fn) that grabs data in a certain region of rom and
ocsenave@249 146 splits it into a collection by 0x50. If rom is not supplied, uses the
ocsenave@249 147 original rom data."
ocsenave@249 148 [start length]
ocsenave@249 149 (fn self
ocsenave@249 150 ([rom]
ocsenave@249 151 (take-nth 2
ocsenave@249 152 (partition-by #(= % 0x50)
ocsenave@249 153 (take length
ocsenave@249 154 (drop start rom)))))
ocsenave@249 155 ([]
ocsenave@249 156 (self com.aurellem.gb.gb-driver/original-rom))))
ocsenave@246 157
ocsenave@249 158 (def hxc-thunk-words
ocsenave@249 159 "Same as hxc-thunk, except it interprets the rom data as characters,
ocsenave@249 160 returning a collection of strings."
ocsenave@249 161 (comp
ocsenave@249 162 (partial comp (partial map character-codes->str))
ocsenave@249 163 hxc-thunk))
ocsenave@249 164
ocsenave@249 165
ocsenave@249 166 ;; --------------------------------------------------
ocsenave@246 167
ocsenave@288 168
ocsenave@288 169
ocsenave@288 170 (defn hxc-pokenames-raw
ocsenave@288 171 "The hardcoded names of the 190 species in memory. List begins at
ocsenave@288 172 ROM@E8000. Although names in memory are padded with 0x50 to be 10 characters
ocsenave@288 173 long, these names are stripped of padding. See also, hxc-pokedex-names"
ocsenave@288 174 ([]
ocsenave@288 175 (hxc-pokenames-raw com.aurellem.gb.gb-driver/original-rom))
ocsenave@288 176 ([rom]
ocsenave@288 177 (let [count-species 190
ocsenave@288 178 name-length 10]
ocsenave@288 179 (map character-codes->str
ocsenave@288 180 (partition name-length
ocsenave@288 181 (map #(if (= 0x50 %) 0x00 %)
ocsenave@288 182 (take (* count-species name-length)
ocsenave@288 183 (drop 0xE8000
ocsenave@288 184 rom))))))))
ocsenave@288 185 (def hxc-pokenames
ocsenave@288 186 (comp
ocsenave@288 187 (partial map format-name)
ocsenave@288 188 hxc-pokenames-raw))
ocsenave@288 189
ocsenave@288 190
ocsenave@288 191
ocsenave@288 192
ocsenave@288 193 (defn hxc-pokedex-names
ocsenave@288 194 "The names of the pokemon in hardcoded pokedex order. List begins at
ocsenave@288 195 ROM@410B1. See also, hxc-pokenames."
ocsenave@288 196 ([] (hxc-pokedex-names
ocsenave@288 197 com.aurellem.gb.gb-driver/original-rom))
ocsenave@288 198 ([rom]
ocsenave@288 199 (let [names (hxc-pokenames rom)]
ocsenave@288 200 (#(mapv %
ocsenave@288 201 ((comp range count keys) %))
ocsenave@288 202 (zipmap
ocsenave@288 203 (take (count names)
ocsenave@288 204 (drop 0x410b1 rom))
ocsenave@288 205
ocsenave@288 206 names)))))
ocsenave@288 207
ocsenave@288 208
ocsenave@288 209
ocsenave@306 210 ;; http://hax.iimarck.us/topic/581/
ocsenave@307 211 (defn hxc-cry
ocsenave@307 212 "The pokemon cry data in internal order. List begins at ROM@39462"
ocsenave@308 213 ([](hxc-cry com.aurellem.gb.gb-driver/original-rom))
ocsenave@307 214 ([rom]
ocsenave@307 215 (zipmap
ocsenave@307 216 (hxc-pokenames rom)
ocsenave@307 217 (map
ocsenave@307 218 (fn [[cry-id pitch length]]
ocsenave@307 219 {:cry-id cry-id
ocsenave@307 220 :pitch pitch
ocsenave@307 221 :length length}
ocsenave@307 222 )
ocsenave@307 223 (partition 3
ocsenave@308 224 (drop 0x39462 rom))))))
ocsenave@306 225
ocsenave@307 226 (defn hxc-cry-groups
ocsenave@308 227 ([] (hxc-cry-groups com.aurellem.gb.gb-driver/original-rom))
ocsenave@307 228 ([rom]
ocsenave@307 229 (map #(mapv first
ocsenave@307 230 (filter
ocsenave@307 231 (fn [[k v]]
ocsenave@307 232 (= % (:cry-id v)))
ocsenave@308 233 (hxc-cry)))
ocsenave@307 234 ((comp
ocsenave@307 235 range
ocsenave@307 236 count
ocsenave@307 237 set
ocsenave@307 238 (partial map :cry-id)
ocsenave@307 239 vals
ocsenave@307 240 hxc-cry)
ocsenave@307 241 rom))))
ocsenave@306 242
ocsenave@288 243
ocsenave@307 244 (defn cry-conversion!
ocsenave@307 245 "Convert Porygon's cry in ROM to be the cry of the given pokemon."
ocsenave@307 246 [pkmn]
ocsenave@307 247 (write-rom!
ocsenave@307 248 (rewrite-memory
ocsenave@307 249 (vec(rom))
ocsenave@307 250 0x3965D
ocsenave@307 251 (map second
ocsenave@307 252 ((hxc-cry) pkmn)))))
ocsenave@307 253
ocsenave@288 254 (def hxc-items-raw
ocsenave@249 255 "The hardcoded names of the items in memory. List begins at
ocsenave@249 256 ROM@045B7"
ocsenave@249 257 (hxc-thunk-words 0x45B7 870))
ocsenave@246 258
ocsenave@246 259 (def hxc-types
ocsenave@246 260 "The hardcoded type names in memory. List begins at ROM@27D99,
ocsenave@246 261 shortly before hxc-titles."
ocsenave@249 262 (hxc-thunk-words 0x27D99 102))
ocsenave@246 263
ocsenave@246 264 (def hxc-titles
ocsenave@246 265 "The hardcoded names of the trainer titles in memory. List begins at
ocsenave@246 266 ROM@27E77"
ocsenave@249 267 (hxc-thunk-words 0x27E77 196))
ocsenave@246 268
ocsenave@259 269
ocsenave@288 270 (def hxc-pokedex-text-raw
ocsenave@259 271 "The hardcoded pokedex entries in memory. List begins at
ocsenave@259 272 ROM@B8000, shortly before move names."
ocsenave@259 273 (hxc-thunk-words 0xB8000 14754))
ocsenave@259 274
ocsenave@288 275
ocsenave@288 276
ocsenave@288 277 (def hxc-items
ocsenave@288 278 "The hardcoded names of the items in memory, presented as
ocsenave@288 279 keywords. List begins at ROM@045B7. See also, hxc-items-raw."
ocsenave@288 280 (comp (partial map format-name) hxc-items-raw))
ocsenave@288 281
ocsenave@285 282 (defn hxc-pokedex-text
ocsenave@285 283 "The hardcoded pokedex entries in memory, presented as an
ocsenave@285 284 associative hash map. List begins at ROM@B8000."
ocsenave@285 285 ([] (hxc-pokedex-text com.aurellem.gb.gb-driver/original-rom))
ocsenave@285 286 ([rom]
ocsenave@285 287 (zipmap
ocsenave@285 288 (hxc-pokedex-names rom)
ocsenave@285 289 (cons nil ;; for missingno.
ocsenave@288 290 (hxc-pokedex-text-raw rom)))))
ocsenave@259 291
ocsenave@272 292 ;; In red/blue, pokedex stats are in internal order.
ocsenave@272 293 ;; In yellow, pokedex stats are in pokedex order.
ocsenave@259 294
ocsenave@259 295 (defn hxc-pokedex-stats
ocsenave@272 296 "The hardcoded pokedex stats (species height weight) in memory. List
ocsenave@272 297 begins at ROM@40687"
ocsenave@259 298 ([] (hxc-pokedex-stats com.aurellem.gb.gb-driver/original-rom))
ocsenave@259 299 ([rom]
ocsenave@288 300 (let [pokedex-names (zipmap (range) (hxc-pokedex-names rom))
ocsenave@288 301 pkmn-count (count pokedex-names)
ocsenave@259 302 ]
ocsenave@259 303 ((fn capture-stats
ocsenave@259 304 [n stats data]
ocsenave@259 305 (if (zero? n) stats
ocsenave@259 306 (let [[species
ocsenave@259 307 [_
ocsenave@259 308 height-ft
ocsenave@259 309 height-in
ocsenave@259 310 weight-1
ocsenave@259 311 weight-2
ocsenave@259 312 _
ocsenave@259 313 dex-ptr-1
ocsenave@259 314 dex-ptr-2
ocsenave@259 315 dex-bank
ocsenave@259 316 _
ocsenave@259 317 & data]]
ocsenave@259 318 (split-with (partial not= 0x50) data)]
ocsenave@259 319 (recur (dec n)
ocsenave@259 320 (assoc stats
ocsenave@285 321 (pokedex-names (- pkmn-count (dec n)))
ocsenave@259 322 {:species
ocsenave@285 323 (format-name (character-codes->str species))
ocsenave@259 324 :height-ft
ocsenave@259 325 height-ft
ocsenave@259 326 :height-in
ocsenave@259 327 height-in
ocsenave@259 328 :weight
ocsenave@259 329 (/ (low-high weight-1 weight-2) 10.)
ocsenave@259 330
ocsenave@259 331 ;; :text
ocsenave@259 332 ;; (character-codes->str
ocsenave@259 333 ;; (take-while
ocsenave@259 334 ;; (partial not= 0x50)
ocsenave@259 335 ;; (drop
ocsenave@259 336 ;; (+ 0xB8000
ocsenave@259 337 ;; -0x4000
ocsenave@259 338 ;; (low-high dex-ptr-1 dex-ptr-2))
ocsenave@259 339 ;; rom)))
ocsenave@259 340 })
ocsenave@259 341
ocsenave@259 342 data)
ocsenave@259 343
ocsenave@259 344
ocsenave@259 345 )))
ocsenave@259 346
ocsenave@259 347 pkmn-count
ocsenave@259 348 {}
ocsenave@259 349 (drop 0x40687 rom))) ))
ocsenave@259 350
ocsenave@259 351
ocsenave@259 352
ocsenave@259 353
ocsenave@259 354
ocsenave@259 355
ocsenave@259 356
ocsenave@246 357 (def hxc-places
ocsenave@246 358 "The hardcoded place names in memory. List begins at
ocsenave@249 359 ROM@71500. [Cinnabar] Mansion seems to be dynamically calculated."
ocsenave@249 360 (hxc-thunk-words 0x71500 560))
ocsenave@246 361
ocsenave@246 362
ocsenave@249 363 (defn hxc-dialog
ocsenave@249 364 "The hardcoded dialogue in memory, including in-game alerts. Dialog
ocsenave@249 365 seems to be separated by 0x57 instead of 0x50 (END). Begins at ROM@98000."
ocsenave@249 366 ([rom]
ocsenave@249 367 (map character-codes->str
ocsenave@249 368 (take-nth 2
ocsenave@249 369 (partition-by #(= % 0x57)
ocsenave@249 370 (take 0x0F728
ocsenave@249 371 (drop 0x98000 rom))))))
ocsenave@249 372 ([]
ocsenave@249 373 (hxc-dialog com.aurellem.gb.gb-driver/original-rom)))
ocsenave@249 374
ocsenave@246 375
ocsenave@246 376 (def hxc-move-names
ocsenave@246 377 "The hardcoded move names in memory. List begins at ROM@BC000"
ocsenave@249 378 (hxc-thunk-words 0xBC000 1551))
ocsenave@246 379
ocsenave@249 380
ocsenave@249 381 (defn hxc-move-data
ocsenave@246 382 "The hardcoded (basic (move effects)) in memory. List begins at
ocsenave@249 383 0x38000. Returns a map of {:name :power :accuracy :pp :fx-id
ocsenave@249 384 :fx-txt}. The move descriptions are handwritten, not hardcoded."
ocsenave@249 385 ([]
ocsenave@249 386 (hxc-move-data com.aurellem.gb.gb-driver/original-rom))
ocsenave@249 387 ([rom]
ocsenave@249 388 (let [names (vec (hxc-move-names rom))
ocsenave@249 389 move-count (count names)
ocsenave@281 390 move-size 6
ocsenave@281 391 types pkmn-types ;;; !! hardcoded types
ocsenave@281 392 ]
ocsenave@249 393 (zipmap (map format-name names)
ocsenave@249 394 (map
ocsenave@281 395 (fn [[idx effect power type-id accuracy pp]]
ocsenave@249 396 {:name (names (dec idx))
ocsenave@249 397 :power power
ocsenave@249 398 :accuracy accuracy
ocsenave@249 399 :pp pp
ocsenave@281 400 :type (types type-id)
ocsenave@249 401 :fx-id effect
ocsenave@249 402 :fx-txt (get move-effects effect)
ocsenave@249 403 }
ocsenave@249 404 )
ocsenave@249 405
ocsenave@249 406 (partition move-size
ocsenave@249 407 (take (* move-size move-count)
ocsenave@249 408 (drop 0x38000 rom))))))))
ocsenave@246 409
ocsenave@246 410
ocsenave@246 411
ocsenave@249 412 (defn hxc-move-data*
ocsenave@249 413 "Like hxc-move-data, but reports numbers as hexadecimal symbols instead."
ocsenave@249 414 ([]
ocsenave@249 415 (hxc-move-data* com.aurellem.gb.gb-driver/original-rom))
ocsenave@249 416 ([rom]
ocsenave@249 417 (let [names (vec (hxc-move-names rom))
ocsenave@249 418 move-count (count names)
ocsenave@249 419 move-size 6
ocsenave@249 420 format-name (fn [s]
ocsenave@249 421 (keyword (.toLowerCase
ocsenave@249 422 (apply str
ocsenave@249 423 (map #(if (= % \space) "-" %) s)))))
ocsenave@249 424 ]
ocsenave@249 425 (zipmap (map format-name names)
ocsenave@249 426 (map
ocsenave@249 427 (fn [[idx effect power type accuracy pp]]
ocsenave@249 428 {:name (names (dec idx))
ocsenave@249 429 :power power
ocsenave@249 430 :accuracy (hex accuracy)
ocsenave@249 431 :pp pp
ocsenave@249 432 :fx-id (hex effect)
ocsenave@249 433 :fx-txt (get move-effects effect)
ocsenave@249 434 }
ocsenave@249 435 )
ocsenave@249 436
ocsenave@249 437 (partition move-size
ocsenave@249 438 (take (* move-size move-count)
ocsenave@249 439 (drop 0x38000 rom))))))))
ocsenave@243 440
ocsenave@243 441
ocsenave@283 442 (defn hxc-machines
ocsenave@283 443 "The hardcoded moves taught by TMs and HMs. List begins at ROM@0x1232D."
ocsenave@283 444 ([] (hxc-machines
ocsenave@283 445 com.aurellem.gb.gb-driver/original-rom))
ocsenave@283 446 ([rom]
ocsenave@283 447 (let [moves (hxc-move-names rom)]
ocsenave@283 448 (zipmap
ocsenave@283 449 (range)
ocsenave@283 450 (take-while
ocsenave@283 451 (comp not nil?)
ocsenave@283 452 (map (comp
ocsenave@283 453 format-name
ocsenave@283 454 (zipmap
ocsenave@283 455 (range)
ocsenave@283 456 moves)
ocsenave@283 457 dec)
ocsenave@283 458 (take 100
ocsenave@283 459 (drop 0x1232D rom))))))))
ocsenave@285 460
ocsenave@285 461
ocsenave@259 462
ocsenave@259 463 (defn internal-id
ocsenave@259 464 ([rom]
ocsenave@259 465 (zipmap
ocsenave@288 466 (hxc-pokenames rom)
ocsenave@259 467 (range)))
ocsenave@259 468 ([]
ocsenave@259 469 (internal-id com.aurellem.gb.gb-driver/original-rom)))
ocsenave@285 470
ocsenave@285 471
ocsenave@285 472
ocsenave@259 473
ocsenave@259 474
ocsenave@263 475 ;; nidoran gender change upon levelup
ocsenave@263 476 ;; (->
ocsenave@263 477 ;; @current-state
ocsenave@263 478 ;; rom
ocsenave@263 479 ;; vec
ocsenave@263 480 ;; (rewrite-memory
ocsenave@263 481 ;; (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♂))
ocsenave@263 482 ;; [1 1 15])
ocsenave@263 483 ;; (rewrite-memory
ocsenave@263 484 ;; (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♀))
ocsenave@263 485 ;; [1 1 3])
ocsenave@263 486 ;; (write-rom!)
ocsenave@263 487
ocsenave@263 488 ;; )
ocsenave@263 489
ocsenave@259 490
ocsenave@259 491
ocsenave@259 492
ocsenave@249 493 (defn hxc-advantage
ocsenave@292 494 ;; in-game multipliers are stored as 10x their effective value
ocsenave@292 495 ;; to allow for fractional multipliers like 1/2
ocsenave@292 496
ocsenave@292 497 "The hardcoded type advantages in memory, returned as tuples of
ocsenave@292 498 atk-type def-type multiplier. By default (i.e. if not listed here),
ocsenave@292 499 the multiplier is 1. List begins at 0x3E62D."
ocsenave@249 500 ([] (hxc-advantage com.aurellem.gb.gb-driver/original-rom))
ocsenave@249 501 ([rom]
ocsenave@249 502 (map
ocsenave@249 503 (fn [[atk def mult]] [(get pkmn-types atk (hex atk))
ocsenave@249 504 (get pkmn-types def (hex def))
ocsenave@249 505 (/ mult 10)])
ocsenave@249 506 (partition 3
ocsenave@249 507 (take-while (partial not= 0xFF)
ocsenave@249 508 (drop 0x3E62D rom))))))
ocsenave@243 509
ocsenave@243 510
ocsenave@281 511
ocsenave@263 512 (defn format-evo
ocsenave@263 513 [coll]
ocsenave@263 514 (let [method (first coll)]
ocsenave@263 515 (cond (empty? coll) []
ocsenave@263 516 (= 0 method) [] ;; just in case
ocsenave@263 517 (= 1 method) ;; level-up evolution
ocsenave@263 518 (conj (format-evo (drop 3 coll))
ocsenave@263 519 {:method :level-up
ocsenave@263 520 :min-level (nth coll 1)
ocsenave@263 521 :into (dec (nth coll 2))})
ocsenave@263 522
ocsenave@263 523 (= 2 method) ;; item evolution
ocsenave@263 524 (conj (format-evo (drop 4 coll))
ocsenave@263 525 {:method :item
ocsenave@263 526 :item (dec (nth coll 1))
ocsenave@263 527 :min-level (nth coll 2)
ocsenave@263 528 :into (dec (nth coll 3))})
ocsenave@243 529
ocsenave@263 530 (= 3 method) ;; trade evolution
ocsenave@263 531 (conj (format-evo (drop 3 coll))
ocsenave@263 532 {:method :trade
ocsenave@263 533 :min-level (nth coll 1) ;; always 1 for trade.
ocsenave@263 534 :into (dec (nth coll 2))}))))
ocsenave@243 535
ocsenave@243 536
ocsenave@263 537 (defn hxc-ptrs-evolve
ocsenave@267 538 "A hardcoded collection of 190 pointers to alternating evolution/learnset data,
ocsenave@263 539 in internal order."
ocsenave@263 540 ([]
ocsenave@263 541 (hxc-ptrs-evolve com.aurellem.gb.gb-driver/original-rom))
ocsenave@259 542 ([rom]
ocsenave@288 543 (let [
ocsenave@288 544 pkmn-count (count (hxc-pokenames-raw)) ;; 190
ocsenave@259 545 ptrs
ocsenave@263 546 (map (fn [[a b]] (low-high a b))
ocsenave@259 547 (partition 2
ocsenave@259 548 (take (* 2 pkmn-count)
ocsenave@263 549 (drop 0x3b1e5 rom))))]
ocsenave@263 550 (map (partial + 0x34000) ptrs)
ocsenave@263 551
ocsenave@263 552 )))
ocsenave@263 553
ocsenave@267 554
ocsenave@267 555 (defn hxc-learnsets
ocsenave@267 556 "Hardcoded map associating pokemon names to lists of pairs [lvl
ocsenave@267 557 move] of abilities they learn as they level up. The data
ocsenave@267 558 exists at ROM@3400, sorted by internal order. Pointers to the data
ocsenave@267 559 exist at ROM@3B1E5; see also, hxc-ptrs-evolve"
ocsenave@267 560 ([] (hxc-learnsets com.aurellem.gb.gb-driver/original-rom))
ocsenave@267 561 ([rom]
ocsenave@267 562 (apply assoc
ocsenave@267 563 {}
ocsenave@267 564 (interleave
ocsenave@288 565 (hxc-pokenames rom)
ocsenave@267 566 (map (comp
ocsenave@268 567 (partial map
ocsenave@268 568 (fn [[lvl mv]] [lvl (dec mv)]))
ocsenave@267 569 (partial partition 2)
ocsenave@267 570 ;; keep the learnset data
ocsenave@267 571 (partial take-while (comp not zero?))
ocsenave@267 572 ;; skip the evolution data
ocsenave@267 573 rest
ocsenave@267 574 (partial drop-while (comp not zero?)))
ocsenave@267 575 (map #(drop % rom)
ocsenave@267 576 (hxc-ptrs-evolve rom)))))))
ocsenave@267 577
ocsenave@267 578 (defn hxc-learnsets-pretty
ocsenave@267 579 "Live hxc-learnsets except it reports the name of each move --- as
ocsenave@267 580 it appears in rom --- rather than the move index."
ocsenave@267 581 ([] (hxc-learnsets-pretty com.aurellem.gb.gb-driver/original-rom))
ocsenave@267 582 ([rom]
ocsenave@267 583 (let [moves (vec(map format-name (hxc-move-names)))]
ocsenave@267 584 (into {}
ocsenave@267 585 (map (fn [[pkmn learnset]]
ocsenave@268 586 [pkmn (map (fn [[lvl mv]] [lvl (moves mv)])
ocsenave@267 587 learnset)])
ocsenave@267 588 (hxc-learnsets rom))))))
ocsenave@267 589
ocsenave@267 590
ocsenave@267 591
ocsenave@267 592
ocsenave@263 593 (defn hxc-evolution
ocsenave@263 594 "Hardcoded evolution data in memory. The data exists at ROM@34000,
ocsenave@263 595 sorted by internal order. Pointers to the data exist at ROM@3B1E5; see also, hxc-ptrs-evolve."
ocsenave@263 596 ([] (hxc-evolution com.aurellem.gb.gb-driver/original-rom))
ocsenave@263 597 ([rom]
ocsenave@259 598 (apply assoc {}
ocsenave@259 599 (interleave
ocsenave@288 600 (hxc-pokenames rom)
ocsenave@259 601 (map
ocsenave@259 602 (comp
ocsenave@259 603 format-evo
ocsenave@263 604 (partial take-while (comp not zero?))
ocsenave@263 605 #(drop % rom))
ocsenave@263 606 (hxc-ptrs-evolve rom)
ocsenave@263 607 )))))
ocsenave@259 608
ocsenave@263 609 (defn hxc-evolution-pretty
ocsenave@263 610 "Like hxc-evolution, except it uses the names of items and pokemon
ocsenave@263 611 --- grabbed from ROM --- rather than their numerical identifiers."
ocsenave@263 612 ([] (hxc-evolution-pretty com.aurellem.gb.gb-driver/original-rom))
ocsenave@263 613 ([rom]
ocsenave@263 614 (let
ocsenave@288 615 [poke-names (vec (hxc-pokenames rom))
ocsenave@288 616 item-names (vec (hxc-items rom))
ocsenave@263 617 use-names
ocsenave@263 618 (fn [m]
ocsenave@263 619 (loop [ks (keys m) new-map m]
ocsenave@263 620 (let [k (first ks)]
ocsenave@263 621 (cond (nil? ks) new-map
ocsenave@263 622 (= k :into)
ocsenave@263 623 (recur
ocsenave@263 624 (next ks)
ocsenave@263 625 (assoc new-map
ocsenave@263 626 :into
ocsenave@263 627 (poke-names
ocsenave@263 628 (:into
ocsenave@263 629 new-map))))
ocsenave@263 630 (= k :item)
ocsenave@263 631 (recur
ocsenave@263 632 (next ks)
ocsenave@263 633 (assoc new-map
ocsenave@263 634 :item
ocsenave@263 635 (item-names
ocsenave@263 636 (:item new-map))))
ocsenave@263 637 :else
ocsenave@263 638 (recur
ocsenave@263 639 (next ks)
ocsenave@263 640 new-map)
ocsenave@263 641 ))))]
ocsenave@259 642
ocsenave@263 643 (into {}
ocsenave@263 644 (map (fn [[pkmn evo-coll]]
ocsenave@263 645 [pkmn (map use-names evo-coll)])
ocsenave@263 646 (hxc-evolution rom))))))
ocsenave@243 647
ocsenave@243 648
ocsenave@273 649 (defn hxc-pokemon-base
ocsenave@273 650 ([] (hxc-pokemon-base com.aurellem.gb.gb-driver/original-rom))
ocsenave@273 651 ([rom]
ocsenave@273 652 (let [entry-size 28
ocsenave@273 653 pkmn-count (count (hxc-pokedex-text rom))
ocsenave@285 654 pokemon (rest (hxc-pokedex-names))
ocsenave@273 655 types (apply assoc {}
ocsenave@273 656 (interleave
ocsenave@273 657 (range)
ocsenave@273 658 pkmn-types)) ;;!! softcoded
ocsenave@273 659 moves (apply assoc {}
ocsenave@273 660 (interleave
ocsenave@273 661 (range)
ocsenave@273 662 (map format-name
ocsenave@273 663 (hxc-move-names rom))))
ocsenave@288 664 machines (hxc-machines)
ocsenave@273 665 ]
ocsenave@285 666 (zipmap
ocsenave@285 667 pokemon
ocsenave@285 668 (map
ocsenave@285 669 (fn [[n
ocsenave@285 670 rating-hp
ocsenave@285 671 rating-atk
ocsenave@285 672 rating-def
ocsenave@285 673 rating-speed
ocsenave@285 674 rating-special
ocsenave@285 675 type-1
ocsenave@285 676 type-2
ocsenave@285 677 rarity
ocsenave@285 678 rating-xp
ocsenave@285 679 pic-dimensions ;; tile_width|tile_height (8px/tile)
ocsenave@285 680 ptr-pic-obverse-1
ocsenave@285 681 ptr-pic-obverse-2
ocsenave@285 682 ptr-pic-reverse-1
ocsenave@285 683 ptr-pic-reverse-2
ocsenave@285 684 move-1
ocsenave@285 685 move-2
ocsenave@285 686 move-3
ocsenave@285 687 move-4
ocsenave@285 688 growth-rate
ocsenave@285 689 &
ocsenave@285 690 TMs|HMs]]
ocsenave@285 691 (let
ocsenave@285 692 [base-moves
ocsenave@285 693 (mapv moves
ocsenave@285 694 ((comp
ocsenave@285 695 ;; since the game uses zero as a delimiter,
ocsenave@285 696 ;; it must also increment all move indices by 1.
ocsenave@285 697 ;; heren we decrement to correct this.
ocsenave@285 698 (partial map dec)
ocsenave@285 699 (partial take-while (comp not zero?)))
ocsenave@285 700 [move-1 move-2 move-3 move-4]))
ocsenave@285 701
ocsenave@285 702 types
ocsenave@285 703 (set (list (types type-1)
ocsenave@285 704 (types type-2)))
ocsenave@285 705 TMs|HMs
ocsenave@285 706 (map
ocsenave@285 707 (comp
ocsenave@285 708 (partial map first)
ocsenave@285 709 (partial remove (comp zero? second)))
ocsenave@285 710 (split-at
ocsenave@285 711 50
ocsenave@285 712 (map vector
ocsenave@285 713 (rest(range))
ocsenave@285 714 (reduce concat
ocsenave@285 715 (map
ocsenave@285 716 #(take 8
ocsenave@285 717 (concat (bit-list %)
ocsenave@285 718 (repeat 0)))
ocsenave@285 719
ocsenave@273 720 TMs|HMs)))))
ocsenave@285 721
ocsenave@285 722 TMs (vec (first TMs|HMs))
ocsenave@285 723 HMs (take 5 (map (partial + -50) (vec (second TMs|HMs))))
ocsenave@285 724
ocsenave@285 725
ocsenave@285 726 ]
ocsenave@285 727
ocsenave@285 728
ocsenave@285 729 {:dex# n
ocsenave@285 730 :base-moves base-moves
ocsenave@285 731 :types types
ocsenave@285 732 :TMs TMs
ocsenave@285 733 :HMs HMs
ocsenave@285 734 :base-hp rating-hp
ocsenave@285 735 :base-atk rating-atk
ocsenave@285 736 :base-def rating-def
ocsenave@285 737 :base-speed rating-speed
ocsenave@285 738 :base-special rating-special
ocsenave@310 739 :o0 pic-dimensions
ocsenave@310 740 :o1 ptr-pic-obverse-1
ocsenave@310 741 :o2 ptr-pic-obverse-2
ocsenave@285 742 }))
ocsenave@285 743
ocsenave@285 744 (partition entry-size
ocsenave@285 745 (take (* entry-size pkmn-count)
ocsenave@285 746 (drop 0x383DE
ocsenave@285 747 rom))))))))
ocsenave@285 748
ocsenave@285 749
ocsenave@310 750 (defn hxc-intro-pkmn
ocsenave@310 751 "The hardcoded pokemon to display in Prof. Oak's introduction; the pokemon's
ocsenave@310 752 internal id is stored at ROM@5EDB."
ocsenave@310 753 ([] (hxc-intro-pkmn
ocsenave@310 754 com.aurellem.gb.gb-driver/original-rom))
ocsenave@310 755 ([rom]
ocsenave@310 756 (nth (hxc-pokenames rom) (nth rom 0x5EDB))))
ocsenave@310 757
ocsenave@310 758 (defn sxc-intro-pkmn!
ocsenave@310 759 "Set the hardcoded pokemon to display in Prof. Oak's introduction."
ocsenave@310 760 [pokemon]
ocsenave@310 761 (write-rom!
ocsenave@310 762 (rewrite-rom 0x5EDB
ocsenave@310 763 [
ocsenave@310 764 (inc
ocsenave@310 765 ((zipmap
ocsenave@310 766 (hxc-pokenames)
ocsenave@310 767 (range))
ocsenave@310 768 pokemon))])))
ocsenave@285 769
ocsenave@310 770
ocsenave@282 771 (defn hxc-item-prices
ocsenave@282 772 "The hardcoded list of item prices in memory. List begins at ROM@4495"
ocsenave@282 773 ([] (hxc-item-prices com.aurellem.gb.gb-driver/original-rom))
ocsenave@282 774 ([rom]
ocsenave@288 775 (let [items (hxc-items rom)
ocsenave@282 776 price-size 3]
ocsenave@282 777 (zipmap items
ocsenave@282 778 (map (comp
ocsenave@282 779 ;; zero-cost items are "priceless"
ocsenave@282 780 #(if (zero? %) :priceless %)
ocsenave@282 781 decode-bcd butlast)
ocsenave@282 782 (partition price-size
ocsenave@282 783 (take (* price-size (count items))
ocsenave@282 784 (drop 0x4495 rom))))))))
ocsenave@273 785
ocsenave@281 786 (defn hxc-shops
ocsenave@281 787 ([] (hxc-shops com.aurellem.gb.gb-driver/original-rom))
ocsenave@281 788 ([rom]
ocsenave@288 789 (let [items (zipmap (range) (hxc-items rom))
ocsenave@281 790
ocsenave@281 791 ;; temporarily softcode the TM items
ocsenave@281 792 items (into
ocsenave@281 793 items
ocsenave@281 794 (map (juxt identity
ocsenave@281 795 (comp keyword
ocsenave@281 796 (partial str "tm-")
ocsenave@281 797 (partial + 1 -200)
ocsenave@281 798 ))
ocsenave@281 799 (take 200 (drop 200 (range)))))
ocsenave@282 800
ocsenave@281 801 ]
ocsenave@281 802
ocsenave@281 803 ((fn parse-shop [coll [num-items & items-etc]]
ocsenave@282 804 (let [inventory (take-while
ocsenave@282 805 (partial not= 0xFF)
ocsenave@282 806 items-etc)
ocsenave@281 807 [separator & items-etc] (drop num-items (rest items-etc))]
ocsenave@281 808 (if (= separator 0x50)
ocsenave@281 809 (map (partial mapv (comp items dec)) (conj coll inventory))
ocsenave@281 810 (recur (conj coll inventory) items-etc)
ocsenave@281 811 )
ocsenave@281 812 ))
ocsenave@281 813
ocsenave@281 814 '()
ocsenave@282 815 (drop 0x233C rom))
ocsenave@281 816
ocsenave@281 817
ocsenave@281 818 )))
ocsenave@281 819
ocsenave@281 820
ocsenave@273 821
ocsenave@292 822
ocsenave@292 823
ocsenave@292 824 (defn hxc-ptrs-wild
ocsenave@292 825 "A list of the hardcoded wild encounter data in memory. Pointers
ocsenave@292 826 begin at ROM@0CB95; data begins at ROM@0x04D89"
ocsenave@292 827 ([] (hxc-ptrs-wild com.aurellem.gb.gb-driver/original-rom))
ocsenave@292 828 ([rom]
ocsenave@292 829 (let [ptrs
ocsenave@292 830 (map (fn [[a b]] (+ a (* 0x100 b)))
ocsenave@292 831 (take-while (partial not= (list 0xFF 0xFF))
ocsenave@292 832 (partition 2 (drop 0xCB95 rom))))]
ocsenave@292 833 ptrs)))
ocsenave@292 834
ocsenave@292 835
ocsenave@292 836
ocsenave@292 837 (defn hxc-wilds
ocsenave@292 838 "A list of the hardcoded wild encounter data in memory. Pointers
ocsenave@292 839 begin at ROM@0CB95; data begins at ROM@0x04D89"
ocsenave@292 840 ([] (hxc-wilds com.aurellem.gb.gb-driver/original-rom))
ocsenave@292 841 ([rom]
ocsenave@292 842 (let [pokenames (zipmap (range) (hxc-pokenames rom))]
ocsenave@292 843 (map
ocsenave@292 844 (partial map (fn [[a b]] {:species (pokenames (dec b)) :level
ocsenave@292 845 a}))
ocsenave@292 846 (partition 10
ocsenave@292 847
ocsenave@292 848 (take-while (comp (partial not= 1)
ocsenave@292 849 first)
ocsenave@292 850 (partition 2
ocsenave@292 851 (drop 0xCD8C rom))
ocsenave@292 852
ocsenave@292 853 ))))))
ocsenave@292 854
ocsenave@292 855
ocsenave@292 856
ocsenave@292 857
ocsenave@292 858
ocsenave@292 859
ocsenave@292 860
ocsenave@292 861
ocsenave@292 862
ocsenave@292 863
ocsenave@292 864
ocsenave@292 865
ocsenave@292 866
ocsenave@292 867
ocsenave@249 868 ;; ********************** MANIPULATION FNS
ocsenave@249 869
ocsenave@249 870
ocsenave@285 871 (defn same-type
ocsenave@285 872 ([pkmn move]
ocsenave@288 873 (same-type
ocsenave@285 874 com.aurellem.gb.gb-driver/original-rom pkmn move))
ocsenave@285 875 ([rom pkmn move]
ocsenave@285 876 (((comp :types (hxc-pokemon-base rom)) pkmn)
ocsenave@285 877 ((comp :type (hxc-move-data rom)) move))))
ocsenave@285 878
ocsenave@285 879
ocsenave@249 880
ocsenave@249 881
ocsenave@249 882 (defn submap?
ocsenave@249 883 "Compares the two maps. Returns true if map-big has the same associations as map-small, otherwise false."
ocsenave@249 884 [map-small map-big]
ocsenave@249 885 (cond (empty? map-small) true
ocsenave@249 886 (and
ocsenave@249 887 (contains? map-big (ffirst map-small))
ocsenave@249 888 (= (get map-big (ffirst map-small))
ocsenave@249 889 (second (first map-small))))
ocsenave@249 890 (recur (next map-small) map-big)
ocsenave@249 891
ocsenave@249 892 :else false))
ocsenave@249 893
ocsenave@249 894
ocsenave@249 895 (defn search-map [proto-map maps]
ocsenave@249 896 "Returns all the maps that make the same associations as proto-map."
ocsenave@249 897 (some (partial submap? proto-map) maps))
ocsenave@249 898
rlm@252 899 (defn filter-vals
rlm@252 900 "Returns a map consisting of all the pairs [key val] for
rlm@252 901 which (pred key) returns true."
rlm@252 902 [pred map]
rlm@252 903 (reduce (partial apply assoc) {}
rlm@252 904 (filter (fn [[k v]] (pred v)) map)))
ocsenave@249 905
ocsenave@249 906
ocsenave@249 907 (defn search-moves
rlm@252 908 "Returns a subcollection of all hardcoded moves with the
rlm@252 909 given attributes. Attributes consist of :name :power
rlm@252 910 :accuracy :pp :fx-id
rlm@252 911 (and also :fx-txt, but it contains the same information
rlm@252 912 as :fx-id)"
ocsenave@249 913 ([attribute-map]
rlm@252 914 (search-moves
rlm@252 915 com.aurellem.gb.gb-driver/original-rom attribute-map))
ocsenave@249 916 ([rom attribute-map]
rlm@252 917 (filter-vals (partial submap? attribute-map)
rlm@252 918 (hxc-move-data rom))))
ocsenave@249 919
ocsenave@249 920
ocsenave@249 921
ocsenave@249 922
ocsenave@243 923
ocsenave@283 924 ;; note: 0x2f31 contains the names "TM" "HM"?
ocsenave@283 925
ocsenave@246 926 ;; note for later: credits start at F1290
ocsenave@243 927
ocsenave@243 928
ocsenave@243 929
ocsenave@246 930 (comment
ocsenave@243 931
rlm@218 932 (def hxc-later
rlm@218 933 "Running this code produces, e.g. hardcoded names NPCs give
rlm@218 934 their pokemon. Will sort through it later."
rlm@218 935 (print (character-codes->str(take 10000
rlm@218 936 (drop 0x71597
rlm@218 937 (rom (root)))))))
rlm@218 938
rlm@218 939 (let [dex
rlm@218 940 (partition-by #(= 0x50 %)
rlm@218 941 (take 2540
rlm@218 942 (drop 0x40687
rlm@218 943 (rom (root)))))]
rlm@218 944 (def dex dex)
rlm@218 945 (def hxc-species
rlm@218 946 (map character-codes->str
rlm@218 947 (take-nth 4 dex))))
ocsenave@259 948 )
ocsenave@259 949
ocsenave@259 950
ocsenave@259 951
ocsenave@281 952
ocsenave@281 953
ocsenave@281 954