changeset 239:19fd38fe376e

revived a functional version of Dylan's assembly.
author Robert McIntyre <rlm@mit.edu>
date Sun, 25 Mar 2012 00:38:45 -0500
parents e23ab90fcc86
children 25022f3c6607
files clojure/com/aurellem/exp/item_bridge.clj clojure/com/aurellem/exp/notes.txt clojure/com/aurellem/gb/assembly.clj clojure/com/aurellem/gb/dylan_assembly.clj
diffstat 4 files changed, 222 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/clojure/com/aurellem/exp/item_bridge.clj	Sun Mar 25 00:08:23 2012 -0500
     1.2 +++ b/clojure/com/aurellem/exp/item_bridge.clj	Sun Mar 25 00:38:45 2012 -0500
     1.3 @@ -197,9 +197,10 @@
     1.4      memory-function-address-start
     1.5      insertion-address-bits))))
     1.6  
     1.7 -(def lemonade-trampoline (partial test-trampoline
     1.8 -                                  trampoline-assembly
     1.9 -                                  (menu-open-state)))
    1.10 +(def lemonade-trampoline
    1.11 +  (partial test-trampoline
    1.12 +           trampoline-assembly
    1.13 +           (menu-open-state)))
    1.14  
    1.15  (defn trampoline-assembly-burn-heal [^SaveState state]
    1.16    (flatten
    1.17 @@ -210,8 +211,8 @@
    1.18      0x1D
    1.19      0xD3 ;; set first item to lemonade
    1.20      
    1.21 -    0xC3 ;; return control to the game via absolute jump.
    1.22 -    0x0C ;; return control to Route 3's map-function
    1.23 +    0xC3 ;; return control to the game via absolute jump
    1.24 +    0x0C ;; to Route 3's map-function
    1.25      0x55
    1.26      ]))
    1.27  
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/clojure/com/aurellem/exp/notes.txt	Sun Mar 25 00:38:45 2012 -0500
     2.3 @@ -0,0 +1,17 @@
     2.4 +start game
     2.5 +
     2.6 +get pikachu, fight rival, deliver oak's parcel
     2.7 +
     2.8 +buy 5 items from viridian store, with the last one being a
     2.9 +burn-heal.
    2.10 +
    2.11 +Perform save corruption.
    2.12 +
    2.13 +move one of the other items that wasn't destroyed (but not
    2.14 +burn-heal) to the money counter to get a bunch of money.
    2.15 +
    2.16 +buy 94 more burn heals.  95 burn heals spells out the
    2.17 +address that will safely return control to pokemon.
    2.18 +
    2.19 +
    2.20 +
     3.1 --- a/clojure/com/aurellem/gb/assembly.clj	Sun Mar 25 00:08:23 2012 -0500
     3.2 +++ b/clojure/com/aurellem/gb/assembly.clj	Sun Mar 25 00:38:45 2012 -0500
     3.3 @@ -1334,30 +1334,6 @@
     3.4          (view-register "L" L)
     3.5          ))))
     3.6    
     3.7 -
     3.8 -
     3.9 -(defn drive-dylan []
    3.10 -  (-> (write-mem-dyl)
    3.11 -      (#(do (println "memory from 0xC00F to 0xC01F:"
    3.12 -                     (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
    3.13 -      (step [])
    3.14 -      (step [])
    3.15 -      (step [])
    3.16 -      (step [:start])
    3.17 -      (step [:select])
    3.18 -      (step [:u :d])
    3.19 -      (step [:a :b :start :select])
    3.20 -      (step [:a])
    3.21 -      (step [:b])
    3.22 -      (step [:a :b])
    3.23 -      (step [:select])
    3.24 -      (step [])
    3.25 -      (step [])
    3.26 -      (step [])
    3.27 -      (#(do (println "memory from 0xC00F to 0xC01F:"
    3.28 -                     (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
    3.29 -      ))
    3.30 -
    3.31  (defn test-mode-4
    3.32    ([] (test-mode-4 (write-memory)))
    3.33    ([target-state]
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/clojure/com/aurellem/gb/dylan_assembly.clj	Sun Mar 25 00:38:45 2012 -0500
     4.3 @@ -0,0 +1,199 @@
     4.4 +(ns com.aurellem.gb.dylan-assembly
     4.5 +  "A much more compact version of write-memory-assembly"
     4.6 +  {:author "Dylan Holmes"}
     4.7 +  (:use (com.aurellem.gb gb-driver assembly util))
     4.8 +  (:import [com.aurellem.gb.gb_driver SaveState]))
     4.9 +
    4.10 +(defn write-memory-assembly-compact
    4.11 +  "Currently, grabs input from the user each frame."
    4.12 +  []
    4.13 +  [
    4.14 +   ;; --------- FRAME METRONOME
    4.15 +   0x18 ;; jump ahead to cleanup. first time only.
    4.16 +   0x40 ;; v-blank-prev [D31E]
    4.17 +
    4.18 +   0xFA ;; load modes into A [D31F]
    4.19 +   0x41
    4.20 +   0xFF
    4.21 +
    4.22 +   0x47 ;; A -> B
    4.23 +   0xCB ;; rotate A
    4.24 +   0x2F
    4.25 +   0x2F ;; invert A
    4.26 +
    4.27 +   0xA0
    4.28 +   0x47 ;; now B_0 contains (VB==1)
    4.29 +
    4.30 +   0xFA ;; load v-blank-prev
    4.31 +   0x1E
    4.32 +   0xD3
    4.33 +
    4.34 +   0x2F ;; complement v-blank-prev
    4.35 +   
    4.36 +   0xA0 ;; A & B --> A
    4.37 +   0x4F ;; now C_0 contains increment?
    4.38 +
    4.39 +
    4.40 +   0x78 ;; B->A
    4.41 +   0xEA ;; spit A --> vbprev
    4.42 +   0x1E
    4.43 +   0xD3
    4.44 +
    4.45 +   0xCB   ;test C_0
    4.46 +   0x41
    4.47 +   0x20   ; JUMP ahead to button input if nonzero
    4.48 +   0x02
    4.49 +   0x18   ; JUMP  back to frame metronome (D31F)
    4.50 +   0xE7
    4.51 +   
    4.52 +   ;; -------- GET BUTTON INPUT
    4.53 +
    4.54 +        ;; btw, C_0 is now 1
    4.55 +        ;; prepare to select bits
    4.56 +
    4.57 +   0x06 ;; load 0x00 into B
    4.58 +   0x00 ;; to initialize for "OR" loop
    4.59 + 
    4.60 +   0x3E ;; load 0x20 into A, to measure dpad
    4.61 +   0x20
    4.62 +
    4.63 +   
    4.64 +   0xE0 ;; load A into [FF00] ;; start of OR loop [D33C]
    4.65 +   0x00
    4.66 +   
    4.67 +   0xF0 ;; load A from [FF00]
    4.68 +   0x00
    4.69 +
    4.70 +   0xE6 ;; bitmask 00001111
    4.71 +   0x0F
    4.72 +   
    4.73 +   0xB0 ;; A or B --> A
    4.74 +   0xCB
    4.75 +   0x41 ;; test bit 0 of C
    4.76 +   0x28 ;; JUMP forward if 0
    4.77 +   0x08
    4.78 +
    4.79 +   0x47 ;; A -> B
    4.80 +   0xCB ;; swap B nybbles
    4.81 +   0x30 
    4.82 +   0x0C ;; increment C
    4.83 +   0x3E ;; load 0x10 into A, to measure btns
    4.84 +   0x10
    4.85 +   0x18 ;; JUMP back to "load A into [FF00]" [20 steps?]
    4.86 +   0xED
    4.87 +
    4.88 +
    4.89 +   ;; ------ TAKE ACTION BASED ON USER INPUT
    4.90 +
    4.91 +   ;; "input mode"
    4.92 +   ;; mode 0x00 : select mode
    4.93 +   ;; mode 0x08 : select bytes-to-write
    4.94 +   ;; mode 0x10 : select hi-bit
    4.95 +   ;; mode 0x18 : select lo-bit
    4.96 +
    4.97 +   ;; "output mode"
    4.98 +   ;; mode 0x20 : write bytes
    4.99 +   ;; mode 0xFF : jump PC
   4.100 +
   4.101 +
   4.102 +   ;; registers
   4.103 +   ;; D : mode select
   4.104 +   ;; E : count of bytes to write
   4.105 +   ;; H : address-high
   4.106 +   ;; L : address-low
   4.107 +   
   4.108 +   ;; now A contains the pressed keys
   4.109 +   0x2F ; complement A, by request. [D34F]
   4.110 +   
   4.111 +   0x47 ; A->B ;; now B contains the pressed keys
   4.112 +   0x7B ; E->A ;; now A contains the count.
   4.113 +
   4.114 +   0xCB ; test bit 5 of D (are we in o/p mode?)
   4.115 +   0x6A
   4.116 +   0x28 ; if test == 0, skip this o/p section
   4.117 +   0x13 ; JUMP
   4.118 +   
   4.119 +   0xCB ; else, test bit 0 of D (fragile; are we in pc mode?)
   4.120 +   0x42
   4.121 +   0x28 ; if test == 0, skip the following command
   4.122 +   0x01
   4.123 +
   4.124 +   ;; output mode I: moving the program counter
   4.125 +   0xE9 ; ** move PC to (HL)
   4.126 +
   4.127 +   ;; output mode II: writing bytes
   4.128 +   0xFE ; A compare 0. finished writing?
   4.129 +   0x00
   4.130 +   0x20 ; if we are not finished, skip cleanup
   4.131 +   0x04 ; JUMP
   4.132 +
   4.133 +   ;; CLEANUP
   4.134 +   ;; btw, A is already zero.
   4.135 +   0xAF ; zero A  [D35F]
   4.136 +   0x57 ; A->D; makes D=0.
   4.137 +   0x18 ; end of frame
   4.138 +   0xBC
   4.139 +   
   4.140 +   ;; ---- end of cleanup
   4.141 +
   4.142 +   
   4.143 +   ;; continue writing bytes
   4.144 +   0x1D ;; decrement E, the number of bytes to write [D363]
   4.145 +   0x78 ;; B->A; now A contains the pressed keys
   4.146 +   0x77 ;; copy A to (HL)
   4.147 +   0x23 ;; increment HL
   4.148 +   0x18 ;; end frame. [goto D31F]
   4.149 +   0xB6 ;; TODO: set skip length backwards
   4.150 +
   4.151 +
   4.152 +   ;; ---- end of o/p section
   4.153 +   
   4.154 +   ;; i/p mode
   4.155 +   ;; adhere to the mode discipline:
   4.156 +   ;; D must be one of 0x00 0x08 0x10 0x18.
   4.157 +
   4.158 +   0x3E ;; load the constant 57 into A. [D369]
   4.159 +   0x57
   4.160 +   0x82 ;; add the mode to A
   4.161 +   0xEA ;; store A into "thing to execute"
   4.162 +   0x74
   4.163 +   0xD3
   4.164 +
   4.165 +   0x3E ;; load the constant 8 into A
   4.166 +   0x08
   4.167 +   0x82 ;; add the mode to A
   4.168 +   
   4.169 +   0x57 ;; store the incremented mode into D
   4.170 +   0x78 ;; B->A; now A contains the pressed keys
   4.171 +   
   4.172 +   0x00 ;; var: thing to execute [D374]
   4.173 +
   4.174 +   0x18 ;; end frame
   4.175 +   0xA8])
   4.176 +
   4.177 +(defn write-mem-compact []
   4.178 +  (-> (tick (mid-game))
   4.179 +      (IE! 0)
   4.180 +      (inject-item-assembly (write-memory-assembly-compact))))
   4.181 +
   4.182 +(defn drive-compact []
   4.183 +  (-> (write-mem-compact)
   4.184 +      (#(do (println "memory from 0xC00F to 0xC01F:"
   4.185 +                     (subvec (vec (memory %)) 0xC00F 0xC01F)) %))
   4.186 +      (step [])
   4.187 +      (step [])
   4.188 +      (step [])
   4.189 +      (step [:start])
   4.190 +      (step [:select])
   4.191 +      (step [:u :d])
   4.192 +      (step [:a :b :start :select])
   4.193 +      (step [:a])
   4.194 +      (step [:b])
   4.195 +      (step [:a :b])
   4.196 +      (step [:select])
   4.197 +      (step [])
   4.198 +      (step [])
   4.199 +      (step [])
   4.200 +      (#(do (println "memory from 0xC00F to 0xC01F:"
   4.201 +                     (subvec (vec (memory %)) 0xC00F 0xC01F)) %))))
   4.202 +