Mercurial > vba-clojure
changeset 414:0162dd315814
moved asseitem-writer assembly to rlm-assembly.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 14 Apr 2012 03:22:10 -0500 |
parents | 70e313aeaa91 |
children | f2f1e0b8c1c7 |
files | clojure/com/aurellem/gb/constants.clj clojure/com/aurellem/gb/rlm_assembly.clj clojure/com/aurellem/run/bootstrap_1.clj |
diffstat | 3 files changed, 222 insertions(+), 156 deletions(-) [+] |
line wrap: on
line diff
1.1 --- a/clojure/com/aurellem/gb/constants.clj Sat Apr 14 01:32:49 2012 -0500 1.2 +++ b/clojure/com/aurellem/gb/constants.clj Sat Apr 14 03:22:10 2012 -0500 1.3 @@ -11,4 +11,6 @@ 1.4 1.5 (def D-memory-end 0xD41B) 1.6 1.7 -(def pokemon-list-start 0xD162) 1.8 \ No newline at end of file 1.9 +(def pokemon-list-start 0xD162) 1.10 + 1.11 +(def pokemon-box-1-address 0xDA7F) 1.12 \ No newline at end of file
2.1 --- a/clojure/com/aurellem/gb/rlm_assembly.clj Sat Apr 14 01:32:49 2012 -0500 2.2 +++ b/clojure/com/aurellem/gb/rlm_assembly.clj Sat Apr 14 03:22:10 2012 -0500 2.3 @@ -2,9 +2,133 @@ 2.4 "Version of main bootstrap program that is valid output for the 2.5 item-writer program." 2.6 (:use (com.aurellem.gb gb-driver assembly util vbm constants)) 2.7 - (:use (com.aurellem.run bootstrap-1)) 2.8 (:import [com.aurellem.gb.gb_driver SaveState])) 2.9 2.10 +(defn pc-item-writer-program 2.11 + [] 2.12 + (let [limit 201 2.13 + [target-high target-low] (disect-bytes-2 pokemon-list-start)] 2.14 + (flatten 2.15 + [[0x00 ;; (item-hack) set increment stack pointer no-op 2.16 + 0x1E ;; load limit into E 2.17 + limit 2.18 + 0x3F ;; (item-hack) set carry flag no-op 2.19 + 2.20 + ;; load 2 into C. 2.21 + 0x0E ;; C == 1 means input-first nybble 2.22 + 0x04 ;; C == 0 means input-second nybble 2.23 + 2.24 + 0x21 ;; load target into HL 2.25 + target-low 2.26 + target-high 2.27 + 0x37 ;; (item-hack) set carry flag no-op 2.28 + 2.29 + 0x00 ;; (item-hack) no-op 2.30 + 0x37 ;; (item-hack) set carry flag no-op 2.31 + 2.32 + 0x00 ;; (item-hack) no-op 2.33 + 0xF3 ;; disable interrupts 2.34 + ;; Input Section 2.35 + 2.36 + 0x3E ;; load 0x20 into A, to measure buttons 2.37 + 0x10 2.38 + 2.39 + 0x00 ;; (item-hack) no-op 2.40 + 0xE0 ;; load A into [FF00] 2.41 + 0x00 2.42 + 2.43 + 0xF0 ;; load 0xFF00 into A to get 2.44 + 0x00 ;; button presses 2.45 + 2.46 + 0xE6 2.47 + 0x0F ;; select bottom four bits of A 2.48 + 0x37 ;; (item-hack) set carry flag no-op 2.49 + 2.50 + 0x00 ;; (item-hack) no-op 2.51 + 0xB8 ;; see if input is different (CP A B) 2.52 + 2.53 + 0x00 ;; (item-hack) (INC SP) 2.54 + 0x28 ;; repeat above steps if input is not different 2.55 + ;; (jump relative backwards if B != A) 2.56 + 0xED ;; (literal -19) (item-hack) -19 == egg bomb (TM37) 2.57 + 2.58 + 0x47 ;; load A into B 2.59 + 2.60 + 0x0D ;; dec C 2.61 + 0x37 ;; (item-hack) set-carry flag 2.62 + ;; branch based on C: 2.63 + 0x20 ;; JR NZ 2.64 + 23 ;; skip "input second nybble" and "jump to target" below 2.65 + 2.66 + ;; input second nybble 2.67 + 2.68 + 0x0C ;; inc C 2.69 + 0x0C ;; inc C 2.70 + 2.71 + 0x00 ;; (item-hack) no-op 2.72 + 0xE6 ;; select bottom bits 2.73 + 0x0F 2.74 + 0x37 ;; (item-hack) set-carry flag no-op 2.75 + 2.76 + 0x00 ;; (item-hack) no-op 2.77 + 0xB2 ;; (OR A D) -> A 2.78 + 2.79 + 0x22 ;; (do (A -> (HL)) (INC HL)) 2.80 + 2.81 + 0x1D ;; (DEC E) 2.82 + 2.83 + 0x00 ;; (item-hack) 2.84 + 0x20 ;; jump back to input section if not done 2.85 + 0xDA ;; literal -36 == TM 18 (counter) 2.86 + 0x01 ;; (item-hack) set BC to literal (no-op) 2.87 + 2.88 + ;; jump to target 2.89 + 0x00 ;; (item-hack) these two bytes can be anything. 2.90 + 0x01 2.91 + 2.92 + 0x00 ;; (item-hack) no-op 2.93 + 0xBF ;; (CP A A) ensures Z 2.94 + 2.95 + 0xCA ;; (item-hack) jump if Z 2.96 + target-low 2.97 + target-high 2.98 + 0x01 ;; (item-hack) will never be reached. 2.99 + 2.100 + ;; input first nybble 2.101 + 0x00 2.102 + 0xCB 2.103 + 0x37 ;; swap nybbles on A 2.104 + 2.105 + 0x57 ;; A -> D 2.106 + 2.107 + 0x37 ;; (item-hack) set carry flag no-op 2.108 + 0x18 ;; relative jump backwards 2.109 + 0xCD ;; literal -51 == TM05; go back to input section 2.110 + 0x01 ;; (item-hack) will never reach this instruction 2.111 + 2.112 + ] 2.113 + (repeat 8 [0x00 0x01]);; these can be anything 2.114 + 2.115 + [;; jump to actual program 2.116 + 0x00 2.117 + 0x37 ;; (item-hack) set carry flag no-op 2.118 + 2.119 + 0x2E ;; 0x3A -> L 2.120 + 0x3A 2.121 + 2.122 + 2.123 + 0x00 ;; (item-hack) no-op 2.124 + 0x26 ;; 0xD5 -> L 2.125 + 0xD5 2.126 + 0x01 ;; (item-hack) set-carry BC 2.127 + 2.128 + 0x00 ;; (item-hack) these can be anything 2.129 + 0x01 2.130 + 2.131 + 0x00 2.132 + 0xE9 ;; jump to (HL) 2.133 + ]]))) 2.134 + 2.135 2.136 2.137 ;; Specs for Main Bootstrap Program 2.138 @@ -339,7 +463,34 @@ 2.139 program 2.140 (replace resolve-external-jumps program*)] 2.141 program))) 2.142 - 2.143 + 2.144 + 2.145 +(defn no-consecutive-repeats? [seq] 2.146 + (not (contains? (set(map - seq (rest seq))) 0))) 2.147 + 2.148 +(defn byte->nybbles [byte] 2.149 + [(bit-shift-right byte 4) (bit-and byte 0x0F)]) 2.150 + 2.151 +(defn bootstrap-pattern 2.152 + "Given an assembly sequence, generate the keypresses required to 2.153 + create that sequence in memory using the pc-item-writer 2.154 + program. The assembly must not have any consecutive repeating 2.155 + nybbles." 2.156 + [assembly] 2.157 + (let [nybbles (flatten (map byte->nybbles assembly)) 2.158 + moves (map (comp buttons (partial - 15)) nybbles) 2.159 + header (map buttons 2.160 + (concat (repeat 2.161 + 50 2.162 + (- 15 (first nybbles))) 2.163 + [(first nybbles)])) 2.164 + tail (map buttons 2.165 + (take 2.166 + (- 201 (count moves)) 2.167 + (interleave (repeat 100 (last nybbles)) 2.168 + (repeat 1000 (- 15 (last nybbles))))))] 2.169 + (assert (no-consecutive-repeats? nybbles)) 2.170 + (concat header moves tail))) 2.171 2.172 ;;;;;; TESTS ;;;;;; 2.173
3.1 --- a/clojure/com/aurellem/run/bootstrap_1.clj Sat Apr 14 01:32:49 2012 -0500 3.2 +++ b/clojure/com/aurellem/run/bootstrap_1.clj Sat Apr 14 03:22:10 2012 -0500 3.3 @@ -1,134 +1,11 @@ 3.4 (ns com.aurellem.run.bootstrap-1 3.5 (:use (com.aurellem.gb saves gb-driver util constants 3.6 - items vbm characters money)) 3.7 + items vbm characters money 3.8 + rlm-assembly)) 3.9 (:use (com.aurellem.run util title save-corruption bootstrap-0)) 3.10 (:use (com.aurellem.exp item-bridge)) 3.11 (:import [com.aurellem.gb.gb_driver SaveState])) 3.12 3.13 -(defn pc-item-writer-program 3.14 - [] 3.15 - (let [limit 201 3.16 - [target-high target-low] (disect-bytes-2 pokemon-list-start)] 3.17 - (flatten 3.18 - [[0x00 ;; (item-hack) set increment stack pointer no-op 3.19 - 0x1E ;; load limit into E 3.20 - limit 3.21 - 0x3F ;; (item-hack) set carry flag no-op 3.22 - 3.23 - ;; load 2 into C. 3.24 - 0x0E ;; C == 1 means input-first nybble 3.25 - 0x04 ;; C == 0 means input-second nybble 3.26 - 3.27 - 0x21 ;; load target into HL 3.28 - target-low 3.29 - target-high 3.30 - 0x37 ;; (item-hack) set carry flag no-op 3.31 - 3.32 - 0x00 ;; (item-hack) no-op 3.33 - 0x37 ;; (item-hack) set carry flag no-op 3.34 - 3.35 - 0x00 ;; (item-hack) no-op 3.36 - 0xF3 ;; disable interrupts 3.37 - ;; Input Section 3.38 - 3.39 - 0x3E ;; load 0x20 into A, to measure buttons 3.40 - 0x10 3.41 - 3.42 - 0x00 ;; (item-hack) no-op 3.43 - 0xE0 ;; load A into [FF00] 3.44 - 0x00 3.45 - 3.46 - 0xF0 ;; load 0xFF00 into A to get 3.47 - 0x00 ;; button presses 3.48 - 3.49 - 0xE6 3.50 - 0x0F ;; select bottom four bits of A 3.51 - 0x37 ;; (item-hack) set carry flag no-op 3.52 - 3.53 - 0x00 ;; (item-hack) no-op 3.54 - 0xB8 ;; see if input is different (CP A B) 3.55 - 3.56 - 0x00 ;; (item-hack) (INC SP) 3.57 - 0x28 ;; repeat above steps if input is not different 3.58 - ;; (jump relative backwards if B != A) 3.59 - 0xED ;; (literal -19) (item-hack) -19 == egg bomb (TM37) 3.60 - 3.61 - 0x47 ;; load A into B 3.62 - 3.63 - 0x0D ;; dec C 3.64 - 0x37 ;; (item-hack) set-carry flag 3.65 - ;; branch based on C: 3.66 - 0x20 ;; JR NZ 3.67 - 23 ;; skip "input second nybble" and "jump to target" below 3.68 - 3.69 - ;; input second nybble 3.70 - 3.71 - 0x0C ;; inc C 3.72 - 0x0C ;; inc C 3.73 - 3.74 - 0x00 ;; (item-hack) no-op 3.75 - 0xE6 ;; select bottom bits 3.76 - 0x0F 3.77 - 0x37 ;; (item-hack) set-carry flag no-op 3.78 - 3.79 - 0x00 ;; (item-hack) no-op 3.80 - 0xB2 ;; (OR A D) -> A 3.81 - 3.82 - 0x22 ;; (do (A -> (HL)) (INC HL)) 3.83 - 3.84 - 0x1D ;; (DEC E) 3.85 - 3.86 - 0x00 ;; (item-hack) 3.87 - 0x20 ;; jump back to input section if not done 3.88 - 0xDA ;; literal -36 == TM 18 (counter) 3.89 - 0x01 ;; (item-hack) set BC to literal (no-op) 3.90 - 3.91 - ;; jump to target 3.92 - 0x00 ;; (item-hack) these two bytes can be anything. 3.93 - 0x01 3.94 - 3.95 - 0x00 ;; (item-hack) no-op 3.96 - 0xBF ;; (CP A A) ensures Z 3.97 - 3.98 - 0xCA ;; (item-hack) jump if Z 3.99 - target-low 3.100 - target-high 3.101 - 0x01 ;; (item-hack) will never be reached. 3.102 - 3.103 - ;; input first nybble 3.104 - 0x00 3.105 - 0xCB 3.106 - 0x37 ;; swap nybbles on A 3.107 - 3.108 - 0x57 ;; A -> D 3.109 - 3.110 - 0x37 ;; (item-hack) set carry flag no-op 3.111 - 0x18 ;; relative jump backwards 3.112 - 0xCD ;; literal -51 == TM05; go back to input section 3.113 - 0x01 ;; (item-hack) will never reach this instruction 3.114 - 3.115 - ] 3.116 - (repeat 8 [0x00 0x01]);; these can be anything 3.117 - 3.118 - [;; jump to actual program 3.119 - 0x00 3.120 - 0x37 ;; (item-hack) set carry flag no-op 3.121 - 3.122 - 0x2E ;; 0x3A -> L 3.123 - 0x3A 3.124 - 3.125 - 3.126 - 0x00 ;; (item-hack) no-op 3.127 - 0x26 ;; 0xD5 -> L 3.128 - 0xD5 3.129 - 0x01 ;; (item-hack) set-carry BC 3.130 - 3.131 - 0x00 ;; (item-hack) these can be anything 3.132 - 0x01 3.133 - 3.134 - 0x00 3.135 - 0xE9 ;; jump to (HL) 3.136 - ]]))) 3.137 3.138 (defn print-desired-item-layout [] 3.139 (clojure.pprint/pprint 3.140 @@ -882,33 +759,6 @@ 3.141 (defn control-checkpoint [] 3.142 (read-script "control-checkpoint")) 3.143 3.144 -(defn no-consecutive-repeats? [seq] 3.145 - (not (contains? (set(map - seq (rest seq))) 0))) 3.146 - 3.147 -(defn byte->nybbles [byte] 3.148 - [(bit-shift-right byte 4) (bit-and byte 0x0F)]) 3.149 - 3.150 -(defn bootstrap-pattern 3.151 - "Given an assembly sequence, generate the keypresses required to 3.152 - create that sequence in memory using the pc-item-writer 3.153 - program. The assembly must not have any consecutive repeating 3.154 - nybbles." 3.155 - [assembly] 3.156 - (let [nybbles (flatten (map byte->nybbles assembly)) 3.157 - moves (map (comp buttons (partial - 15)) nybbles) 3.158 - header (map buttons 3.159 - (concat (repeat 3.160 - 50 3.161 - (- 15 (first nybbles))) 3.162 - [(first nybbles)])) 3.163 - tail (map buttons 3.164 - (take 3.165 - (- 201 (count moves)) 3.166 - (interleave (repeat 100 (last nybbles)) 3.167 - (repeat 1000 (- 15 (last nybbles))))))] 3.168 - (assert (no-consecutive-repeats? nybbles)) 3.169 - (concat header moves tail))) 3.170 - 3.171 (def increasing-pattern [0x01 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF]) 3.172 3.173 (defn test-pattern-writing 3.174 @@ -928,5 +778,68 @@ 3.175 0xD162 (+ 0xD162 (count pattern))) 3.176 pattern)))) 3.177 3.178 +(defn-memo launch-main-bootstrap-program 3.179 + ([] (launch-main-bootstrap-program 3.180 + (control-checkpoint) 3.181 + ;;(launch-bootstrap-program) 3.182 + )) 3.183 + ([script] 3.184 + (->> script 3.185 + (play-moves 3.186 + (bootstrap-pattern (main-bootstrap-program)))))) 3.187 3.188 - 3.189 \ No newline at end of file 3.190 +(defn set-target-address 3.191 + "Assumes that the game is under control of the main-bootstrap 3.192 + program in MODE-SELECT mode, and sets the target address to which 3.193 + jumps/writes will occur." 3.194 + [target-address script] 3.195 + (let [[target-high target-low] (disect-bytes-2 target-address)] 3.196 + (->> script 3.197 + (play-moves 3.198 + (map buttons 3.199 + [set-H-mode target-high 0x00 3.200 + set-L-mode target-low 0x00]))))) 3.201 + 3.202 +(defn write-RAM 3.203 + "Assumes that the game is under control of the main-bootstrap 3.204 + program in MODE-SELECT mode, and rewrites RAM starting at 3.205 + 'start-address with 'new-ram." 3.206 + [start-address new-ram script] 3.207 + (->> script 3.208 + (set-target-address start-address) 3.209 + (play-moves [(buttons (count new-ram))]) 3.210 + (play-moves (map buttons new-ram)))) 3.211 + 3.212 +(defn transfer-control 3.213 + "Assumes that the game is under control of the main-bootstrap 3.214 + program in MODE-SELECT mode, and jumps to the target-address." 3.215 + [target-address script] 3.216 + (->> script 3.217 + (set-target-address target-address) 3.218 + (play-moves [(buttons jump-mode)]))) 3.219 + 3.220 +(defn-memo relocate-main-bootstrap 3.221 + ([] (relocate-main-bootstrap (launch-main-bootstrap-program))) 3.222 + ([script] 3.223 + (let [target (+ 90 pokemon-box-1-address)] 3.224 + (->> script 3.225 + (write-RAM target (main-bootstrap-program target)) 3.226 + (transfer-control target))))) 3.227 + 3.228 +(def mid-game-data 3.229 + (subvec (vec (memory (mid-game))) 3.230 + pokemon-list-start 3.231 + (+ pokemon-list-start 700))) 3.232 + 3.233 +(def mid-game-map-address 0x46BC) 3.234 + 3.235 +(defn set-mid-game-data 3.236 + ([] (set-mid-game-data (relocate-main-bootstrap))) 3.237 + ([script] 3.238 + (->> script 3.239 + (write-RAM pokemon-list-start mid-game-data) 3.240 + (transfer-control mid-game-map-address)))) 3.241 + 3.242 + 3.243 + 3.244 +