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