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 +