diff clojure/com/aurellem/run/image.clj @ 511:964957680c11

got an image to display, but it doesn't tile correctly.
author Robert McIntyre <rlm@mit.edu>
date Fri, 22 Jun 2012 15:03:41 -0500
parents b9814e3114e4
children 7ba07a6adb0c
line wrap: on
line diff
     1.1 --- a/clojure/com/aurellem/run/image.clj	Wed Jun 20 22:49:31 2012 -0500
     1.2 +++ b/clojure/com/aurellem/run/image.clj	Fri Jun 22 15:03:41 2012 -0500
     1.3 @@ -90,7 +90,7 @@
     1.4  
     1.5  (def max-palettes 8)
     1.6  
     1.7 -(defn write-data [target data]
     1.8 +(defn write-byte [target data]
     1.9      (flatten
    1.10       [0x3E ;; load literal to A
    1.11        data
    1.12 @@ -114,14 +114,27 @@
    1.13                "00" ;; color num
    1.14                "0"  ;; H/L
    1.15                ) 2)]
    1.16 -    (write-data palette-select-address palette-write-data)))
    1.17 +    (write-byte palette-select-address palette-write-data)))
    1.18          
    1.19  (defn set-palettes [palette-select palette-data palettes]
    1.20    (assert (<= (count palettes)) max-palettes)
    1.21    (flatten 
    1.22     [(begin-sequential-palette-write 0 palette-select)
    1.23 -    (map (partial write-data palette-data)
    1.24 -         (flatten (map gb-rgb->bits palettes)))]))
    1.25 +
    1.26 +    0x21 ;; target address to HL
    1.27 +    (reverse (disect-bytes-2 palette-data))
    1.28 +    
    1.29 +    
    1.30 +    (for [palette palettes]
    1.31 +      (map (fn [byte]
    1.32 +             [0x3E ;; literal to A
    1.33 +              byte
    1.34 +              0x77]) ;; A -> (HL)
    1.35 +           
    1.36 +           (flatten
    1.37 +            (map #(gb-rgb->bits (get palette % [0 0 0]))
    1.38 +                 (range 4)))))]))
    1.39 +      
    1.40  
    1.41  (defn display-one-color
    1.42    "Displayes a single color onto the gameboy screen. Input rgb in
    1.43 @@ -129,14 +142,16 @@
    1.44    ([state [r g b]]
    1.45       ;; construct a kernel that displays a single color
    1.46       (let
    1.47 -         [palettes (repeat 8 [r g b])
    1.48 +         [palettes (repeat 8 [[r g b] [r g b] [r g b] [r g b]])
    1.49            kernel-address 0xC000
    1.50            kernel
    1.51            [0xF3 ;; disable interrupts
    1.52             (clear-music-registers)
    1.53             (frame-metronome)
    1.54 -           (set-palettes obj-palette-select obj-palette-data palettes)
    1.55 -           (set-palettes bg-palette-select bg-palette-data palettes)
    1.56 +           ;;(set-palettes
    1.57 +           ;; obj-palette-select obj-palette-data palettes)
    1.58 +           (set-palettes
    1.59 +            bg-palette-select bg-palette-data palettes)
    1.60             (infinite-loop)]]
    1.61         (-> (set-memory-range state
    1.62                               kernel-address (flatten kernel))
    1.63 @@ -493,42 +508,108 @@
    1.64                      (+ target-address
    1.65                         (count test-data))))))))
    1.66  
    1.67 +(def LCD-bank-select-address 0xFF4F)
    1.68 +
    1.69 +(def BG-1-address 0x9800)
    1.70 +(def BG-2-address 0x9C00)
    1.71 +(def character-data-address 0x8000)
    1.72 +
    1.73 +(def LCD-control-register 0xFF40)
    1.74 +(def STAT-register        0xFF41)
    1.75 +
    1.76 +(def SCX-register 0xFF42)
    1.77 +(def SCY-register 0xFF43)
    1.78 +
    1.79 +(defn select-LCD-bank [n]
    1.80 +  (assert (or (= n 0) (= n 1)))
    1.81 +  (write-byte LCD-bank-select-address n))
    1.82 +
    1.83  (defn display-image-kernel [base-address ^BufferedImage image]
    1.84 -  (let [gb-image (image->gb-image image)]
    1.85 -  
    1.86 -    [(clear-music-registers)
    1.87 +  (let [gb-image (image->gb-image image)
    1.88 +        
    1.89 +        A [(clear-music-registers)
    1.90 +           
    1.91 +           ;; [X] disable LCD protection circuit.
    1.92 +           (write-byte LCD-control-register 0x00)
    1.93 +           ;; now we can write to all video RAM anytime with
    1.94 +           ;; impunity.
    1.95 +           
    1.96 +           ;; we're only using background palettes; just set the
    1.97 +           ;; minimum required bg palettes for this image,
    1.98 +           ;; starting with palette #0.
    1.99  
   1.100 -     ;; [ ] disable LCD protection circuit.
   1.101 -     
   1.102 -     ;; now we can write to all video RAM anytime with
   1.103 -     ;; impunity.
   1.104 +           (set-palettes bg-palette-select bg-palette-data
   1.105 +                         (:palettes gb-image))
   1.106  
   1.107 +           ;; [X] switch to bank 0 to set BG character data.
   1.108 +           (select-LCD-bank 0)
   1.109  
   1.110 -     
   1.111 -     ;; we're only using background palettes; just set the
   1.112 -     ;; minimum required bg palettes for this image,
   1.113 -     ;; starting with palette #0.
   1.114 +           ;; [X] set SCX and SCY to 0
   1.115 +           (write-byte SCX-register 0)
   1.116 +           (write-byte SCY-register 0)
   1.117  
   1.118 -     (set-palettes bg-palette-select bg-palette-data
   1.119 -                   (:palettes gb-image))
   1.120 +           ]
   1.121 +        A (flatten A)
   1.122  
   1.123 -     ;; [ ] switch to bank 0 to set BG character data.
   1.124 -     
   1.125 -     
   1.126 -     ;; [ ] write minimum amount of tiles to BG character
   1.127 -     ;; section
   1.128 -     
   1.129 +        B [;; [X] write minimum amount of tiles to BG character
   1.130 +           ;; section
   1.131 +           (write-data
   1.132 +            (+ base-address (count A))
   1.133 +            character-data-address
   1.134 +            (flatten
   1.135 +             (map gb-tile->bytes (:tiles gb-image))))]
   1.136 +        B (flatten B)
   1.137  
   1.138 -     ;; [ ] disable the display of OBJ tiles.
   1.139 -     
   1.140 +        
   1.141 +        C [;; [ ] write image to the screen in terms of tiles
   1.142 +           (write-data
   1.143 +            (+ base-address (+ (count A) (count B)))
   1.144 +            BG-1-address
   1.145 +            (map first (:data gb-image)))]
   1.146  
   1.147 -     ;; [ ] reactivate the LCD display
   1.148 -     
   1.149 +        C (flatten C)
   1.150  
   1.151 -     (infinite-loop)]
   1.152 +        D [;; [ ] specifiy pallets for each character
   1.153 +           (select-LCD-bank 1)
   1.154 +           (write-data
   1.155 +            (+ base-address (+ (count A) (count B) (count C)))
   1.156 +            BG-1-address
   1.157 +            (map second (:data gb-image)))
   1.158  
   1.159 -     
   1.160 -  ))
   1.161  
   1.162 +           ;; [X] reactivate the LCD display
   1.163 +           ;; we're using only BG images, located at
   1.164 +           ;; BG-1 (0x9800), with background character data
   1.165 +           ;; stored starting at 0x8000
   1.166  
   1.167 +           (write-byte
   1.168 +            LCD-control-register
   1.169 +            (Integer/parseInt
   1.170 +             (str
   1.171 +              "1"  ;; LCDC on/off
   1.172 +              "0"  ;; Window code area
   1.173 +              "0"  ;; Windowing on?
   1.174 +              "1"  ;; BG tile base (1 = 0x8000)
   1.175 +              "0"  ;; BG-1 or BG-2 ?
   1.176 +              "0"  ;; OBJ-block composition
   1.177 +              "0"  ;; OBJ-on flag 
   1.178 +              "1") ;; no-effect 
   1.179 +             2))
   1.180 +           
   1.181  
   1.182 +           (infinite-loop)]
   1.183 +        D (flatten D)]
   1.184 +
   1.185 +    (concat A B C D)))
   1.186 +
   1.187 +
   1.188 +(defn display-image [#^BufferedImage image]
   1.189 +  (let [kernel-address 0xB000]
   1.190 +    (-> (tick (tick (tick (mid-game))))
   1.191 +        (set-memory-range
   1.192 +         kernel-address
   1.193 +         (display-image-kernel kernel-address image))
   1.194 +        (PC! kernel-address))))
   1.195 +      
   1.196 +
   1.197 +