19 static int gamescr_start(void);
20 static void gamescr_stop(void);
21 static void gamescr_frame(void);
22 static void gamescr_vblank(void);
24 static void update(void);
25 static void draw(void);
27 static struct screen gamescr = {
35 static uint16_t *framebuf;
37 static int nframes, backbuf;
38 static uint16_t *vram[] = { gba_vram_lfb0, gba_vram_lfb1 };
40 static int32_t pos[2], angle, horizon = 80;
41 static struct voxscape *vox;
43 #define COLOR_HORIZON 192
44 #define COLOR_ZENITH 255
47 static uint16_t oam[4 * MAX_SPR];
48 static int dynspr_base, dynspr_count;
50 static int num_tur, total_tur;
54 struct screen *init_game_screen(void)
59 static int gamescr_start(void)
63 gba_setmode(4, DISPCNT_BG2 | DISPCNT_OBJ | DISPCNT_FB1);
67 pos[0] = pos[1] = VOX_SZ << 15;
69 if(!(vox = vox_create(VOX_SZ, VOX_SZ, height_pixels, color_pixels))) {
70 panic(get_pc(), "vox_create");
72 vox_proj(vox, FOV, NEAR, FAR);
73 vox_view(vox, pos[0], pos[1], -40, angle);
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);
84 interrupt(INTR_HBLANK, hblank);
85 REG_DISPSTAT |= DISPSTAT_IEN_HBLANK;
90 spr_setup(16, 16, spr_game_pixels, spr_game_cmap);
94 for(i=0; i<MAX_SPR; i++) {
95 spr_oam_clear(oam, i);
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);
108 dma_copy32(3, (void*)OAM_ADDR, oam, sidx * 2, 0);
118 static void gamescr_stop(void)
120 /*mask(INTR_HBLANK);*/
123 static void gamescr_frame(void)
125 backbuf = ++nframes & 1;
126 framebuf = vram[backbuf];
128 vox_framebuf(vox, 240, 160, framebuf, horizon);
137 if(!(nframes & 15)) {
138 emuprint("vbl: %d", vblperf_count);
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)}
159 #define WALK_SPEED 0x40000
160 #define TURN_SPEED 0x200
163 static void update(void)
165 int32_t fwd[2], right[2];
170 if(KEYPRESS(BN_SELECT)) {
175 if(keystate & BN_LEFT) {
178 if(keystate & BN_RIGHT) {
182 fwd[0] = -SIN(angle);
187 if(keystate & BN_A) {
192 if(keystate & BN_DOWN) {
197 if(keystate & BN_UP) {
198 if(horizon > 40) horizon -= ELEV_SPEED;
200 if(keystate & BN_DOWN) {
201 if(horizon < 200 - ELEV_SPEED) horizon += ELEV_SPEED;
203 if(keystate & BN_RT) {
207 if(keystate & BN_LT) {
212 vox_view(vox, pos[0], pos[1], -40, angle);
217 spr_oam(oam, dynspr_base + snum++, numspr[num_tur][0], 200, 144, SPR_VRECT | SPR_256COL);
218 spr_oam(oam, dynspr_base + snum++, numspr[num_tur][1], 208, 144, SPR_VRECT | SPR_256COL);
219 spr_oam(oam, dynspr_base + snum++, numspr[total_tur][0], 224, 144, SPR_VRECT | SPR_256COL);
220 spr_oam(oam, dynspr_base + snum++, numspr[total_tur][1], 232, 144, SPR_VRECT | SPR_256COL);
222 if(energy == MAX_ENERGY) {
223 ledspr = SPRID_LEDBLU;
225 ledspr = energy > 2 ? SPRID_LEDGRN : SPRID_LEDRED;
228 spr_oam(oam, dynspr_base + snum++, i >= energy ? SPRID_LEDOFF : ledspr,
229 8 + (i << 3), 144, SPR_VRECT | SPR_256COL);
232 spr_oam(oam, dynspr_base + snum++, SPRID_ENEMY, 50, 50, SPR_VRECT | SPR_SZ64 | SPR_256COL);
239 static void draw(void)
241 //dma_fill16(3, framebuf, 0, 240 * 160 / 2);
242 fillblock_16byte(framebuf, 0, 240 * 160 / 16);
245 //vox_sky_grad(vox, COLOR_HORIZON, COLOR_ZENITH);
246 //vox_sky_solid(vox, COLOR_ZENITH);
249 #define OFFS(x, y) ((y) * 128 + (x))
250 static short enemy_frame_offs[] = {
251 OFFS(0, 128), OFFS(32, 128), OFFS(64, 128), OFFS(96, 128),
252 OFFS(0, 192), OFFS(32, 192), OFFS(64, 192), OFFS(96, 192)
255 #define MAXBANK 0x100
258 static void gamescr_vblank(void)
260 static int bank, bankdir, theta, s;
267 /* TODO: pre-arrange sprite tiles in gba-native format, so that I can just
268 * DMA them from cartridge easily
272 src = (void*)(spr_game_pixels + enemy_frame_offs[1]);
273 dst = (void*)(VRAM_LFB_OBJ_ADDR + SPRID(0, 64));
274 for(i=0; i<64; i++) {
275 dma_copy32(3, dst, src, 32 / 4, 0);
281 dma_copy32(3, (void*)(OAM_ADDR + dynspr_base * 8), oam + dynspr_base * 4, dynspr_count * 2, 0);
283 theta = -(bank << 3);
285 s = 0x100000 / (MAXBANK + (abs(bank) >> 3));
286 sa = ((SIN(theta) >> 8) * s) >> 12;
287 ca = ((COS(theta) >> 8) * s) >> 12;
289 s = (MAXBANK + (abs(bank) >> 3));
294 REG_BG2X = -ca * 120 - sa * 80 + (120 << 8);
295 REG_BG2Y = sa * 120 - ca * 80 + (80 << 8);
302 keystate = ~REG_KEYINPUT;
304 if((keystate & (BN_LEFT | BN_RIGHT)) == 0) {
306 bank -= bankdir << 4;
308 } else if(keystate & BN_LEFT) {
310 if(bank > -MAXBANK) bank -= 16;
311 } else if(keystate & BN_RIGHT) {
313 if(bank < MAXBANK) bank += 16;
318 static uint16_t skygrad[] __attribute__((section(".data"))) = {
320 0x662a, 0x660a, 0x660a, 0x660b, 0x660b, 0x660b, 0x660b, 0x6a0b, 0x6a0c,
321 0x6a0c, 0x6a0c, 0x6a0c, 0x6a0c, 0x6a0d, 0x6a0d, 0x6a0d, 0x6a0d, 0x6a0d,
322 0x6a0d, 0x6a0e, 0x6e0e, 0x6e0e, 0x6e0e, 0x6e0e, 0x6e0f, 0x6e0f, 0x6e0f,
323 0x6e0f, 0x6e0f, 0x6e0f, 0x6e10, 0x6e10, 0x7210, 0x7210, 0x7210, 0x7211,
324 0x7211, 0x7211, 0x71f1, 0x71f1, 0x71f2, 0x71f2, 0x71f2, 0x71f2, 0x71f2,
325 0x75f2, 0x75f3, 0x75f3, 0x75f3, 0x75f3, 0x75f3, 0x75f4, 0x75f4, 0x75f4,
326 0x75f4, 0x75f4, 0x75f5, 0x79f5, 0x79f5, 0x79f5, 0x79f5, 0x79f5, 0x79f6,
327 0x79f6, 0x79f6, 0x79f6, 0x79f6, 0x79f7, 0x79f7, 0x79f7, 0x7df7, 0x7df7,
328 0x7df7, 0x7df8, 0x7df8, 0x7df8, 0x7dd8, 0x7dd8, 0x7dd9, 0x7dd9,
330 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
331 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
332 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
333 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
334 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
335 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
336 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
337 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9,
338 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9, 0x7dd9
342 static void hblank(void)
344 int vcount = REG_VCOUNT;
345 gba_bgpal[255] = skygrad[vcount];