rlm@98: (ns com.aurellem.items rlm@98: (:use (com.aurellem gb-driver vbm title)) rlm@99: ;; this is bullshit rlm@98: (:import [com.aurellem.gb_driver SaveState])) rlm@98: rlm@98: (defn game-name [] rlm@98: (map char (subvec (vec (memory)) 0x134 0x142))) rlm@98: rlm@99: (def item-list-start 0xD31C) rlm@98: rlm@99: (defn item-list [^SaveState state] rlm@99: (subvec rlm@99: (vec (memory state)) rlm@99: item-list-start rlm@100: (+ item-list-start 150))) rlm@98: rlm@98: (def item-hack-3 (read-state 77557)) rlm@98: rlm@99: (def item-code->item-name rlm@99: (hash-map rlm@103: 0x01 :master-ball rlm@103: 0x02 :ultra-ball rlm@103: 0x03 :great-ball rlm@103: 0x04 :poke-ball rlm@103: 0x05 :town-map rlm@103: 0x06 :bicycle rlm@103: 0x08 :safari-ball rlm@103: 0x09 :pokedex rlm@103: 0x0A :moon-stone rlm@103: 0x0B :antidote rlm@103: 0x0C :burn-heal rlm@103: 0x0D :ice-heal rlm@103: 0x0E :awakening rlm@103: 0x0F :parlyz-heal rlm@103: 0x10 :full-restore rlm@103: 0x11 :max-potion rlm@103: 0x12 :hyper-potion rlm@103: 0x13 :super-potion rlm@103: 0x14 :potion rlm@103: 0x15 :boulderbadge rlm@103: 0x16 :cascadebadge rlm@103: 0x17 :thunderbadge rlm@103: 0x18 :rainbowbadge rlm@103: 0x19 :soulbadge rlm@103: 0x1A :marshbadge rlm@103: 0x1B :volcanobadge rlm@103: 0x1C :earthbadge rlm@103: 0x1D :escape-rope rlm@103: 0x1E :repel rlm@103: 0x1F :old-amber rlm@103: 0x20 :fire-stone rlm@103: 0x21 :thunderstone rlm@103: 0x22 :water-stone rlm@103: 0x23 :hp-up rlm@103: 0x24 :protein rlm@103: 0x25 :iron rlm@103: 0x26 :carbos rlm@103: 0x27 :calcium rlm@103: 0x28 :rare-candy rlm@103: 0x29 :dome-fossil rlm@103: 0x2A :helix-fossil rlm@103: 0x2B :secret-key rlm@103: 0x2D :bike-voucher rlm@103: 0x2E :x-accuracy rlm@103: 0x2F :leaf-stone rlm@103: 0x30 :card-key rlm@103: 0x31 :nugget rlm@103: 0x32 :pp-up rlm@103: 0x33 :poke-doll rlm@103: 0x34 :full-heal rlm@103: 0x35 :revive rlm@103: 0x36 :max-revive rlm@103: 0x37 :guard-spec rlm@103: 0x38 :super-repel rlm@103: 0x39 :max-repel rlm@103: 0x3A :dire-hit rlm@103: 0x3B :coin rlm@103: 0x3C :fresh-water rlm@103: 0x3D :soda-pop rlm@103: 0x3E :lemonade rlm@103: 0x3F :s.s.ticket rlm@103: 0x40 :gold-teeth rlm@103: 0x41 :x-attach rlm@103: 0x42 :x-defend rlm@103: 0x43 :x-speed rlm@103: 0x44 :x-special rlm@103: 0x45 :coin-case rlm@103: 0x46 :oaks-parcel rlm@103: 0x47 :itemfinder rlm@103: 0x48 :silph-scope rlm@103: 0x49 :poke-flute rlm@103: 0x4A :lift-key rlm@103: 0x4B :exp.all rlm@103: 0x4C :old-rod rlm@103: 0x4D :good-rod rlm@103: 0x4E :super-rod rlm@103: 0x4F :pp-up rlm@103: 0x50 :ether rlm@103: 0x51 :max-ether rlm@103: 0x52 :elixer rlm@103: 0x53 :max-elixer rlm@103: 0xC4 :HM01 ;; cut rlm@103: 0xC5 :HM02 ;; fly rlm@103: 0xC6 :HM03 ;; surf rlm@103: 0xC7 :HM04 ;; strength rlm@103: 0xC8 :HM05 ;; flash rlm@103: 0xC9 :TM01 ;; mega punch rlm@103: 0xCA :TM02 ;; razor wind rlm@103: 0xCB :TM03 ;; swords dance rlm@103: 0xCC :TM04 ;; whirlwind rlm@103: 0xCD :TM05 ;; mega kick rlm@103: 0xCE :TM06 ;; toxic rlm@103: 0xCF :TM07 ;; horn drill rlm@103: 0xD0 :TM08 ;; body slam rlm@103: 0xD1 :TM09 ;; take down rlm@103: 0xD2 :TM10 ;; double-edge rlm@103: 0xD3 :TM11 ;; bubblebeam rlm@103: 0xD4 :TM12 ;; water gun rlm@103: 0xD5 :TM13 ;; ice beam rlm@103: 0xD6 :TM14 ;; blizzard rlm@103: 0xD7 :TM15 ;; hyper beam rlm@103: 0xD8 :TM16 ;; pay day rlm@103: 0xD9 :TM17 ;; submission rlm@103: 0xDA :TM18 ;; counter rlm@103: 0xDB :TM19 ;; seismic toss rlm@103: 0xDC :TM20 ;; rage rlm@103: 0xDD :TM21 ;; mega drain rlm@103: 0xDE :TM22 ;; solarbeam rlm@103: 0xDF :TM23 ;; dragon rage rlm@103: 0xE0 :TM24 ;; thunderbolt rlm@103: 0xE1 :TM25 ;; thunder rlm@103: 0xE2 :TM26 ;; earthquake rlm@103: 0xE3 :TM27 ;; fissure rlm@103: 0xE4 :TM28 ;; dig rlm@103: 0xE5 :TM29 ;; psychic rlm@103: 0xE6 :TM30 ;; teleport rlm@103: 0xE7 :TM31 ;; mimic rlm@103: 0xE8 :TM32 ;; double team rlm@103: 0xE9 :TM33 ;; reflect rlm@103: 0xEA :TM34 ;; bide rlm@103: 0xEB :TM35 ;; metronome rlm@103: 0xEC :TM36 ;; self destruct rlm@103: 0xED :TM37 ;; eggbomb rlm@103: 0xEE :TM38 ;; fire blast rlm@103: 0xEF :TM39 ;; swift rlm@103: 0xF0 :TM40 ;; skull bash rlm@103: 0xF1 :TM41 ;; softboiled rlm@103: 0xF2 :TM42 ;; dream eater rlm@103: 0xF3 :TM43 ;; sky attack rlm@103: 0xF4 :TM44 ;; rest rlm@103: 0xF5 :TM45 ;; thunder wave rlm@103: 0xF6 :TM46 ;; psywave rlm@103: 0xF7 :TM47 ;; explosion rlm@103: 0xF8 :TM48 ;; rock slide rlm@103: 0xF9 :TM49 ;; tri attack rlm@103: 0xFA :TM50 ;; substitute rlm@103: 0xFB :TM51 ;; "cut" rlm@103: 0xFC :TM52 ;; "fly" rlm@103: 0xFD :TM53 ;; "surf" rlm@103: 0xFE :TM54 ;; "strength" rlm@103: 0xFF :end-of-list-sentinel rlm@103: )) rlm@98: rlm@99: (def item-name->item-code rlm@99: (zipmap (vals item-code->item-name) rlm@99: (keys item-code->item-name))) rlm@98: rlm@99: (defn inventory [^SaveState state] rlm@99: (let [items (item-list state)] rlm@99: (map rlm@99: (fn [[item-code quantity]] rlm@103: [(item-code->item-name rlm@103: item-code rlm@103: (str ":0x" (.toUpperCase (Integer/toHexString item-code)))) rlm@99: quantity]) rlm@99: (partition rlm@99: 2 rlm@99: (next (take-while (partial not= 255) items)))))) rlm@98: rlm@102: (defn print-inventory rlm@102: ([] (print-inventory @current-state)) rlm@102: ([^SaveState state] rlm@102: (println rlm@102: (let [inv (inventory state)] rlm@102: (reduce rlm@102: str rlm@102: (concat rlm@102: ["+-------------------+----------+\n" rlm@102: "|##| Item | Quantity |\n" rlm@102: "+--+----------------+----------+\n"] rlm@98: rlm@102: (map rlm@102: (fn [index [item-name quantity]] rlm@102: (str rlm@102: (format "|%-2d| %-14s | %3d |\n" index rlm@102: (apply str (rest (str item-name))) rlm@102: quantity))) rlm@102: (range 0 (count inv)) inv) rlm@105: ["+--+----------------+----------+\n"])))) rlm@105: state)) rlm@98: rlm@99: (defn inventory-codes [inventory] rlm@99: (flatten rlm@99: (concat [(count inventory)] rlm@99: (map (fn [[item-name quantity]] rlm@99: [(item-name->item-code item-name) rlm@99: quantity]) inventory) rlm@99: [(item-name->item-code :end-of-list-sentinel)]))) rlm@103: rlm@103: (defn set-inv-mem [^SaveState state inv-codes] rlm@103: (set-state! state) rlm@103: (let [mem (memory state)] rlm@103: (dorun (map (fn [index val] rlm@103: (aset mem index val)) rlm@103: (range item-list-start rlm@103: (+ item-list-start (count inv-codes))) inv-codes)) rlm@103: (write-memory! mem))) rlm@103: rlm@98: rlm@99: (defn set-inventory [^SaveState state new-inventory] rlm@99: (set-state! state) rlm@99: (let [mem (memory state) rlm@99: inv (inventory-codes new-inventory)] rlm@98: rlm@99: (dorun (map (fn [index val] rlm@99: (aset mem index val)) rlm@99: (range item-list-start rlm@99: (+ item-list-start (count inv))) inv)) rlm@99: (write-memory! mem) rlm@99: (update-state))) rlm@102: rlm@103: (defn give rlm@103: ([^SaveState state items] rlm@103: (set-inventory state rlm@103: (concat items (inventory state)))) rlm@103: ([items] rlm@103: (give @current-state items))) rlm@103: rlm@103: rlm@102: (def gliched-tms rlm@102: [[:TM51 1] rlm@102: [:TM52 1] rlm@102: [:TM53 1] rlm@102: [:TM54 1]]) rlm@102: rlm@102: (def good-items rlm@102: [[:bicycle 1] rlm@102: [:ultra-ball 15] rlm@102: [:pp-up 1] rlm@102: [:master-ball 5] rlm@102: [:rare-candy 99] rlm@102: [:full-restore 25] rlm@102: [:max-revive 8] rlm@102: [:max-repel 40] rlm@102: [:TM25 1] rlm@102: [:TM11 1] rlm@102: [:TM15 1] rlm@102: ]) rlm@98: rlm@102: (def some-badges rlm@102: [[:cascadebadge 1] rlm@102: [:thunderbadge 1] rlm@102: [:rainbowbadge 1] rlm@102: [:soulbadge 1] rlm@102: ]) rlm@102: rlm@102: (defn run-item-program rlm@102: "This is my first assembly/item program! rlm@102: it just increments BC by one. rlm@102: rlm@103: The code places a 3 'great balls' at the beginning of the rlm@102: inventory, then directly sets the program counter to start rlm@103: executing at the position of the 'great balls' in memory. rlm@102: rlm@102: Since a 'great ball' is represented in memory as 0x03, which rlm@102: corresponts to the opcode which increments BC by one, that is rlm@103: what happens. Then the program counter to the 0x03 quantity entry rlm@103: and BC is incremented again. rlm@102: rlm@102: Obviously, the game crashes more or less immediately after the rlm@103: program counter advances past the 'great balls' into the next items rlm@103: in the inventory, thus I call shutdown! before anything bad happens." rlm@102: [] rlm@103: (set-inventory (read-state 578544) [[:great-ball 3]]) rlm@102: (print-inventory) rlm@102: (println "3 ticks") (tick) (tick) (tick) rlm@102: (println "PC before:" (PC)) rlm@102: (println "BC before:" (BC)) rlm@102: (PC! (inc item-list-start)) rlm@102: (println "PC after setting:" (PC)) rlm@102: (println "data at PC:" (aget (memory) (PC))) rlm@102: (println "one tick") rlm@102: (tick) rlm@102: (println "PC after one tick:" (PC)) rlm@103: (println "BC after one tick:" (BC)) rlm@103: (tick) rlm@103: (println "PC after two ticks:" (PC)) rlm@103: (println "BC after two ticks:" (BC)) rlm@103: rlm@103: (shutdown!)) rlm@103: rlm@103: rlm@103: (defn test-opcodes-1 rlm@103: [] rlm@103: (set-inv-mem (read-state 578544) rlm@103: [20 0x02 0x00 0x00 0x02 0x00 0x00 rlm@103: 0x00 0x0 0xFF]) rlm@103: (print-inventory) rlm@103: (println "3 ticks") (tick) (tick) (tick) rlm@103: (println "PC before:" (PC)) rlm@103: (println "BC before:" (BC)) rlm@103: (println "AF:" (AF)) rlm@103: (PC! (inc item-list-start)) rlm@103: (BC! (+ 1 item-list-start)) rlm@103: (println "PC after setting:" (PC)) rlm@103: (println "data at PC:" (aget (memory) (PC))) rlm@103: (println "data at " (BC) "(BC):" (aget (memory) (BC))) rlm@103: rlm@103: (println "one tick") rlm@103: (tick) rlm@103: (println "PC after one tick:" (PC)) rlm@103: (println "BC after one tick:" (BC)) rlm@103: (println "data at PC:" (aget (memory) (PC))) rlm@103: (println "data at " (BC) "(BC):" (aget (memory) (BC))) rlm@103: (tick) rlm@103: (AF! 0xFFFF) rlm@103: (println "PC after two ticks:" (PC)) rlm@103: (println "BC after two ticks:" (BC)) rlm@103: (println "data at PC:" (aget (memory) (PC))) rlm@103: (println "data at " (BC) "(BC):" (aget (memory) (BC))) rlm@103: (tick) rlm@103: (println "PC after three ticks:" (PC)) rlm@103: (println "BC after three ticks:" (BC)) rlm@103: (println "data at PC:" (aget (memory) (PC))) rlm@103: (println "data at " (BC) "(BC):" (aget (memory) (BC))) rlm@103: (tick) rlm@103: (println "PC after four ticks:" (PC)) rlm@103: (println "BC after four ticks:" (BC)) rlm@103: (println "data at PC:" (aget (memory) (PC))) rlm@103: (println "data at " (BC) "(BC):" (aget (memory) (BC))) rlm@103: (tick) rlm@103: (println "PC after five ticks:" (PC)) rlm@103: (println "BC after five ticks:" (BC)) rlm@103: (println "data at PC:" (aget (memory) (PC))) rlm@103: (println "data at " (BC) "(BC):" (aget (memory) (BC))) rlm@103: (print-inventory) rlm@103: (shutdown!)) rlm@103: rlm@103: rlm@103: rlm@103: (defn test-opcodes-2 rlm@103: [] rlm@103: (set-inv-mem (read-state 578544) rlm@103: [20 0x08 0x1D 0xD3 0x00 0x00 0x00 rlm@103: 0x00 0x0 0xFF]) rlm@103: (print-inventory) rlm@103: (println "3 ticks") (tick) (tick) (tick) rlm@103: (println "PC before:" (PC)) rlm@103: (println "SP:" (SP)) rlm@103: (PC! (inc item-list-start)) rlm@103: (println "PC after setting:" (PC)) rlm@103: (println "SP:" (Integer/toBinaryString (SP))) rlm@103: (println "data at PC:" (aget (memory) (PC))) rlm@103: (println "data at 0xD31D:" (Integer/toBinaryString (aget (memory) 0xD31D))) rlm@103: (println "data at 0xD31E:" (Integer/toBinaryString (aget (memory) 0xD31E))) rlm@103: (println "one tick") rlm@103: (tick) rlm@103: (println "PC after one tick:" (PC)) rlm@103: (println "data at PC:" (aget (memory) (PC))) rlm@103: (println "data at 0xD31D:" (Integer/toBinaryString (aget (memory) 0xD31D))) rlm@103: (println "data at 0xD31E:" (Integer/toBinaryString (aget (memory) 0xD31E))) rlm@103: (tick) (tick) (tick) rlm@103: (println "PC aftter four tick:" (PC)) rlm@103: (println "data at PC:" (aget (memory) (PC))) rlm@103: (println "data at 0xD31D:" (aget (memory) 0xD31D)) rlm@103: rlm@103: (print-inventory) rlm@103: (shutdown!))