bd0b2874e99c7ef55d8d3aad197d2a461bce0137
[gba_blender] / src / main.c
1 /*
2 blender for the Gameboy Advance
3 Copyright (C) 2021  John Tsiombikas <nuclear@member.fsf.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18 #include <stdlib.h>
19 #include <string.h>
20 #include "gbaregs.h"
21 #include "timer.h"
22 #include "keyb.h"
23 #include "intr.h"
24 #include "gfx.h"
25 #include "xgl.h"
26 #include "polyfill.h"
27 #include "debug.h"
28 #include "meshdata.h"
29
30 #define MENU_HEIGHT             17
31 #define TRACK_HEIGHT    18
32 #define VP_HEIGHT               (160 - MENU_HEIGHT - TRACK_HEIGHT)
33
34 static void handle_keys(void);
35
36 extern struct { unsigned char r, g, b; } bgimg_cmap[];
37 extern unsigned char bgimg_pixels[];
38
39 static int32_t cam_theta, cam_phi;
40
41 int main(void)
42 {
43         int i;
44         unsigned int nframes = 0, backbuf;
45         uint16_t *cptr;
46         unsigned char r, g, b;
47         unsigned char *fbptr[2], *fb;
48
49         intr_init();
50         reset_msec_timer();
51         set_intr();
52
53         /* mode 4: 240x160 8bpp */
54         REG_DISPCNT = DISPCNT_BG2 | 4;
55
56         fbptr[0] = (unsigned char*)VRAM_LFB_FB0_ADDR;
57         fbptr[1] = (unsigned char*)VRAM_LFB_FB1_ADDR;
58
59         set_bg_color(0xff, 31, 31, 31);
60
61         cptr = (uint16_t*)CRAM_BG_ADDR;
62         for(i=0; i<128; i++) {
63                 r = bgimg_cmap[i].r >> 3;
64                 g = bgimg_cmap[i].g >> 3;
65                 b = bgimg_cmap[i].b >> 3;
66                 *cptr++ = r | (g << 5) | (b << 10);
67         }
68         for(i=0; i<128; i++) {
69                 r = (rand() & 0xf) + 8;
70                 g = (rand() & 0xf) + 8;
71                 b = (rand() & 0xf) + 8;
72                 *cptr++ = r | (g << 5) | (b << 10);
73         }
74         memcpy(fbptr[0], bgimg_pixels, 240 * 160);
75         memcpy(fbptr[1], bgimg_pixels, 240 * 160);
76
77         xgl_init();
78         xgl_viewport(0, MENU_HEIGHT, 240, VP_HEIGHT);
79
80         key_repeat(75, 75, KEY_LEFT | KEY_RIGHT | KEY_DOWN | KEY_UP);
81
82         for(;;) {
83                 handle_keys();
84
85                 backbuf = ++nframes & 1;
86
87                 fb = fbptr[backbuf] + 240 * MENU_HEIGHT;
88                 polyfill_framebuffer(fb, 240, VP_HEIGHT);
89                 memset(fb, 14, 240 * VP_HEIGHT);
90
91                 xgl_load_identity();
92                 xgl_translate(0, 0, 5 << 16);
93                 xgl_rotate_x(cam_phi);
94                 xgl_rotate_y(cam_theta);
95 //              xgl_draw(XGL_QUADS, cube, sizeof cube / sizeof *cube);
96                 xgl_draw(XGL_TRIANGLES, suzanne, sizeof suzanne / sizeof *suzanne);
97
98                 wait_vblank();
99                 present(backbuf);
100         }
101
102         return 0;
103 }
104
105 static void handle_keys(void)
106 {
107         update_keyb();
108
109         if(KEYPRESS(KEY_UP)) {
110                 cam_phi += 0x2000;
111                 if(cam_phi > X_HPI) cam_phi = X_HPI;
112         }
113         if(KEYPRESS(KEY_DOWN)) {
114                 cam_phi -= 0x2000;
115                 if(cam_phi < -X_HPI) cam_phi = -X_HPI;
116         }
117         if(KEYPRESS(KEY_LEFT)) {
118                 cam_theta += 0x2000;
119         }
120         if(KEYPRESS(KEY_RIGHT)) {
121                 cam_theta -= 0x2000;
122         }
123 }