You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#include <stdlib.h>
#include <string.h>
#include "gbaregs.h"
#include "timer.h"
#include "keyb.h"
#include "intr.h"
#include "gfx.h"
+#include "xgl.h"
+#include "polyfill.h"
+#include "debug.h"
+#include "meshdata.h"
+#include "sprites.h"
+#include "dma.h"
+
+enum {
+ SIDX_DEL0, SIDX_DEL1, SIDX_DEL2,
+ SIDX_TIME,
+ SIDX_ICON_ZOOM,
+ SIDX_ICON_PAN,
+ SIDX_ICON_ORBIT,
+ SIDX_ICON_X,
+ SIDX_ICON_Y,
+ SIDX_ICON_Z,
+ SIDX_DIRTY
+};
+
+#define SIDX_ICONS_BASE SIDX_ICON_ZOOM
+
+#define SNAM_START 512
+enum {
+ SNAM_DEL0 = SNAM_START,
+ SNAM_DEL1 = SNAM_DEL0 + 8,
+ SNAM_DEL2 = SNAM_DEL1 + 8,
+ SNAM_ICON_ZOOM = SNAM_START + 24,
+ SNAM_ICON_PAN = SNAM_ICON_ZOOM + 4,
+ SNAM_ICON_ORBIT = SNAM_START + 32 * 4 + 24, /* for tiles down, 24 across */
+ SNAM_ICON_X = SNAM_START + 32 * 8 + 26,
+ SNAM_ICON_Y = SNAM_ICON_X + 2,
+ SNAM_ICON_Z = SNAM_ICON_Y + 2,
+ SNAM_DIRTY = SNAM_ICON_ORBIT + 4,
+ SNAM_TIME0 = SNAM_START + 32 * 8,
+ SNAM_TIME1 = SNAM_TIME0 + 32 * 2
+};
+
+#define MENU_HEIGHT 17
+#define TRACK_HEIGHT 18
+#define VP_HEIGHT (160 - MENU_HEIGHT - TRACK_HEIGHT)
static void handle_keys(void);
+static void upd_rotation(void);
+static void show_msgbox(int en);
extern struct { unsigned char r, g, b; } bgimg_cmap[];
extern unsigned char bgimg_pixels[];
+static int32_t cam_theta = 0x10000, cam_phi = -0x8000;
+static int32_t cam_pan_x, cam_pan_y;
+
+static int show_obj = 1, show_del;
+static int32_t rot_matrix[16];
+static int pan_mode;
+
+static int snam_time[26];
+static int spos_time[104];
+
+#define AXIS0 0x10000
+#define AXIS1 0x80000
+#define AXIS3 0x2c000
+
+static struct xvertex gridaxes[] = {
+ {AXIS0, 0, 0, 0, 0, 0, 92},
+ {AXIS1, 0, 0, 0, 0, 0, 92},
+ {-AXIS0, 0, 0, 0, 0, 0, 92},
+ {-AXIS1, 0, 0, 0, 0, 0, 92},
+ {0, 0, AXIS0, 0, 0, 0, 93},
+ {0, 0, AXIS1, 0, 0, 0, 93},
+ {0, 0, -AXIS0, 0, 0, 0, 93},
+ {0, 0, -AXIS1, 0, 0, 0, 93},
+
+ {0, 0, 0, 0, 0, 0, 92},
+ {AXIS1, 0, 0, 0, 0, 0, 92},
+ {0, 0, 0, 0, 0, 0, 92},
+ {-AXIS1, 0, 0, 0, 0, 0, 92},
+ {0, 0, 0, 0, 0, 0, 93},
+ {0, 0, AXIS1, 0, 0, 0, 93},
+ {0, 0, -0, 0, 0, 0, 93},
+ {0, 0, -AXIS1, 0, 0, 0, 93},
+};
+
+static struct xvertex small_axes[] = {
+ {0, 0, 0, 0, 0, 0, 92},
+ {AXIS3, 0, 0, 0, 0, 0, 92},
+ {0, 0, 0, 0, 0, 0, 93},
+ {0, 0, AXIS3, 0, 0, 0, 93},
+ {0, 0, 0, 0, 0, 0, 94},
+ {0, AXIS3, 0, 0, 0, 0, 94}
+};
+
+#define MAX_SIDX 16
+static uint16_t oam[4 * MAX_SIDX];
+
+
int main(void)
{
int i;
+ int x, y, anm;
+ unsigned int nframes = 0, backbuf;
uint16_t *cptr;
unsigned char r, g, b;
+ unsigned char *fbptr[2], *fb;
intr_init();
reset_msec_timer();
set_intr();
/* mode 4: 240x160 8bpp */
- REG_DISPCNT = DISPCNT_BG2 | 4;
+ REG_DISPCNT = DISPCNT_BG2 | DISPCNT_OBJ | 4;
+
+ fbptr[0] = (unsigned char*)VRAM_LFB_FB0_ADDR;
+ fbptr[1] = (unsigned char*)VRAM_LFB_FB1_ADDR;
+
+ set_bg_color(0xff, 31, 31, 31);
cptr = (uint16_t*)CRAM_BG_ADDR;
for(i=0; i<128; i++) {
b = bgimg_cmap[i].b >> 3;
*cptr++ = r | (g << 5) | (b << 10);
}
- memcpy((void*)VRAM_LFB_FB0_ADDR, bgimg_pixels, 240 * 160);
- memcpy((void*)VRAM_LFB_FB1_ADDR, bgimg_pixels, 240 * 160);
+ for(i=0; i<128; i++) {
+ r = i / 5 + 6;
+ *cptr++ = r | (r << 5) | (r << 10);
+ }
+ dma_copy16(3, fbptr[0], bgimg_pixels, 240 * 160 / 2, 0);
+ dma_copy16(3, fbptr[1], bgimg_pixels, 240 * 160 / 2, 0);
- /*key_repeat(500, 75, KEY_LEFT | KEY_RIGHT | KEY_DOWN | KEY_UP);*/
+ init_sprites();
+ REG_BLDCNT = BLDCNT_ALPHA | BLDCNT_B_BG2;
+ REG_BLDALPHA = 0x040c;
+
+ for(i=0; i<13; i++) {
+ snam_time[i] = SNAM_TIME0 + (i << 1);
+ snam_time[i + 13] = SNAM_TIME1 + (i << 1);
+ }
+ for(i=0; i<104; i++) {
+ int t = (i << 16) / 103;
+ spos_time[i] = (t * 223) >> 16;
+ }
+
+ set_sprite(oam, SIDX_ICONS_BASE, SNAM_ICON_ZOOM, 213, 57, 4, SPR_SZ32 | SPR_BLEND);
+ set_sprite(oam, SIDX_ICONS_BASE + 1, SNAM_ICON_PAN, 213, 81, 4, SPR_SZ32 | SPR_BLEND);
+ set_sprite(oam, SIDX_ICONS_BASE + 2, SNAM_ICON_ORBIT, 213, 103, 4, SPR_SZ32 | SPR_BLEND);
+ set_sprite(oam, SIDX_DIRTY, SNAM_DIRTY, 192, 9, 4, SPR_SZ16 | SPR_HRECT);
+
+ xgl_init();
+ xgl_enable(XGL_LIGHTING);
+
+ upd_rotation();
+
+ key_repeat(75, 75, KEY_LEFT | KEY_RIGHT | KEY_DOWN | KEY_UP | KEY_LT | KEY_RT);
+
+ /* every vblank, copy the shadow OAM automatically */
+ /*dma_copy16(3, (void*)OAM_ADDR, oam, sizeof oam / 2, DMACNT_VBLANK |
+ DMACNT_REPEAT | DMACNT_INC_RELOAD);*/
for(;;) {
+ handle_keys();
+
+ backbuf = ++nframes & 1;
+
+ fb = fbptr[backbuf] + 240 * MENU_HEIGHT;
+ polyfill_framebuffer(fb, 240, VP_HEIGHT);
+ dma_fill16(3, fb, 0x0e0e, 240 * VP_HEIGHT / 2);
+
+ xgl_viewport(0, 0, 240, VP_HEIGHT);
+ xgl_load_identity();
+ xgl_translate(-cam_pan_x, -cam_pan_y, 8 << 16);
+ xgl_mult_matrix(rot_matrix);
+
+ if(show_obj) {
+ if(cam_theta < X_PI) {
+ xgl_draw(XGL_LINES, gridaxes + 2, 2); /* -X */
+ } else {
+ xgl_draw(XGL_LINES, gridaxes, 2); /* +X */
+ }
+ if(cam_theta < X_HPI || cam_theta > (3 * X_HPI)) {
+ xgl_draw(XGL_LINES, gridaxes + 4, 2); /* +Z */
+ } else {
+ xgl_draw(XGL_LINES, gridaxes + 6, 2); /* -Z */
+ }
+ if(show_obj == 1) {
+ xgl_draw(XGL_QUADS, cube, sizeof cube / sizeof *cube);
+ } else {
+ xgl_draw(XGL_TRIANGLES, suzanne, sizeof suzanne / sizeof *suzanne);
+ }
+ if(cam_theta < X_PI) {
+ xgl_draw(XGL_LINES, gridaxes, 2); /* +X */
+ } else {
+ xgl_draw(XGL_LINES, gridaxes + 2, 2); /* -X */
+ }
+ if(cam_theta < X_HPI || cam_theta > (3 * X_HPI)) {
+ xgl_draw(XGL_LINES, gridaxes + 6, 2); /* -Z */
+ } else {
+ xgl_draw(XGL_LINES, gridaxes + 4, 2); /* +Z */
+ }
+ } else {
+ xgl_draw(XGL_LINES, gridaxes + 8, 8);
+ }
+
+ /* small axes */
+ xgl_viewport(176, 2, 64, 32);
+ xgl_xyzzy();
+ xgl_draw(XGL_LINES, small_axes, 6);
+
+ xgl_transform(small_axes + 5, &x, &y);
+ set_sprite(oam, SIDX_ICONS_BASE + 3, SNAM_ICON_Z, x - 8, y + 8, 3, SPR_SZ16);
+ xgl_transform(small_axes + 1, &x, &y);
+ set_sprite(oam, SIDX_ICONS_BASE + 4, SNAM_ICON_X, x - 8, y + 8, 1, SPR_SZ16);
+ xgl_transform(small_axes + 3, &x, &y);
+ set_sprite(oam, SIDX_ICONS_BASE + 5, SNAM_ICON_Y, x - 8, y + 8, 2, SPR_SZ16);
+
+ anm = (timer_msec >> 5) % 104;
+ set_sprite(oam, SIDX_TIME, snam_time[anm >> 2], spos_time[anm], 144, 5, SPR_SZ16);
+
wait_vblank();
- swap_buffers();
+ present(backbuf);
+ dma_copy16(3, (void*)OAM_ADDR, oam, sizeof oam / 2, 0);
}
return 0;
}
+#define PAN_SPEED 0x4000
+
static void handle_keys(void)
{
update_keyb();
if(KEYPRESS(KEY_UP)) {
+ if(pan_mode) {
+ cam_pan_y += PAN_SPEED;
+ if(cam_pan_y > 0x1c000) cam_pan_y = 0x1c000;
+ } else {
+ cam_phi += 0x2000;
+ if(cam_phi > X_HPI) cam_phi = X_HPI;
+ upd_rotation();
+ }
}
if(KEYPRESS(KEY_DOWN)) {
+ if(pan_mode) {
+ cam_pan_y -= PAN_SPEED;
+ if(cam_pan_y < -0x1c000) cam_pan_y = -0x1c000;
+ } else {
+ cam_phi -= 0x2000;
+ if(cam_phi < -X_HPI) cam_phi = -X_HPI;
+ upd_rotation();
+ }
}
if(KEYPRESS(KEY_LEFT)) {
+ if(pan_mode) {
+ cam_pan_x -= PAN_SPEED;
+ if(cam_pan_x < -0x50000) cam_pan_x = -0x50000;
+ } else {
+ cam_theta += 0x2000;
+ if(cam_theta > X_2PI) cam_theta -= X_2PI;
+ upd_rotation();
+ }
}
if(KEYPRESS(KEY_RIGHT)) {
+ if(pan_mode) {
+ cam_pan_x += PAN_SPEED;
+ if(cam_pan_x > 0x50000) cam_pan_x = 0x50000;
+ } else {
+ cam_theta -= 0x2000;
+ if(cam_theta < 0) cam_theta += X_2PI;
+ upd_rotation();
+ }
+ }
+
+ if(KEYPRESS(KEY_START)) {
+ pan_mode ^= 1;
+ }
+ if(KEYPRESS(KEY_SELECT)) {
+ if(show_obj) {
+ show_obj = ((show_obj - 1) ^ 1) + 1;
+ } else {
+ show_obj = 1;
+ }
+ }
+
+ if(KEYPRESS(KEY_RT)) {
+ cam_pan_x += PAN_SPEED;
+ }
+ if(KEYPRESS(KEY_LT)) {
+ cam_pan_x -= PAN_SPEED;
+ }
+
+ if(KEYPRESS(KEY_A)) {
+ if(!show_del) {
+ if(show_obj) show_del = 1;
+ } else {
+ show_del = 0;
+ }
+ show_msgbox(show_del);
+ }
+ if(KEYPRESS(KEY_B)) {
+ if(show_del) {
+ show_obj = 0;
+ show_del = 0;
+ show_msgbox(0);
+ }
+ }
+}
+
+static void upd_rotation(void)
+{
+ xgl_load_identity();
+ xgl_rotate_x(cam_phi);
+ xgl_rotate_y(cam_theta);
+ xgl_get_matrix(rot_matrix);
+}
+
+static void show_msgbox(int en)
+{
+ int i;
+
+ if(en) {
+ for(i=0; i<3; i++) {
+ set_sprite(oam, SIDX_DEL0 + i, SNAM_DEL0 + i * 8, 42 + i * 64, 50, 0,
+ SPR_SZ64 | SPR_BLEND);
+ }
+ } else {
+ for(i=0; i<3; i++) {
+ set_sprite(oam, SIDX_DEL0 + i, 0, 0, 0, 0, 0);
+ }
}
}