1 /*
2  * C version of the 'space' assembly demo.
3  *
4  * Little demo illustrating how to use the graphical possibilities
5  *  of the GB (background, window and animated sprite)
6  * I have used fixed-point values for both the position and
7  *  speed of objects to get smooth movements
8  *
9  * OBJ data             : 0x8000 -> 0x8FFF (unsigned)
10  * Window data          : 0x8800 -> 0x97FF (unsigned)
11  * Background data      : 0x8800 -> 0x97FF (signed)
12  *
13  * Tiled 0xFC -> 0xFF are standard tiles (all black -> all white)
14  *
15  * Keys:
16  * Arrow keys           : Change the speed (and direction) of the sprite
17  * Arrow keys + A       : Change the speed (and direction) of the window
18  * Arrow keys + B       : Change the speed (and direction) of the background
19  * START                : Open/close the door
20  * SELECT               : Basic fading effect
21  *
22  * Note that the window is kept in the lower right part of the screen
23  * since it can't be made transparent
24  */
25 
26 #include <gb/gb.h>
27 
28 const unsigned char std_data[] = {
29 
30   /* Basic tiles (0xFC to 0xFF) */
31   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
32   0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
33   0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
34   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
35 };
36 
37 const unsigned char earth_data[] = {
38 
39   /* Tile 0x00 */
40   0x07,0x07,0x18,0x1F,0x32,0x2D,0x71,0x4E,0x70,0x4F,0xF8,0x87,0xF8,0x87,0xF8,0x87,
41   0xFC,0x83,0xFE,0x81,0x7F,0x40,0x7F,0x40,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00,
42   0xC0,0xC0,0xF0,0x30,0x78,0x88,0x3C,0xC4,0x5C,0xA4,0x9E,0x62,0x3E,0xC2,0x3E,0xC2,
43   0x5E,0xA2,0x7E,0x82,0x0C,0xF4,0x0C,0xF4,0x98,0x68,0xB0,0x70,0xC0,0xC0,0x00,0x00,
44   0x07,0x07,0x1F,0x18,0x2F,0x30,0x4F,0x70,0x6F,0x50,0x9F,0xE0,0x9F,0xE0,0xBF,0xC0,
45   0xFF,0x80,0xB7,0xC8,0x63,0x5C,0x43,0x7C,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00,
46   0xC0,0xC0,0xB0,0x70,0x18,0xE8,0x0C,0xF4,0x0C,0xF4,0x82,0x7E,0x82,0x7E,0x86,0x7A,
47   0xC6,0x3A,0xE6,0x1A,0xF4,0x0C,0xFC,0x04,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00,
48 
49   /* Tile 0x08 */
50   0x07,0x07,0x1E,0x19,0x20,0x3F,0x40,0x7F,0x42,0x7D,0x81,0xFE,0x81,0xFE,0x83,0xFC,
51   0xD7,0xA8,0xBB,0xC4,0x6E,0x51,0x7C,0x43,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00,
52   0xC0,0xC0,0x70,0xB0,0xE8,0x18,0xF4,0x0C,0xF4,0x0C,0xFE,0x02,0xFE,0x02,0xFE,0x02,
53   0xFE,0x02,0x7E,0x82,0x3C,0xC4,0x3C,0xC4,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00,
54   0x07,0x07,0x1B,0x1C,0x20,0x3F,0x40,0x7F,0x40,0x7F,0xE0,0x9F,0x90,0xEF,0x89,0xF6,
55   0x8D,0xF2,0x9F,0xE0,0x5E,0x61,0x6F,0x50,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00,
56   0xC0,0xC0,0xB0,0x70,0x28,0xD8,0x04,0xFC,0x2C,0xD4,0x1E,0xE2,0x1E,0xE2,0x3E,0xC2,
57   0x7E,0x82,0xB6,0x4A,0xE4,0x1C,0xC4,0x3C,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00,
58 
59   /* Tile 0x10 */
60   0x07,0x07,0x18,0x1F,0x20,0x3F,0x40,0x7F,0x40,0x7F,0xEE,0x91,0xF1,0x8E,0xE0,0x9F,
61   0xE0,0x9F,0xF1,0x8E,0x71,0x4E,0x72,0x4D,0x3F,0x20,0x1F,0x18,0x07,0x07,0x00,0x00,
62   0xC0,0xC0,0xF0,0x30,0x08,0xF8,0x04,0xFC,0x04,0xFC,0x02,0xFE,0x02,0xFE,0x92,0x6E,
63   0xD6,0x2A,0xFE,0x02,0xEC,0x14,0xFC,0x04,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00,
64   0x07,0x07,0x1D,0x1A,0x36,0x29,0x5C,0x63,0x6C,0x53,0xCE,0xB1,0x9F,0xE0,0x9E,0xE1,
65   0xAE,0xD1,0xBF,0xC0,0x47,0x78,0x47,0x78,0x2F,0x30,0x1F,0x18,0x07,0x07,0x00,0x00,
66   0xC0,0xC0,0x70,0xB0,0x08,0xF8,0x04,0xFC,0x04,0xFC,0xE2,0x1E,0x32,0xCE,0x0E,0xF2,
67   0x0E,0xF2,0x1E,0xE2,0x1C,0xE4,0x2C,0xD4,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00,
68 
69   /* Tile 0x18 */
70   0x07,0x07,0x1E,0x19,0x33,0x2C,0x49,0x76,0x42,0x7D,0xC4,0xBB,0xC1,0xBE,0xC1,0xBE,
71   0xE2,0x9D,0xF3,0x8C,0x78,0x47,0x78,0x47,0x3C,0x23,0x1C,0x1B,0x07,0x07,0x00,0x00,
72   0xC0,0xC0,0x70,0xB0,0x68,0x98,0xC4,0x3C,0xC4,0x3C,0xEE,0x12,0xF2,0x0E,0xE2,0x1E,
73   0xE2,0x1E,0xF2,0x0E,0x7C,0x84,0x7C,0x84,0xF8,0x08,0xF0,0x30,0xC0,0xC0,0x00,0x00
74 };
75 
76 const unsigned char frame_data[] = {
77 
78   /* Tile 0x00 */
79   0xFF,0x00,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,
80   0xFF,0x00,0x01,0xFE,0x03,0xFC,0x07,0xF8,0x0F,0xF0,0x1F,0xE0,0x3F,0xC0,0x7F,0x80,
81   0xFF,0x00,0xFE,0x01,0xFC,0x03,0xF8,0x07,0xF0,0x0F,0xE0,0x1F,0xC0,0x3F,0x80,0x7F,
82   0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
83   0xFF,0x00,0xFF,0x01,0xFD,0x03,0xF9,0x07,0xF1,0x0F,0xE1,0x1F,0xC1,0x3F,0x81,0x7F,
84   0x80,0x7F,0x81,0x7E,0x83,0x7C,0x87,0x78,0x8F,0x70,0x9F,0x60,0xBF,0x40,0xFF,0x00,
85   0xFF,0x70,0xFF,0x98,0xEF,0xB8,0xCF,0xF8,0xFF,0x70,0xFF,0x00,0xFF,0x00,0xFF,0x01,
86   0xFF,0x00,0xFE,0x01,0xFC,0x03,0xF8,0x07,0xF0,0x0F,0xE0,0x1F,0xC0,0x3F,0xFF,0xFF,
87 
88   /* Tile 0x08 */
89   0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,
90   0x00,0xFF,0x01,0xFE,0x03,0xFC,0x07,0xF8,0x0F,0xF0,0x1F,0xE0,0x3F,0xC0,0xFF,0xFF,
91   0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,
92   0xFF,0x0E,0xFF,0x13,0xFD,0x17,0xF9,0x1F,0xFE,0x0F,0xE0,0x1F,0xC0,0x3F,0x80,0xFF,
93   0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,
94   0xFF,0x01,0xFF,0x01,0xFD,0x03,0xF9,0x07,0xF1,0x0F,0xE1,0x1F,0xC1,0x3F,0x81,0x7F,
95   0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,0x80,0x7F,
96   0x01,0xFF,0x01,0xFF,0x03,0xFD,0x07,0xF9,0x0F,0xF1,0x1F,0xE1,0x3F,0xC1,0x7F,0x81,
97 
98   /* Tile 0x10 */
99   0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,
100   0x01,0xFF,0x01,0xFE,0x03,0xFC,0x77,0xF8,0xFF,0x98,0xEF,0xB8,0xCF,0xF8,0x7F,0xF0,
101   0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x0E,0xFF,0x13,0xFD,0x17,0xF9,0x1F,0xFF,0x0E,
102   0x80,0x7F,0x81,0x7E,0x83,0x7C,0x87,0x78,0x8F,0x70,0x9F,0x60,0xBF,0x40,0xFF,0x7F,
103   0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0xFF,0xFF,
104 
105   /* Door1 */
106 
107   /* Tile 0x15 */
108   0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,
109   0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,
110   0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,
111 
112   /* Door2 */
113 
114   /* Tile 0x18 */
115   0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,
116   0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,
117   0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,
118   0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
119 
120   /* Door3 */
121 
122   /* Tile 0x1C */
123   0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,
124   0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,
125   0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,
126   0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
127 
128   /* Door4 */
129 
130   /* Tile 0x20 */
131   0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
132 };
133 
134 const unsigned char bkg_data[] = {
135 
136   /* Tile 0x00 */
137   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,
138   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,
139   0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
140   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xF7,0xFF,0xFF,
141   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
142   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,
143   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
144   0xFF,0xFF,0xDF,0xFF,0xEF,0xFF,0xFF,0xF7,0xFF,0xFB,0xFF,0xFD,0xFF,0xFE,0xFE,0xFF,
145 
146   /* Tile 0x08 */
147   0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7D,0xFE,0x7C,0x39,
148   0xFF,0xFF,0xF7,0xFF,0xEF,0xFF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,
149   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,
150   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFD,
151   0xBB,0x01,0xC7,0x83,0xC7,0x83,0xC7,0x83,0xBB,0x01,0x7C,0x39,0x7D,0xFE,0xFF,0xFF,
152   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,
153   0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,
154   0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFB,0xAF,0x77,0x27,0x8F,0xDF,0x8F,0x27,0x8F,
155 
156   /* Tile 0x10 */
157   0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
158   0xFF,0xFB,0xFF,0xF7,0xEF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
159   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
160   0xFF,0xBF,0xFF,0xDF,0xEF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
161   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
162   0xFF,0xFF,0xFF,0xFE,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
163   0xAF,0x77,0xFF,0xFB,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
164   0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,
165 
166   /* Tile 0x18 */
167   0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,
168   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,
169   0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,
170   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0x7D,0xFE,0x7C,0x39,
171   0xFF,0xFF,0xF7,0xFF,0xEF,0xFF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0x7F,0xFF,0xFF,0xFF,
172   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,
173   0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
174   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFD,
175 
176   /* Tile 0x20 */
177   0xFF,0xFF,0xDF,0xFF,0xEF,0xFF,0xFF,0xF7,0xFF,0xFB,0xFE,0xFD,0xFD,0xFE,0xFE,0xFF,
178   0xAB,0x11,0xC7,0x83,0x83,0xC7,0xC7,0x83,0xAB,0x11,0x7C,0x39,0x7D,0xFE,0xFE,0xFF,
179   0xFF,0xFF,0xFF,0xFF,0xFB,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0x7F,
180   0xFB,0xFF,0xFF,0xFD,0xFE,0xFE,0xFE,0xFF,0xFE,0xFE,0xFF,0xFD,0xFB,0xFF,0xFF,0xFF,
181   0xEF,0xFF,0xFF,0xDF,0x3F,0xBF,0x3F,0x7F,0x3F,0xBF,0xFF,0xDF,0xEF,0xFF,0xFF,0xFF,
182   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFB,0xFF,0xFF,0xFF,0xFF,
183   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFD,0xFE,0xFE,0xFD,
184   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,
185 
186   /* Tile 0x28 */
187   0xF7,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
188   0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
189   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
190   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
191   0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
192 };
193 
194 /*
195  * Image size: 0x40 x 0x40
196  * Number of tiles (total - unique): 0x40 - 0x2D
197  */
198 
199 const unsigned char bkg_tiles[] = {
200   0x00,0x01,0x02,0x03,0xFC,0xFC,0x04,0xFC,
201   0xFC,0x05,0x06,0xFC,0x07,0x08,0x09,0x0A,
202   0xFC,0xFC,0xFC,0x02,0x0B,0x0C,0x0D,0xFC,
203   0x0E,0x0F,0x10,0xFC,0x11,0x12,0x13,0x14,
204   0x15,0x16,0x17,0xFC,0x18,0x19,0x1A,0xFC,
205   0x1B,0x1C,0x1D,0xFC,0xFC,0x1E,0x1F,0x20,
206   0x21,0x22,0xFC,0x23,0x24,0x25,0xFC,0x26,
207   0x27,0x13,0x28,0x29,0x2A,0x2B,0x2C,0x11
208 };
209 
210 /*
211  * Image size: 0x10 x 0x70
212  * Number of tiles (total - unique): 0x1C - 0x1C
213  */
214 
215 const unsigned char earth_tiles[] = {
216   0x00,0x02,
217   0x04,0x06,
218   0x08,0x0A,
219   0x0C,0x0E,
220   0x10,0x12,
221   0x14,0x16,
222   0x18,0x1A
223 };
224 
225 /*
226  * Image size: 0x80 x 0x50
227  * Number of tiles (total - unique): 0xA0 - 0x15
228  */
229 
230 const unsigned char frame_tiles[] = {
231   0x80,0x81,0xFD,0x82,0x83,0x81,0xFD,0x82,0x83,0x81,0xFD,0x82,0x83,0x81,0xFD,0x84,
232   0x85,0x86,0x87,0x88,0x89,0x8A,0x87,0x88,0x89,0x8A,0x87,0x88,0x89,0x8A,0x8B,0x8C,
233   0xFD,0x8D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x8F,
234   0x82,0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x85,0x90,
235   0x8E,0x8F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x8D,
236   0x85,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x82,0x8C,
237   0xFD,0x8D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E,0x8F,
238   0x82,0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x85,0x90,
239   0x8E,0x91,0xFD,0x82,0x83,0x81,0xFD,0x82,0x83,0x81,0xFD,0x82,0x83,0x81,0x92,0x8D,
240   0x93,0x8A,0x87,0x88,0x89,0x8A,0x87,0x88,0x89,0x8A,0x87,0x88,0x89,0x8A,0x87,0x94
241 };
242 
243 /*
244  * Image size: 0x60 x 0x30
245  * Number of tiles (total - unique): 0x48 - 0x03
246  */
247 
248 const unsigned char door1_tiles[] = {
249   0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,
250   0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,
251   0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,
252   0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,
253   0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,
254   0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,
255 
256   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
257   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
258   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
259   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
260   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
261   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
262 };
263 
264 /*
265  * Image size: 0x60 x 0x30
266  * Number of tiles (total - unique): 0x48 - 0x04
267  */
268 
269 const unsigned char door2_tiles[] = {
270   0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,
271   0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,
272   0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,0x9A,
273   0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,0x98,
274   0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,
275   0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,0x9B,
276 
277   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
278   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
279   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
280   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
281   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
282 };
283 
284 /*
285  * Image size: 0x60 x 0x30
286  * Number of tiles (total - unique): 0x48 - 0x04
287  */
288 
289 const unsigned char door3_tiles[] = {
290   0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,
291   0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,
292   0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,0x9E,
293   0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,
294   0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,0x9D,
295   0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,
296 
297   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
298   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
299   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
300   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
301   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
302 };
303 
304 /*
305  * Image size: 0x60 x 0x30
306  * Number of tiles (total - unique): 0x48 - 0x01
307  */
308 
309 const unsigned char door4_tiles[] = {
310   0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,
311   0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,
312   0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,0x97,
313   0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,
314   0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,0x96,
315   0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,
316 
317   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
318   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
319   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
320   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
321   0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC
322 };
323 
324 /* Should really be const, but sdcc doesnt yet support it. */
325 const unsigned char *film[] = {
326   &door1_tiles[0x0C*0],
327   &door2_tiles[0x0C*0],
328   &door3_tiles[0x0C*0],
329   &door4_tiles[0x0C*0],
330   &door1_tiles[0x0C*1],
331   &door2_tiles[0x0C*1],
332   &door3_tiles[0x0C*1],
333   &door4_tiles[0x0C*1],
334   &door1_tiles[0x0C*2],
335   &door2_tiles[0x0C*2],
336   &door3_tiles[0x0C*2],
337   &door4_tiles[0x0C*2],
338   &door1_tiles[0x0C*3],
339   &door2_tiles[0x0C*3],
340   &door3_tiles[0x0C*3],
341   &door4_tiles[0x0C*3],
342   &door1_tiles[0x0C*4],
343   &door2_tiles[0x0C*4],
344   &door3_tiles[0x0C*4],
345   &door4_tiles[0x0C*4],
346   &door1_tiles[0x0C*5],
347   &door2_tiles[0x0C*5],
348   &door3_tiles[0x0C*5],
349   &door4_tiles[0x0C*5],
350   &door1_tiles[0x0C*6]
351 };
352 
353 #define NBDFRAMES 0x18                  /* Nb frames for the door */
354 #define NBSFRAMES 0x07                  /* Nb frames for the sprite */
355 #define WINSZX    0x80                  /* Size of the picture in the window */
356 #define WINSZY    0x50
357 #define MINWINX   (MAXWNDPOSX-WINSZX+1) /* Bounds of the window origin */
358 #define MINWINY   (MAXWNDPOSY-WINSZY+1)
359 #define MAXWINX   MAXWNDPOSX
360 #define MAXWINY   MAXWNDPOSY
361 #define FADESTEP  0x10                  /* Nb steps for the fading effect */
362 #define STARTFADE (0x06*FADESTEP)       /* Initial value for the fading effect */
363 
364 #define CLOSED  0x00
365 #define OPENING 0x01
366 #define OPENED  0x02
367 #define CLOSING 0x03
368 
369 static uint8_t tim;  /* Global "tim" value (counter) */
370 uint8_t doorstate;    /* State of the door (OPENED, CLOSED...) */
371 uint8_t doorpos;      /* Current position in the door animation */
372 static uint8_t color; /* Current color for fading effect */
373 uint8_t sframe;       /* Current frame of the sprite */
374 fixed bposx, bposy; /* Background position (fixed point) */
375 fixed bspx, bspy;   /* Background speed (fixed point) */
376 fixed wposx, wposy; /* Window position (fixed point) */
377 fixed wspx, wspy;   /* Window speed (fixed point) */
378 fixed sposx, sposy; /* Sprite position (fixed point) */
379 fixed sspx, sspy;   /* Sprite speed (fixed point) */
380 
381 void fade();
382 void scroll();
383 void door();
384 void animate_sprite();
385 void tile_sprite();
386 void place_sprite();
387 
388 /* Fade the screen (off and on) */
fade()389 void fade()
390 {
391   if(color == 0)
392     return;
393   switch(color)
394     {
395     case STARTFADE:
396     case STARTFADE-4*FADESTEP:
397       BGP_REG = 0xF9U;
398       break;
399     case STARTFADE-FADESTEP:
400     case STARTFADE-3*FADESTEP:
401       BGP_REG = 0xFEU;
402       break;
403     case STARTFADE-2*FADESTEP:
404       BGP_REG = 0xFFU;
405       break;
406     case STARTFADE-5*FADESTEP:
407       BGP_REG = 0xE4U;
408       break;
409     }
410   color--;
411 }
412 
413 /* Scroll the background, the window and the sprite */
scroll()414 void scroll()
415 {
416   /* Update background */
417   bposx.w += bspx.w;
418   bposy.w += bspy.w;
419   SCX_REG = bposx.b.h;
420   SCY_REG = bposy.b.h;
421 
422   /* Update window */
423   wposx.w += wspx.w ;
424   wposy.w += wspy.w ;
425   /* X position */
426   if(wposx.b.h >= MAXWINX) {
427     wposx.b.h = MAXWINX;
428     /* Invert speed */
429     wspx.w = -(int16_t)wspx.w;
430   } else if(wposx.b.h <= MINWINX) {
431     wposx.b.h = MINWINX;
432     /* Invert speed */
433     wspx.w = -(int16_t)wspx.w;
434   }
435   WX_REG = wposx.b.h;
436   /* Y position */
437   if(wposy.b.h >= MAXWINY) {
438     wposy.b.h = MAXWINY;
439     /* Invert speed */
440     wspy.w = -(int16_t)wspy.w;
441   } else if(wposy.b.h <= MINWINY) {
442     wposy.b.h = MINWINY;
443     /* Invert speed */
444     wspy.w = -(int16_t)wspy.w;
445   }
446   WY_REG = wposy.b.h;
447 
448   /* Update sprite */
449   sposx.w += sspx.w;
450   sposy.w += sspy.w;
451   place_sprite();
452 }
453 
454 /* Open and close the door */
door()455 void door()
456 {
457   if(doorstate == OPENING) {
458     doorpos++;
459     /* Draw the door in the window */
460     set_win_tiles(2, 2, 12, 6, film[doorpos]);
461     if(doorpos == NBDFRAMES)
462       doorstate = OPENED;
463   } else if(doorstate == CLOSING) {
464     doorpos--;
465     /* Draw the door in the window */
466     set_win_tiles(2, 2, 12, 6, film[doorpos]);
467     if(doorpos == 0)
468       doorstate = CLOSED;
469   }
470 }
471 
472 /* Animate sprite */
animate_sprite()473 void animate_sprite()
474 {
475   if((tim&0x07) == 0) {
476     sframe++;
477     if(sframe == NBSFRAMES)
478       sframe = 0;
479     tile_sprite();
480   }
481 }
482 
483 /* Set sprite tiles */
tile_sprite()484 void tile_sprite()
485 {
486   uint8_t s;
487 
488   s = sframe<<1;
489   set_sprite_tile(0, earth_tiles[s]);
490   set_sprite_tile(1, earth_tiles[s+1]);
491 }
492 
493 /* Place sprite */
place_sprite()494 void place_sprite()
495 {
496   move_sprite(0, sposx.b.h, sposy.b.h);
497   move_sprite(1, sposx.b.h+8, sposy.b.h);
498 }
499 
main()500 void main()
501 {
502   uint8_t i, j;
503 
504   disable_interrupts();
505   DISPLAY_OFF;
506   LCDC_REG = 0x67;
507   /*
508    * LCD        = Off
509    * WindowBank = 0x9C00
510    * Window     = On
511    * BG Chr     = 0x8800
512    * BG Bank    = 0x9800
513    * OBJ        = 8x16
514    * OBJ        = On
515    * BG         = On
516    */
517 
518   doorstate = CLOSED;
519 
520   /* Set palettes */
521   BGP_REG = OBP0_REG = OBP1_REG = 0xE4U;
522 
523   /* Initialize the background */
524   set_bkg_data(0xFC, 0x04, std_data);
525   set_bkg_data(0x00, 0x2D, bkg_data);
526   /*
527    * Draw the background
528    *
529    * Width  = 0x100 = 0x20 * 8
530    * Height = 0x100 = 0x20 * 8
531    */
532   for(i = 0; i < 32; i+=8)
533     for(j = 0; j < 32; j+=8)
534       set_bkg_tiles(i, j, 8, 8, bkg_tiles);
535   bposx.w = 0;
536   SCX_REG = 0;
537   bposy.w = 0;
538   SCY_REG = 0;
539   bspx.w = 0xFF00;
540   bspy.w = 0x0080;
541 
542   /* Initialize the window */
543   set_win_data(0x80, 0x21, frame_data);
544   /*
545    * Draw the frame in the window
546    *
547    * Width  = 0x80 = 0x10 * 8
548    * Height = 0x50 = 0x0A * 8
549    */
550   set_win_tiles(0, 0, 16, 10, frame_tiles);
551   /*
552    * Draw the door in the window
553    *
554    * Width  = 0x60 = 0x20 * 12
555    * Height = 0x30 = 0x20 * 6
556    */
557   set_win_tiles(2, 2, 12, 6, door1_tiles);
558   wposx.b.h = MAXWNDPOSX;
559   wposx.b.l = 0;
560   WX_REG = MAXWNDPOSX;
561   wposy.b.h = MAXWNDPOSY;
562   wposy.b.l = 0;
563   WY_REG = MAXWNDPOSY;
564   wspx.w = 0xFF80;
565   wspy.w = 0xFFC0;
566 
567   /* Initialize the sprite */
568   set_sprite_data(0x00, 0x1C, earth_data);
569   set_sprite_prop(0, 0x00);
570   set_sprite_prop(1, 0x00);
571   sframe = 0;
572   sposx.w  = 0x1000;
573   sposy.w  = 0x1000;
574   sspx.w  = 0x0040;
575   sspy.w  = 0x0040;
576   tile_sprite();
577   place_sprite();
578 
579   DISPLAY_ON;
580   enable_interrupts();
581 
582   while(1) {
583     /* Skip four VBLs (slow down animation) */
584     for(i = 0; i < 4; i++)
585       wait_vbl_done();
586     tim++;
587     fade();
588     door();
589     scroll();
590     animate_sprite();
591     i = joypad();
592     if(i & J_B) {
593       if(i & J_UP)
594 	bspy.w -= 0x0010;
595       if(i & J_DOWN)
596 	bspy.w += 0x0010;
597       if(i & J_LEFT)
598 	bspx.w -= 0x0010;
599       if(i & J_RIGHT)
600 	bspx.w += 0x0010;
601     } else if(i & J_A) {
602       if(i & J_UP)
603 	wspy.w -= 0x0010;
604       if(i & J_DOWN)
605 	wspy.w += 0x0010;
606       if(i & J_LEFT)
607 	wspx.w -= 0x0010;
608       if(i & J_RIGHT)
609 	wspx.w += 0x0010;
610     } else {
611       if(i & J_SELECT)
612 	color = STARTFADE;
613       if(i & J_START)
614 	if(doorstate == CLOSED) {
615 	  doorstate = OPENING;
616 	  doorpos = 0;
617 	} else if(doorstate == OPENED) {
618 	  doorstate = CLOSING;
619 	  doorpos = NBDFRAMES;
620 	}
621       if(i & J_UP)
622 	sspy.w -= 0x0010;
623       if(i & J_DOWN)
624 	sspy.w += 0x0010;
625       if(i & J_LEFT)
626 	sspx.w -= 0x0010;
627       if(i & J_RIGHT)
628 	sspx.w += 0x0010;
629     }
630   }
631 }
632