# HG changeset patch # User Robert McIntyre # Date 1334391730 18000 # Node ID 0162dd315814fc31dbb7b78bb7f3e140cd3ced71 # Parent 70e313aeaa9130e6e5e1ce7a0eabb8d6afe91926 moved asseitem-writer assembly to rlm-assembly. diff -r 70e313aeaa91 -r 0162dd315814 clojure/com/aurellem/gb/constants.clj --- a/clojure/com/aurellem/gb/constants.clj Sat Apr 14 01:32:49 2012 -0500 +++ b/clojure/com/aurellem/gb/constants.clj Sat Apr 14 03:22:10 2012 -0500 @@ -11,4 +11,6 @@ (def D-memory-end 0xD41B) -(def pokemon-list-start 0xD162) \ No newline at end of file +(def pokemon-list-start 0xD162) + +(def pokemon-box-1-address 0xDA7F) \ No newline at end of file diff -r 70e313aeaa91 -r 0162dd315814 clojure/com/aurellem/gb/rlm_assembly.clj --- a/clojure/com/aurellem/gb/rlm_assembly.clj Sat Apr 14 01:32:49 2012 -0500 +++ b/clojure/com/aurellem/gb/rlm_assembly.clj Sat Apr 14 03:22:10 2012 -0500 @@ -2,9 +2,133 @@ "Version of main bootstrap program that is valid output for the item-writer program." (:use (com.aurellem.gb gb-driver assembly util vbm constants)) - (:use (com.aurellem.run bootstrap-1)) (:import [com.aurellem.gb.gb_driver SaveState])) +(defn pc-item-writer-program + [] + (let [limit 201 + [target-high target-low] (disect-bytes-2 pokemon-list-start)] + (flatten + [[0x00 ;; (item-hack) set increment stack pointer no-op + 0x1E ;; load limit into E + limit + 0x3F ;; (item-hack) set carry flag no-op + + ;; load 2 into C. + 0x0E ;; C == 1 means input-first nybble + 0x04 ;; C == 0 means input-second nybble + + 0x21 ;; load target into HL + target-low + target-high + 0x37 ;; (item-hack) set carry flag no-op + + 0x00 ;; (item-hack) no-op + 0x37 ;; (item-hack) set carry flag no-op + + 0x00 ;; (item-hack) no-op + 0xF3 ;; disable interrupts + ;; Input Section + + 0x3E ;; load 0x20 into A, to measure buttons + 0x10 + + 0x00 ;; (item-hack) no-op + 0xE0 ;; load A into [FF00] + 0x00 + + 0xF0 ;; load 0xFF00 into A to get + 0x00 ;; button presses + + 0xE6 + 0x0F ;; select bottom four bits of A + 0x37 ;; (item-hack) set carry flag no-op + + 0x00 ;; (item-hack) no-op + 0xB8 ;; see if input is different (CP A B) + + 0x00 ;; (item-hack) (INC SP) + 0x28 ;; repeat above steps if input is not different + ;; (jump relative backwards if B != A) + 0xED ;; (literal -19) (item-hack) -19 == egg bomb (TM37) + + 0x47 ;; load A into B + + 0x0D ;; dec C + 0x37 ;; (item-hack) set-carry flag + ;; branch based on C: + 0x20 ;; JR NZ + 23 ;; skip "input second nybble" and "jump to target" below + + ;; input second nybble + + 0x0C ;; inc C + 0x0C ;; inc C + + 0x00 ;; (item-hack) no-op + 0xE6 ;; select bottom bits + 0x0F + 0x37 ;; (item-hack) set-carry flag no-op + + 0x00 ;; (item-hack) no-op + 0xB2 ;; (OR A D) -> A + + 0x22 ;; (do (A -> (HL)) (INC HL)) + + 0x1D ;; (DEC E) + + 0x00 ;; (item-hack) + 0x20 ;; jump back to input section if not done + 0xDA ;; literal -36 == TM 18 (counter) + 0x01 ;; (item-hack) set BC to literal (no-op) + + ;; jump to target + 0x00 ;; (item-hack) these two bytes can be anything. + 0x01 + + 0x00 ;; (item-hack) no-op + 0xBF ;; (CP A A) ensures Z + + 0xCA ;; (item-hack) jump if Z + target-low + target-high + 0x01 ;; (item-hack) will never be reached. + + ;; input first nybble + 0x00 + 0xCB + 0x37 ;; swap nybbles on A + + 0x57 ;; A -> D + + 0x37 ;; (item-hack) set carry flag no-op + 0x18 ;; relative jump backwards + 0xCD ;; literal -51 == TM05; go back to input section + 0x01 ;; (item-hack) will never reach this instruction + + ] + (repeat 8 [0x00 0x01]);; these can be anything + + [;; jump to actual program + 0x00 + 0x37 ;; (item-hack) set carry flag no-op + + 0x2E ;; 0x3A -> L + 0x3A + + + 0x00 ;; (item-hack) no-op + 0x26 ;; 0xD5 -> L + 0xD5 + 0x01 ;; (item-hack) set-carry BC + + 0x00 ;; (item-hack) these can be anything + 0x01 + + 0x00 + 0xE9 ;; jump to (HL) + ]]))) + ;; Specs for Main Bootstrap Program @@ -339,7 +463,34 @@ program (replace resolve-external-jumps program*)] program))) - + + +(defn no-consecutive-repeats? [seq] + (not (contains? (set(map - seq (rest seq))) 0))) + +(defn byte->nybbles [byte] + [(bit-shift-right byte 4) (bit-and byte 0x0F)]) + +(defn bootstrap-pattern + "Given an assembly sequence, generate the keypresses required to + create that sequence in memory using the pc-item-writer + program. The assembly must not have any consecutive repeating + nybbles." + [assembly] + (let [nybbles (flatten (map byte->nybbles assembly)) + moves (map (comp buttons (partial - 15)) nybbles) + header (map buttons + (concat (repeat + 50 + (- 15 (first nybbles))) + [(first nybbles)])) + tail (map buttons + (take + (- 201 (count moves)) + (interleave (repeat 100 (last nybbles)) + (repeat 1000 (- 15 (last nybbles))))))] + (assert (no-consecutive-repeats? nybbles)) + (concat header moves tail))) ;;;;;; TESTS ;;;;;; diff -r 70e313aeaa91 -r 0162dd315814 clojure/com/aurellem/run/bootstrap_1.clj --- a/clojure/com/aurellem/run/bootstrap_1.clj Sat Apr 14 01:32:49 2012 -0500 +++ b/clojure/com/aurellem/run/bootstrap_1.clj Sat Apr 14 03:22:10 2012 -0500 @@ -1,134 +1,11 @@ (ns com.aurellem.run.bootstrap-1 (:use (com.aurellem.gb saves gb-driver util constants - items vbm characters money)) + items vbm characters money + rlm-assembly)) (:use (com.aurellem.run util title save-corruption bootstrap-0)) (:use (com.aurellem.exp item-bridge)) (:import [com.aurellem.gb.gb_driver SaveState])) -(defn pc-item-writer-program - [] - (let [limit 201 - [target-high target-low] (disect-bytes-2 pokemon-list-start)] - (flatten - [[0x00 ;; (item-hack) set increment stack pointer no-op - 0x1E ;; load limit into E - limit - 0x3F ;; (item-hack) set carry flag no-op - - ;; load 2 into C. - 0x0E ;; C == 1 means input-first nybble - 0x04 ;; C == 0 means input-second nybble - - 0x21 ;; load target into HL - target-low - target-high - 0x37 ;; (item-hack) set carry flag no-op - - 0x00 ;; (item-hack) no-op - 0x37 ;; (item-hack) set carry flag no-op - - 0x00 ;; (item-hack) no-op - 0xF3 ;; disable interrupts - ;; Input Section - - 0x3E ;; load 0x20 into A, to measure buttons - 0x10 - - 0x00 ;; (item-hack) no-op - 0xE0 ;; load A into [FF00] - 0x00 - - 0xF0 ;; load 0xFF00 into A to get - 0x00 ;; button presses - - 0xE6 - 0x0F ;; select bottom four bits of A - 0x37 ;; (item-hack) set carry flag no-op - - 0x00 ;; (item-hack) no-op - 0xB8 ;; see if input is different (CP A B) - - 0x00 ;; (item-hack) (INC SP) - 0x28 ;; repeat above steps if input is not different - ;; (jump relative backwards if B != A) - 0xED ;; (literal -19) (item-hack) -19 == egg bomb (TM37) - - 0x47 ;; load A into B - - 0x0D ;; dec C - 0x37 ;; (item-hack) set-carry flag - ;; branch based on C: - 0x20 ;; JR NZ - 23 ;; skip "input second nybble" and "jump to target" below - - ;; input second nybble - - 0x0C ;; inc C - 0x0C ;; inc C - - 0x00 ;; (item-hack) no-op - 0xE6 ;; select bottom bits - 0x0F - 0x37 ;; (item-hack) set-carry flag no-op - - 0x00 ;; (item-hack) no-op - 0xB2 ;; (OR A D) -> A - - 0x22 ;; (do (A -> (HL)) (INC HL)) - - 0x1D ;; (DEC E) - - 0x00 ;; (item-hack) - 0x20 ;; jump back to input section if not done - 0xDA ;; literal -36 == TM 18 (counter) - 0x01 ;; (item-hack) set BC to literal (no-op) - - ;; jump to target - 0x00 ;; (item-hack) these two bytes can be anything. - 0x01 - - 0x00 ;; (item-hack) no-op - 0xBF ;; (CP A A) ensures Z - - 0xCA ;; (item-hack) jump if Z - target-low - target-high - 0x01 ;; (item-hack) will never be reached. - - ;; input first nybble - 0x00 - 0xCB - 0x37 ;; swap nybbles on A - - 0x57 ;; A -> D - - 0x37 ;; (item-hack) set carry flag no-op - 0x18 ;; relative jump backwards - 0xCD ;; literal -51 == TM05; go back to input section - 0x01 ;; (item-hack) will never reach this instruction - - ] - (repeat 8 [0x00 0x01]);; these can be anything - - [;; jump to actual program - 0x00 - 0x37 ;; (item-hack) set carry flag no-op - - 0x2E ;; 0x3A -> L - 0x3A - - - 0x00 ;; (item-hack) no-op - 0x26 ;; 0xD5 -> L - 0xD5 - 0x01 ;; (item-hack) set-carry BC - - 0x00 ;; (item-hack) these can be anything - 0x01 - - 0x00 - 0xE9 ;; jump to (HL) - ]]))) (defn print-desired-item-layout [] (clojure.pprint/pprint @@ -882,33 +759,6 @@ (defn control-checkpoint [] (read-script "control-checkpoint")) -(defn no-consecutive-repeats? [seq] - (not (contains? (set(map - seq (rest seq))) 0))) - -(defn byte->nybbles [byte] - [(bit-shift-right byte 4) (bit-and byte 0x0F)]) - -(defn bootstrap-pattern - "Given an assembly sequence, generate the keypresses required to - create that sequence in memory using the pc-item-writer - program. The assembly must not have any consecutive repeating - nybbles." - [assembly] - (let [nybbles (flatten (map byte->nybbles assembly)) - moves (map (comp buttons (partial - 15)) nybbles) - header (map buttons - (concat (repeat - 50 - (- 15 (first nybbles))) - [(first nybbles)])) - tail (map buttons - (take - (- 201 (count moves)) - (interleave (repeat 100 (last nybbles)) - (repeat 1000 (- 15 (last nybbles))))))] - (assert (no-consecutive-repeats? nybbles)) - (concat header moves tail))) - (def increasing-pattern [0x01 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF]) (defn test-pattern-writing @@ -928,5 +778,68 @@ 0xD162 (+ 0xD162 (count pattern))) pattern)))) +(defn-memo launch-main-bootstrap-program + ([] (launch-main-bootstrap-program + (control-checkpoint) + ;;(launch-bootstrap-program) + )) + ([script] + (->> script + (play-moves + (bootstrap-pattern (main-bootstrap-program)))))) - \ No newline at end of file +(defn set-target-address + "Assumes that the game is under control of the main-bootstrap + program in MODE-SELECT mode, and sets the target address to which + jumps/writes will occur." + [target-address script] + (let [[target-high target-low] (disect-bytes-2 target-address)] + (->> script + (play-moves + (map buttons + [set-H-mode target-high 0x00 + set-L-mode target-low 0x00]))))) + +(defn write-RAM + "Assumes that the game is under control of the main-bootstrap + program in MODE-SELECT mode, and rewrites RAM starting at + 'start-address with 'new-ram." + [start-address new-ram script] + (->> script + (set-target-address start-address) + (play-moves [(buttons (count new-ram))]) + (play-moves (map buttons new-ram)))) + +(defn transfer-control + "Assumes that the game is under control of the main-bootstrap + program in MODE-SELECT mode, and jumps to the target-address." + [target-address script] + (->> script + (set-target-address target-address) + (play-moves [(buttons jump-mode)]))) + +(defn-memo relocate-main-bootstrap + ([] (relocate-main-bootstrap (launch-main-bootstrap-program))) + ([script] + (let [target (+ 90 pokemon-box-1-address)] + (->> script + (write-RAM target (main-bootstrap-program target)) + (transfer-control target))))) + +(def mid-game-data + (subvec (vec (memory (mid-game))) + pokemon-list-start + (+ pokemon-list-start 700))) + +(def mid-game-map-address 0x46BC) + +(defn set-mid-game-data + ([] (set-mid-game-data (relocate-main-bootstrap))) + ([script] + (->> script + (write-RAM pokemon-list-start mid-game-data) + (transfer-control mid-game-map-address)))) + + + +