foo
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 8 Aug 2022 03:33:16 +0000 (06:33 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 8 Aug 2022 03:33:16 +0000 (06:33 +0300)
src/gamescr.c
src/player.c [new file with mode: 0644]
src/player.h [new file with mode: 0644]
src/polyfill.c
src/polyfill.h
src/xgl.c
src/xgl.h

index 3b15a4a..dcceb20 100644 (file)
@@ -6,6 +6,7 @@
 #include "util.h"
 #include "intr.h"
 #include "input.h"
 #include "util.h"
 #include "intr.h"
 #include "input.h"
+#include "player.h"
 #include "sprite.h"
 #include "debug.h"
 #include "level.h"
 #include "sprite.h"
 #include "debug.h"
 #include "level.h"
@@ -33,43 +34,18 @@ static const char *testlvl =
        "#### ###\n"
        "########\n";
 
        "#### ###\n"
        "########\n";
 
-static struct xvertex cube[] __attribute__((section(".rodata"))) = {
-       /* front */
-       {-0x10000, -0x10000, -0x10000,  0, 0, -0x10000, 255},
-       {0x10000, -0x10000, -0x10000,   0, 0, -0x10000, 255},
-       {0x10000, 0x10000, -0x10000,    0, 0, -0x10000, 255},
-       {-0x10000, 0x10000, -0x10000,   0, 0, -0x10000, 255},
-       /* right */
-       {0x10000, -0x10000, -0x10000,   0x10000, 0, 0,  128},
-       {0x10000, -0x10000, 0x10000,    0x10000, 0, 0,  128},
-       {0x10000, 0x10000, 0x10000,             0x10000, 0, 0,  128},
-       {0x10000, 0x10000, -0x10000,    0x10000, 0, 0,  128},
-       /* back */
-       {0x10000, -0x10000, 0x10000,    0, 0, 0x10000,  200},
-       {-0x10000, -0x10000, 0x10000,   0, 0, 0x10000,  200},
-       {-0x10000, 0x10000, 0x10000,    0, 0, 0x10000,  200},
-       {0x10000, 0x10000, 0x10000,             0, 0, 0x10000,  200},
-       /* left */
-       {-0x10000, -0x10000, 0x10000,   -0x10000, 0, 0, 192},
-       {-0x10000, -0x10000, -0x10000,  -0x10000, 0, 0, 192},
-       {-0x10000, 0x10000, -0x10000,   -0x10000, 0, 0, 192},
-       {-0x10000, 0x10000, 0x10000,    -0x10000, 0, 0, 192},
-       /* top */
-       {-0x10000, 0x10000, -0x10000,   0, 0x10000, 0,  150},
-       {0x10000, 0x10000, -0x10000,    0, 0x10000, 0,  150},
-       {0x10000, 0x10000, 0x10000,             0, 0x10000, 0,  150},
-       {-0x10000, 0x10000, 0x10000,    0, 0x10000, 0,  150},
-       /* bottom */
-       {0x10000, -0x10000, -0x10000,   0, -0x10000, 0, 210},
-       {-0x10000, -0x10000, -0x10000,  0, -0x10000, 0, 210},
-       {-0x10000, -0x10000, 0x10000,   0, -0x10000, 0, 210},
-       {0x10000, -0x10000, 0x10000,    0, -0x10000, 0, 210}
+static struct xvertex tm_floor[] __attribute__((section(".rodata"))) = {
+       {0x10000, -0x10000, 0x10000,    0, 0x10000, 0,  210},
+       {-0x10000, -0x10000, 0x10000,   0, 0x10000, 0,  210},
+       {-0x10000, -0x10000, -0x10000,  0, 0x10000, 0,  210},
+       {0x10000, -0x10000, -0x10000,   0, 0x10000, 0,  210}
 };
 
 
 static struct level *lvl;
 
 };
 
 
 static struct level *lvl;
 
-static int32_t cam_theta, cam_phi;
+static struct player player;
+
 
 void gamescr(void)
 {
 
 void gamescr(void)
 {
@@ -83,7 +59,10 @@ void gamescr(void)
 
        xgl_init();
 
 
        xgl_init();
 
-       select_input(BN_DPAD);
+       memset(&player, 0, sizeof player);
+       player.y = 0x60000;
+
+       select_input(BN_DPAD | BN_A | BN_B);
 
        mask(INTR_VBLANK);
        screen_vblank = vblank;
 
        mask(INTR_VBLANK);
        screen_vblank = vblank;
@@ -113,33 +92,17 @@ static void update(void)
 
        bnstate = get_input();
 
 
        bnstate = get_input();
 
-       if(bnstate & KEY_UP) {
-               cam_phi += 0x2000;
-               if(cam_phi > X_HPI) cam_phi = X_HPI;
-       }
-       if(bnstate & KEY_DOWN) {
-               cam_phi -= 0x2000;
-               if(cam_phi < -X_HPI) cam_phi = -X_HPI;
-       }
-       if(bnstate & KEY_LEFT) {
-               cam_theta += 0x2000;
-               if(cam_theta > X_2PI) cam_theta -= X_2PI;
-       }
-       if(bnstate & KEY_RIGHT) {
-               cam_theta -= 0x2000;
-               if(cam_theta < X_2PI) cam_theta += X_2PI;
-       }
+       player_input(&player, bnstate);
 }
 
 static void draw(void)
 {
        xgl_load_identity();
 }
 
 static void draw(void)
 {
        xgl_load_identity();
-       //xgl_translate(0, -0x50000, 0);
-       xgl_translate(0, 0, 0x80000);
-       xgl_rotate_x(cam_phi);
-       xgl_rotate_y(cam_theta);
+       xgl_rotate_x(player.phi);
+       xgl_rotate_y(player.theta);
+       xgl_translate(player.x, 0, player.y);
 
 
-       xgl_draw(XGL_QUADS, cube, sizeof cube / sizeof *cube);
+       xgl_draw(XGL_QUADS, tm_floor, sizeof tm_floor / sizeof *tm_floor);
 }
 
 __attribute__((noinline, target("arm"), section(".iwram")))
 }
 
 __attribute__((noinline, target("arm"), section(".iwram")))
diff --git a/src/player.c b/src/player.c
new file mode 100644 (file)
index 0000000..62c9813
--- /dev/null
@@ -0,0 +1,29 @@
+#include "player.h"
+#include "gbaregs.h"
+#include "xgl.h"
+
+void player_input(struct player *p, uint16_t bnstate)
+{
+       if(bnstate & KEY_UP) {
+               p->phi += 0x2000;
+               if(p->phi > X_HPI) p->phi = X_HPI;
+       }
+       if(bnstate & KEY_DOWN) {
+               p->phi -= 0x2000;
+               if(p->phi < -X_HPI) p->phi = -X_HPI;
+       }
+       if(bnstate & KEY_LEFT) {
+               p->theta += 0x2000;
+               if(p->theta > X_2PI) p->theta -= X_2PI;
+       }
+       if(bnstate & KEY_RIGHT) {
+               p->theta -= 0x2000;
+               if(p->theta < X_2PI) p->theta += X_2PI;
+       }
+       if(bnstate & KEY_A) {
+               p->y += 0x1000;
+       }
+       if(bnstate & KEY_B) {
+               p->y -= 0x1000;
+       }
+}
diff --git a/src/player.h b/src/player.h
new file mode 100644 (file)
index 0000000..6751691
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef PLAYER_H_
+#define PLAYER_H_
+
+#include <stdint.h>
+
+struct player {
+       int32_t x, y;
+       int32_t theta, phi;
+};
+
+void player_input(struct player *p, uint16_t bnstate);
+
+#endif /* PLAYER_H_ */
index 18294f5..5b70987 100644 (file)
@@ -1,6 +1,6 @@
 /*
 /*
-blender for the Gameboy Advance
-Copyright (C) 2021  John Tsiombikas <nuclear@member.fsf.org>
+gbajam22 entry for the Gameboy Advance
+Copyright (C) 2022  John Tsiombikas <nuclear@mutantstargoat.com>
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
index 88166cf..1afce36 100644 (file)
@@ -1,6 +1,6 @@
 /*
 /*
-blender for the Gameboy Advance
-Copyright (C) 2021  John Tsiombikas <nuclear@member.fsf.org>
+gbajam22 entry for the Gameboy Advance
+Copyright (C) 2022  John Tsiombikas <nuclear@mutantstargoat.com>
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
index deccdea..48db220 100644 (file)
--- a/src/xgl.c
+++ b/src/xgl.c
@@ -1,6 +1,6 @@
 /*
 /*
-blender for the Gameboy Advance
-Copyright (C) 2021  John Tsiombikas <nuclear@member.fsf.org>
+gbajam22 entry for the Gameboy Advance
+Copyright (C) 2022  John Tsiombikas <nuclear@mutantstargoat.com>
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -190,6 +190,8 @@ static void xform_norm(struct xvertex *out, const struct xvertex *in, const int3
 
 /* d = 1.0 / tan(fov/2) */
 #define PROJ_D 0x20000
 
 /* d = 1.0 / tan(fov/2) */
 #define PROJ_D 0x20000
+/* near Z = 0.5 */
+#define NEAR_Z 0x10000
 
 void xgl_draw(int prim, const struct xvertex *varr, int vcount)
 {
 
 void xgl_draw(int prim, const struct xvertex *varr, int vcount)
 {
@@ -204,47 +206,45 @@ void xgl_draw(int prim, const struct xvertex *varr, int vcount)
        }
 
        while(vcount >= prim) {
        }
 
        while(vcount >= prim) {
-               cidx = varr->cidx;
+               cidx = 0xff;//varr->cidx;
 
                xform(xv, varr, mat[mtop]);
                xform_norm(xv, varr, mat[mtop]);
 
 
                xform(xv, varr, mat[mtop]);
                xform_norm(xv, varr, mat[mtop]);
 
-               if(xv->nz > 0) {
-                       /* backface */
-                       varr += prim;
-                       vcount -= prim;
-                       continue;
-               }
+               /* backfacing check */
+               if(xv->nz > 0) goto skip_poly;
 
 
+               /*
                if(opt & XGL_LIGHTING) {
                        ndotl = (xv->nx >> 8) * ldir[0] + (xv->ny >> 8) * ldir[1] + (xv->nz >> 8) * ldir[2];
                        if(ndotl < 0) ndotl = 0;
                        cidx = 128 + (ndotl >> 9);
                        if(cidx > 255) cidx = 255;
                }
                if(opt & XGL_LIGHTING) {
                        ndotl = (xv->nx >> 8) * ldir[0] + (xv->ny >> 8) * ldir[1] + (xv->nz >> 8) * ldir[2];
                        if(ndotl < 0) ndotl = 0;
                        cidx = 128 + (ndotl >> 9);
                        if(cidx > 255) cidx = 255;
                }
+               */
 
 
-               xv->x = (xv->x << 1) / (xv->z >> 8);    /* assume aspect: ~2 */
-               xv->y = (xv->y << 2) / (xv->z >> 8);    /* the shift is * PROJ_D */
-               /* projection result is 24.8 */
-               /* viewport */
-               pv->x = (((xv->x + 0x100) >> 1) * vp[2]) + (vp[0] << 8);
-               pv->y = (((0x100 - xv->y) >> 1) * vp[3]) + (vp[1] << 8);
-               varr++;
-
-               for(i=1; i<prim; i++) {
-                       xform(xv + i, varr, mat[mtop]);
-
+               for(i=0; i<prim; i++) {
+                       if(i > 0) {
+                               xform(xv + i, varr + i, mat[mtop]);
+                       }
                        xv[i].x = (xv[i].x << 1) / (xv[i].z >> 8);      /* assume aspect: ~2 */
                        xv[i].y = (xv[i].y << 2) / (xv[i].z >> 8);      /* the shift is * PROJ_D */
                        xv[i].x = (xv[i].x << 1) / (xv[i].z >> 8);      /* assume aspect: ~2 */
                        xv[i].y = (xv[i].y << 2) / (xv[i].z >> 8);      /* the shift is * PROJ_D */
-                       /* projection result is 24.8 */
+                       /* transform result is 24.8 */
+               }
+
+               /* clip against near plane */
+
+
+               for(i=0; i<prim; i++) {
                        /* viewport */
                        pv[i].x = (((xv[i].x + 0x100) >> 1) * vp[2]) + (vp[0] << 8);
                        pv[i].y = (((0x100 - xv[i].y) >> 1) * vp[3]) + (vp[1] << 8);
                        /* viewport */
                        pv[i].x = (((xv[i].x + 0x100) >> 1) * vp[2]) + (vp[0] << 8);
                        pv[i].y = (((0x100 - xv[i].y) >> 1) * vp[3]) + (vp[1] << 8);
-                       varr++;
                }
                }
-               vcount -= prim;
 
                polyfill_flat(pv, prim, cidx);
 
                polyfill_flat(pv, prim, cidx);
+skip_poly:
+               varr += prim;
+               vcount -= prim;
        }
 }
 
        }
 }
 
@@ -284,7 +284,7 @@ static void draw_ptlines(int prim, const struct xvertex *varr, int vcount)
 #ifndef ALT_LCLIP
                clip_line((int*)&xv[0].x, (int*)&xv[0].y, (int*)&xv[1].x, (int*)&xv[1].y, vp[0], vp[1], vp[2] - 1, vp[3] - 1);
 #endif
 #ifndef ALT_LCLIP
                clip_line((int*)&xv[0].x, (int*)&xv[0].y, (int*)&xv[1].x, (int*)&xv[1].y, vp[0], vp[1], vp[2] - 1, vp[3] - 1);
 #endif
-               draw_line(xv[0].x, xv[0].y, xv[1].x, xv[1].y, varr[-2].cidx);
+               draw_line(xv[0].x, xv[0].y, xv[1].x, xv[1].y, 0xff);
        }
 }
 
        }
 }
 
@@ -292,3 +292,83 @@ void xgl_xyzzy(void)
 {
        mat[mtop][12] = mat[mtop][13] = 0;
 }
 {
        mat[mtop][12] = mat[mtop][13] = 0;
 }
+
+#define ISECT_NEAR(v0, v1)     ((((v0)->z - NEAR_Z) << 8) / (((v0)->z - (v1)->z) >> 8))
+
+#define LERP_VATTR(res, v0, v1, t) \
+       do { \
+               (res)->x = (v0)->x + (((v1)->x - (v0)->x) >> 8) * (t);  \
+               (res)->y = (v0)->y + (((v1)->y - (v0)->y) >> 8) * (t);  \
+               (res)->z = (v0)->z + (((v1)->z - (v0)->z) >> 8) * (t);  \
+               (res)->nx = (v0)->nx + (((v1)->nx - (v0)->nx) >> 8) * (t);      \
+               (res)->ny = (v0)->ny + (((v1)->ny - (v0)->ny) >> 8) * (t);      \
+               (res)->nz = (v0)->nz + (((v1)->nz - (v0)->nz) >> 8) * (t);      \
+               (res)->tx = (v0)->tx + (((v1)->tx - (v0)->tx) >> 8) * (t);      \
+               (res)->ty = (v0)->ty + (((v1)->ty - (v0)->ty) >> 8) * (t);      \
+               (res)->lit = (v0)->lit + (((v1)->lit - (v0)->lit) >> 8) * (t); \
+       } while(0)
+
+static int clip_edge_near(struct xvertex *poly, int *vnumptr, struct xvertex *v0, struct xvertex *v1)
+{
+       int vnum = *vnumptr;
+       int in0, in1;
+       int32_t t;
+       struct xvertex *vptr;
+
+       in0 = v0->z >= NEAR_Z ? 1 : 0;
+       in1 = v1->z >= NEAR_Z ? 1 : 0;
+
+       if(in0) {
+               /* start inside */
+               if(in1) {
+                       /* all inside */
+                       poly[vnum++] = *v1;     /* append v1 */
+                       *vnumptr = vnum;
+                       return 1;
+               } else {
+                       /* going out */
+                       vptr = poly + vnum;
+                       t = ISECT_NEAR(v0, v1); /* 24:8 */
+                       LERP_VATTR(vptr, v0, v1, t);
+                       ++vnum;         /* append new vertex on the intersection point */
+               }
+       } else {
+               /* start outside */
+               if(in1) {
+                       /* going in */
+                       vptr = poly + vnum;
+                       t = ISECT_NEAR(v0, v1);
+                       LERP_VATTR(vptr, v0, v1, t);
+                       ++vnum;         /* append new vertex ... */
+                       /* then append v1 */
+                       poly[vnum++] = *v1;
+               } else {
+                       /* all outside */
+                       return -1;
+               }
+       }
+
+       *vnumptr = vnum;
+       return 0;
+}
+
+/* special case near-plane clipper */
+int xgl_clip_near(struct xvertex *vout, int *voutnum, struct xvertex *vin, int vnum)
+{
+       int i, nextidx, res;
+       int edges_clipped = 0;
+
+       *voutnum = 0;
+
+       for(i=0; i<vnum; i++) {
+               nextidx = i + 1;
+               if(nextidx >= vnum) nextidx = 0;
+               res = clip_edge_near(vout, voutnum, vin + i, vin + nextidx);
+               if(res == 0) {
+                       ++edges_clipped;
+               }
+       }
+
+       if(*voutnum <= 0) return -1;
+       return edges_clipped > 0 ? 0 : 1;
+}
index eba42b5..9a2308b 100644 (file)
--- a/src/xgl.h
+++ b/src/xgl.h
@@ -1,6 +1,6 @@
 /*
 /*
-blender for the Gameboy Advance
-Copyright (C) 2021  John Tsiombikas <nuclear@member.fsf.org>
+gbajam22 entry for the Gameboy Advance
+Copyright (C) 2022  John Tsiombikas <nuclear@mutantstargoat.com>
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -37,7 +37,8 @@ enum {
 struct xvertex {
        int32_t x, y, z;
        int32_t nx, ny, nz;
 struct xvertex {
        int32_t x, y, z;
        int32_t nx, ny, nz;
-       unsigned char cidx;
+       int32_t tx, ty;
+       int32_t lit;
 };
 
 void xgl_init(void);
 };
 
 void xgl_init(void);