2 blender for the Gameboy Advance
3 Copyright (C) 2021 John Tsiombikas <nuclear@member.fsf.org>
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.
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.
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/>.
33 SIDX_DEL0, SIDX_DEL1, SIDX_DEL2,
38 #define SNAM_START 512
40 SNAM_DEL0 = SNAM_START,
41 SNAM_DEL1 = SNAM_DEL0 + 8,
42 SNAM_DEL2 = SNAM_DEL1 + 8,
43 SNAM_ICON_ZOOM = SNAM_START + 24,
44 SNAM_ICON_PAN = SNAM_ICON_ZOOM + 4,
45 SNAM_ICON_ORBIT = SNAM_START + 32 * 4 + 24, /* for tiles down, 24 across */
46 SNAM_ICON_X = SNAM_START + 32 * 8 + 26,
47 SNAM_ICON_Y = SNAM_ICON_X + 2,
48 SNAM_ICON_Z = SNAM_ICON_Y + 2
51 #define MENU_HEIGHT 17
52 #define TRACK_HEIGHT 18
53 #define VP_HEIGHT (160 - MENU_HEIGHT - TRACK_HEIGHT)
55 static void handle_keys(void);
56 static void show_msgbox(int en);
58 extern struct { unsigned char r, g, b; } bgimg_cmap[];
59 extern unsigned char bgimg_pixels[];
61 static int32_t cam_theta = 0x10000, cam_phi = -0x8000;
63 static int show_obj = 1, show_del;
68 static struct xvertex gridaxes[] = {
69 {AXIS0, 0, 0, 0, 0, 0, 92},
70 {AXIS1, 0, 0, 0, 0, 0, 92},
71 {-AXIS0, 0, 0, 0, 0, 0, 92},
72 {-AXIS1, 0, 0, 0, 0, 0, 92},
73 {0, 0, AXIS0, 0, 0, 0, 93},
74 {0, 0, AXIS1, 0, 0, 0, 93},
75 {0, 0, -AXIS0, 0, 0, 0, 93},
76 {0, 0, -AXIS1, 0, 0, 0, 93},
78 {0, 0, 0, 0, 0, 0, 92},
79 {AXIS1, 0, 0, 0, 0, 0, 92},
80 {0, 0, 0, 0, 0, 0, 92},
81 {-AXIS1, 0, 0, 0, 0, 0, 92},
82 {0, 0, 0, 0, 0, 0, 93},
83 {0, 0, AXIS1, 0, 0, 0, 93},
84 {0, 0, -0, 0, 0, 0, 93},
85 {0, 0, -AXIS1, 0, 0, 0, 93},
89 static uint16_t oam[4 * MAX_SIDX];
95 unsigned int nframes = 0, backbuf;
97 unsigned char r, g, b;
98 unsigned char *fbptr[2], *fb;
104 /* mode 4: 240x160 8bpp */
105 REG_DISPCNT = DISPCNT_BG2 | DISPCNT_OBJ | 4;
107 fbptr[0] = (unsigned char*)VRAM_LFB_FB0_ADDR;
108 fbptr[1] = (unsigned char*)VRAM_LFB_FB1_ADDR;
110 set_bg_color(0xff, 31, 31, 31);
112 cptr = (uint16_t*)CRAM_BG_ADDR;
113 for(i=0; i<128; i++) {
114 r = bgimg_cmap[i].r >> 3;
115 g = bgimg_cmap[i].g >> 3;
116 b = bgimg_cmap[i].b >> 3;
117 *cptr++ = r | (g << 5) | (b << 10);
119 for(i=0; i<128; i++) {
121 *cptr++ = r | (r << 5) | (r << 10);
123 dma_copy16(3, fbptr[0], bgimg_pixels, 240 * 160 / 2, 0);
124 dma_copy16(3, fbptr[1], bgimg_pixels, 240 * 160 / 2, 0);
127 REG_BLDCNT = BLDCNT_ALPHA | BLDCNT_B_BG2;
128 REG_BLDALPHA = 0x040c;
130 set_sprite(oam, SIDX_ICONS_BASE, SNAM_ICON_ZOOM, 213, 57, 4, SPR_SZ32);
131 set_sprite(oam, SIDX_ICONS_BASE + 1, SNAM_ICON_PAN, 213, 81, 4, SPR_SZ32);
132 set_sprite(oam, SIDX_ICONS_BASE + 2, SNAM_ICON_ORBIT, 213, 103, 4, SPR_SZ32);
135 xgl_viewport(0, 0, 240, VP_HEIGHT);
136 xgl_enable(XGL_LIGHTING);
138 key_repeat(75, 75, KEY_LEFT | KEY_RIGHT | KEY_DOWN | KEY_UP);
140 /* every vblank, copy the shadow OAM automatically */
141 /*dma_copy16(3, (void*)OAM_ADDR, oam, sizeof oam / 2, DMACNT_VBLANK |
142 DMACNT_REPEAT | DMACNT_INC_RELOAD);*/
147 backbuf = ++nframes & 1;
149 fb = fbptr[backbuf] + 240 * MENU_HEIGHT;
150 polyfill_framebuffer(fb, 240, VP_HEIGHT);
151 //memset(fb, 14, 240 * VP_HEIGHT);
152 dma_fill16(3, fb, 0x0e0e, 240 * VP_HEIGHT / 2);
155 xgl_translate(0, 0, 8 << 16);
156 xgl_rotate_x(cam_phi);
157 xgl_rotate_y(cam_theta);
160 if(cam_theta < X_PI) {
161 xgl_draw(XGL_LINES, gridaxes + 2, 2); /* -X */
163 xgl_draw(XGL_LINES, gridaxes, 2); /* +X */
165 if(cam_theta < X_HPI || cam_theta > (3 * X_HPI)) {
166 xgl_draw(XGL_LINES, gridaxes + 4, 2); /* +Z */
168 xgl_draw(XGL_LINES, gridaxes + 6, 2); /* -Z */
171 xgl_draw(XGL_QUADS, cube, sizeof cube / sizeof *cube);
173 xgl_draw(XGL_TRIANGLES, suzanne, sizeof suzanne / sizeof *suzanne);
175 if(cam_theta < X_PI) {
176 xgl_draw(XGL_LINES, gridaxes, 2); /* +X */
178 xgl_draw(XGL_LINES, gridaxes + 2, 2); /* -X */
180 if(cam_theta < X_HPI || cam_theta > (3 * X_HPI)) {
181 xgl_draw(XGL_LINES, gridaxes + 6, 2); /* -Z */
183 xgl_draw(XGL_LINES, gridaxes + 4, 2); /* +Z */
186 xgl_draw(XGL_LINES, gridaxes + 8, 8);
191 dma_copy16(3, (void*)OAM_ADDR, oam, sizeof oam / 2, 0);
197 static void handle_keys(void)
201 if(KEYPRESS(KEY_UP)) {
203 if(cam_phi > X_HPI) cam_phi = X_HPI;
205 if(KEYPRESS(KEY_DOWN)) {
207 if(cam_phi < -X_HPI) cam_phi = -X_HPI;
209 if(KEYPRESS(KEY_LEFT)) {
211 if(cam_theta > X_2PI) cam_theta -= X_2PI;
213 if(KEYPRESS(KEY_RIGHT)) {
215 if(cam_theta < 0) cam_theta += X_2PI;
217 if(KEYPRESS(KEY_RT)) {
218 if(++show_obj > 2) show_obj = 0;
220 if(KEYPRESS(KEY_LT)) {
221 if(--show_obj < 0) show_obj = 2;
224 if(KEYPRESS(KEY_A)) {
226 if(show_obj) show_del = 1;
230 show_msgbox(show_del);
232 if(KEYPRESS(KEY_B)) {
241 static void show_msgbox(int en)
247 set_sprite(oam, SIDX_DEL0 + i, SNAM_DEL0 + i * 8, 42 + i * 64, 50, 0,
248 SPR_SZ64 | SPR_BLEND);
252 set_sprite(oam, SIDX_DEL0 + i, 0, 0, 0, 0, 0);