UI sprites
[gbajam22] / src / gamescr.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include "gbaregs.h"
4 #include "game.h"
5 #include "dma.h"
6 #include "util.h"
7 #include "intr.h"
8 #include "input.h"
9 #include "player.h"
10 #include "gba.h"
11 #include "sprite.h"
12 #include "debug.h"
13 #include "level.h"
14 #include "voxscape.h"
15 #include "data.h"
16
17 #define FOV             30
18 #define NEAR    2
19 #define FAR             85
20
21 static int gamescr_start(void);
22 static void gamescr_stop(void);
23 static void gamescr_frame(void);
24 static void gamescr_vblank(void);
25
26 static void update(void);
27 static void draw(void);
28
29 static struct screen gamescr = {
30         "game",
31         gamescr_start,
32         gamescr_stop,
33         gamescr_frame,
34         gamescr_vblank
35 };
36
37 static uint16_t *framebuf;
38
39 static int nframes, backbuf;
40 static uint16_t *vram[] = { gba_vram_lfb0, gba_vram_lfb1 };
41
42 static int32_t pos[2], angle, horizon = 80;
43 static struct voxscape *vox;
44
45 #define COLOR_HORIZON   192
46 #define COLOR_ZENITH    255
47
48 #define MAX_SPR         32
49 static uint16_t oam[4 * MAX_SPR];
50 static int dynspr_base, dynspr_count;
51
52 static int num_tur, total_tur;
53 static int energy;
54 #define MAX_ENERGY      5
55
56 struct screen *init_game_screen(void)
57 {
58         return &gamescr;
59 }
60
61 static int gamescr_start(void)
62 {
63         int i, sidx;
64
65         gba_setmode(4, DISPCNT_BG2 | DISPCNT_OBJ | DISPCNT_FB1);
66
67         vblperf_setcolor(0);
68
69         pos[0] = pos[1] = VOX_SZ << 15;
70
71         if(!(vox = vox_create(VOX_SZ, VOX_SZ, height_pixels, color_pixels))) {
72                 panic(get_pc(), "vox_create");
73         }
74         vox_proj(vox, FOV, NEAR, FAR);
75         vox_view(vox, pos[0], pos[1], -40, angle);
76
77         /* setup color image palette */
78         for(i=0; i<256; i++) {
79                 int r = color_cmap[i * 3];
80                 int g = color_cmap[i * 3 + 1];
81                 int b = color_cmap[i * 3 + 2];
82                 gba_bgpal[i] = (((uint16_t)b << 7) & 0x7c00) | (((uint16_t)g << 2) & 0x3e0) | (((uint16_t)r >> 3) & 0x1f);
83         }
84         /*
85         intr_disable();
86         interrupt(INTR_HBLANK, hblank);
87         REG_DISPSTAT |= DISPSTAT_IEN_HBLANK;
88         unmask(INTR_HBLANK);
89         intr_enable();
90         */
91
92         spr_setup(16, 8, spr_game_pixels, spr_game_cmap);
93         wait_vblank();
94         spr_clear();
95
96         for(i=0; i<MAX_SPR; i++) {
97                 spr_oam_clear(oam, i);
98         }
99
100         sidx = 0;
101         spr_oam(oam, sidx++, SPRID_CROSS, 120-8, 80-8, SPR_SZ16 | SPR_256COL);
102         spr_oam(oam, sidx++, SPRID_UIMID, 0, 144, SPR_VRECT | SPR_256COL);
103         spr_oam(oam, sidx++, SPRID_UIRIGHT, 48, 144, SPR_SZ16 | SPR_256COL);
104         spr_oam(oam, sidx++, SPRID_UILEFT, 168, 144, SPR_SZ16 | SPR_256COL);
105         spr_oam(oam, sidx++, SPRID_UITGT, 184, 144, SPR_SZ16 | SPR_256COL);
106         spr_oam(oam, sidx++, SPRID_UISLASH, 216, 144, SPR_VRECT | SPR_256COL);
107         dynspr_base = sidx;
108
109         wait_vblank();
110         dma_copy32(3, (void*)OAM_ADDR, oam, sidx * 2, 0);
111
112         num_tur = 0;
113         total_tur = 16;
114         energy = 5;
115
116         nframes = 0;
117         return 0;
118 }
119
120 static void gamescr_stop(void)
121 {
122         /*mask(INTR_HBLANK);*/
123 }
124
125 static void gamescr_frame(void)
126 {
127         backbuf = ++nframes & 1;
128         framebuf = vram[backbuf];
129
130         vox_framebuf(vox, 240, 160, framebuf, horizon);
131
132         update();
133         draw();
134
135         vblperf_end();
136         wait_vblank();
137         present(backbuf);
138
139         if(!(nframes & 15)) {
140                 emuprint("vbl: %d", vblperf_count);
141         }
142 #ifdef VBLBAR
143         vblperf_begin();
144 #else
145         vblperf_count = 0;
146 #endif
147 }
148
149 #define NS(x)   (SPRID_UINUM + ((x) << 1))
150 static int numspr[][2] = {
151         {NS(0),NS(0)}, {NS(0),NS(1)}, {NS(0),NS(2)}, {NS(0),NS(3)}, {NS(0),NS(4)},
152         {NS(0),NS(5)}, {NS(0),NS(6)}, {NS(0),NS(7)}, {NS(0),NS(8)}, {NS(0),NS(9)},
153         {NS(1),NS(0)}, {NS(1),NS(1)}, {NS(1),NS(2)}, {NS(1),NS(3)}, {NS(1),NS(4)},
154         {NS(1),NS(5)}, {NS(1),NS(6)}, {NS(1),NS(7)}, {NS(1),NS(8)}, {NS(1),NS(9)},
155         {NS(2),NS(0)}, {NS(2),NS(1)}, {NS(2),NS(2)}, {NS(2),NS(3)}, {NS(2),NS(4)},
156         {NS(2),NS(5)}, {NS(2),NS(6)}, {NS(2),NS(7)}, {NS(2),NS(8)}, {NS(2),NS(9)},
157         {NS(3),NS(0)}, {NS(3),NS(1)}, {NS(3),NS(2)}, {NS(3),NS(3)}, {NS(3),NS(4)},
158         {NS(3),NS(5)}, {NS(3),NS(6)}, {NS(3),NS(7)}, {NS(3),NS(8)}, {NS(3),NS(9)}
159 };
160
161 #define WALK_SPEED      0x40000
162 #define TURN_SPEED      0x200
163 #define ELEV_SPEED      8
164
165 static void update(void)
166 {
167         int32_t fwd[2], right[2];
168         int i, ledspr;
169
170         update_keyb();
171
172         if(KEYPRESS(BN_SELECT)) {
173                 vox_quality ^= 1;
174         }
175
176         if(keystate) {
177                 if(keystate & BN_LEFT) {
178                         angle += TURN_SPEED;
179                 }
180                 if(keystate & BN_RIGHT) {
181                         angle -= TURN_SPEED;
182                 }
183
184                 fwd[0] = -SIN(angle);
185                 fwd[1] = COS(angle);
186                 right[0] = fwd[1];
187                 right[1] = -fwd[0];
188
189                 if(keystate & BN_A) {
190                         pos[0] += fwd[0];
191                         pos[1] += fwd[1];
192                 }
193                 /*
194                 if(keystate & BN_DOWN) {
195                         pos[0] -= fwd[0];
196                         pos[1] -= fwd[1];
197                 }
198                 */
199                 if(keystate & BN_UP) {
200                         if(horizon > 40) horizon -= ELEV_SPEED;
201                 }
202                 if(keystate & BN_DOWN) {
203                         if(horizon < 200 - ELEV_SPEED) horizon += ELEV_SPEED;
204                 }
205                 if(keystate & BN_RT) {
206                         pos[0] += right[0];
207                         pos[1] += right[1];
208                 }
209                 if(keystate & BN_LT) {
210                         pos[0] -= right[0];
211                         pos[1] -= right[1];
212                 }
213
214                 vox_view(vox, pos[0], pos[1], -40, angle);
215         }
216
217         /* turrets number */
218         spr_oam(oam, dynspr_base, numspr[num_tur][0], 200, 144, SPR_VRECT | SPR_256COL);
219         spr_oam(oam, dynspr_base + 1, numspr[num_tur][1], 208, 144, SPR_VRECT | SPR_256COL);
220         spr_oam(oam, dynspr_base + 2, numspr[total_tur][0], 224, 144, SPR_VRECT | SPR_256COL);
221         spr_oam(oam, dynspr_base + 3, numspr[total_tur][1], 232, 144, SPR_VRECT | SPR_256COL);
222         /* energy bar */
223         if(energy == MAX_ENERGY) {
224                 ledspr = SPRID_LEDBLU;
225         } else {
226                 ledspr = energy > 2 ? SPRID_LEDGRN : SPRID_LEDRED;
227         }
228         for(i=0; i<5; i++) {
229                 spr_oam(oam, dynspr_base + i + 4, i >= energy ? SPRID_LEDOFF : ledspr,
230                                 8 + (i << 3), 144, SPR_VRECT | SPR_256COL);
231         }
232         dynspr_count = 9;
233 }
234
235 static void draw(void)
236 {
237         //dma_fill16(3, framebuf, 0, 240 * 160 / 2);
238         fillblock_16byte(framebuf, 0, 240 * 160 / 16);
239
240         vox_render(vox);
241         //vox_sky_grad(vox, COLOR_HORIZON, COLOR_ZENITH);
242         //vox_sky_solid(vox, COLOR_ZENITH);
243 }
244
245 #define MAXBANK         0x100
246
247 ARM_IWRAM
248 static void gamescr_vblank(void)
249 {
250         static int bank, bankdir, theta, s;
251         int32_t sa, ca;
252
253         if(!nframes) return;
254
255         dma_copy32(3, (void*)(OAM_ADDR + dynspr_base * 8), oam + dynspr_base * 4, dynspr_count * 2, 0);
256
257         theta = -(bank << 3);
258 #if 0
259         s = 0x100000 / (MAXBANK + (abs(bank) >> 3));
260         sa = ((SIN(theta) >> 8) * s) >> 12;
261         ca = ((COS(theta) >> 8) * s) >> 12;
262 #else
263         s = (MAXBANK + (abs(bank) >> 3));
264         sa = SIN(theta) / s;
265         ca = COS(theta) / s;
266 #endif
267
268         REG_BG2X = -ca * 120 - sa * 80 + (120 << 8);
269         REG_BG2Y = sa * 120 - ca * 80 + (80 << 8);
270
271         REG_BG2PA = ca;
272         REG_BG2PB = sa;
273         REG_BG2PC = -sa;
274         REG_BG2PD = ca;
275
276         keystate = ~REG_KEYINPUT;
277
278         if((keystate & (BN_LEFT | BN_RIGHT)) == 0) {
279                 if(bank) {
280                         bank -= bankdir << 4;
281                 }
282         } else if(keystate & BN_LEFT) {
283                 bankdir = -1;
284                 if(bank > -MAXBANK) bank -= 16;
285         } else if(keystate & BN_RIGHT) {
286                 bankdir = 1;
287                 if(bank < MAXBANK) bank += 16;
288         }
289 }
290
291 /*
292 static uint16_t skygrad[] __attribute__((section(".data"))) = {
293
294         0x662a, 0x660a, 0x660a, 0x660b, 0x660b, 0x660b, 0x660b, 0x6a0b, 0x6a0c,
295         0x6a0c, 0x6a0c, 0x6a0c, 0x6a0c, 0x6a0d, 0x6a0d, 0x6a0d, 0x6a0d, 0x6a0d,
296         0x6a0d, 0x6a0e, 0x6e0e, 0x6e0e, 0x6e0e, 0x6e0e, 0x6e0f, 0x6e0f, 0x6e0f,
297         0x6e0f, 0x6e0f, 0x6e0f, 0x6e10, 0x6e10, 0x7210, 0x7210, 0x7210, 0x7211,
298         0x7211, 0x7211, 0x71f1, 0x71f1, 0x71f2, 0x71f2, 0x71f2, 0x71f2, 0x71f2,
299         0x75f2, 0x75f3, 0x75f3, 0x75f3, 0x75f3, 0x75f3, 0x75f4, 0x75f4, 0x75f4,
300         0x75f4, 0x75f4, 0x75f5, 0x79f5, 0x79f5, 0x79f5, 0x79f5, 0x79f5, 0x79f6,
301         0x79f6, 0x79f6, 0x79f6, 0x79f6, 0x79f7, 0x79f7, 0x79f7, 0x7df7, 0x7df7,
302         0x7df7, 0x7df8, 0x7df8, 0x7df8, 0x7dd8, 0x7dd8, 0x7dd9, 0x7dd9,
303
304         0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
305         0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
306         0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
307         0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
308         0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
309         0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
310         0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
311         0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
312         0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9
313 };
314
315 ARM_IWRAM
316 static void hblank(void)
317 {
318         int vcount = REG_VCOUNT;
319         gba_bgpal[255] = skygrad[vcount];
320 }
321 */