foo
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 7 Aug 2022 17:12:06 +0000 (20:12 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 7 Aug 2022 17:12:06 +0000 (20:12 +0300)
Makefile
src/gamescr.c
src/level.c [new file with mode: 0644]
src/level.h [new file with mode: 0644]
src/util.c
src/util.h

index db4dd95..e61b6b9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,7 @@ inc = -I. -Ilibs/maxmod
 
 CFLAGS = $(opt) $(dbg) -pedantic -Wall -MMD $(def) $(inc)
 ASFLAGS = -mthumb-interwork
-LDFLAGS = -mthumb -mthumb-interwork $(libs)
+LDFLAGS = -mthumb -mthumb-interwork $(libs) -lm
 
 -include cfg.mk
 
index cacb40d..3b15a4a 100644 (file)
@@ -8,25 +8,82 @@
 #include "input.h"
 #include "sprite.h"
 #include "debug.h"
+#include "level.h"
+#include "xgl.h"
+#include "polyfill.h"
 
+static void update(void);
 static void draw(void);
 static void vblank(void);
 
 static int nframes, num_vbl, backbuf;
 static uint16_t *vram[] = { (uint16_t*)VRAM_LFB_FB0_ADDR, (uint16_t*)VRAM_LFB_FB1_ADDR };
-static uint16_t bnstate;
 
+static const char *testlvl =
+       "########\n"
+       "###   s#\n"
+       "### ####\n"
+       "###    #\n"
+       "##     #\n"
+       "##     #\n"
+       "##     #\n"
+       "## ### #\n"
+       "## ### #\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 level *lvl;
+
+static int32_t cam_theta, cam_phi;
 
 void gamescr(void)
 {
-       int i;
+       unsigned char *fb;
 
        REG_DISPCNT = 4 | DISPCNT_BG2 | DISPCNT_OBJ | DISPCNT_FB1;
 
-       vblperf_setcolor(0xff);//192);
+       vblperf_setcolor(0xff);
+
+       lvl = init_level(testlvl);
 
-       fillblock_16byte(vram[0], 0xffffffff, 240 * 160 / 16);
-       fillblock_16byte(vram[1], 0xffffffff, 240 * 160 / 16);
+       xgl_init();
+
+       select_input(BN_DPAD);
 
        mask(INTR_VBLANK);
        screen_vblank = vblank;
@@ -35,9 +92,12 @@ void gamescr(void)
        nframes = 0;
        for(;;) {
                backbuf = ++nframes & 1;
+               fb = (unsigned char*)vram[backbuf];
 
-               bnstate = ~REG_KEYINPUT;
+               polyfill_framebuffer(fb, 240, 160);
+               fillblock_16byte(fb, 0, 240 * 160 / 16);
 
+               update();
                draw();
 
                vblperf_end();
@@ -47,19 +107,39 @@ void gamescr(void)
        }
 }
 
-static void draw(void)
+static void update(void)
 {
-       int i, j;
-       uint16_t pix;
-       uint16_t *fb = vram[backbuf];
-
-       for(i=0; i<160; i++) {
-               for(j=0; j<240/2; j++) {
-                       pix = ((i^j) << 1) & 0xff;
-                       pix |= (i^j) << 9;
-                       *fb++ = pix;
-               }
+       uint16_t bnstate;
+
+       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;
+       }
+}
+
+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_draw(XGL_QUADS, cube, sizeof cube / sizeof *cube);
 }
 
 __attribute__((noinline, target("arm"), section(".iwram")))
diff --git a/src/level.c b/src/level.c
new file mode 100644 (file)
index 0000000..dfe3475
--- /dev/null
@@ -0,0 +1,76 @@
+#include "util.h"
+#include "debug.h"
+#include "level.h"
+
+struct level *init_level(const char *descstr)
+{
+       const char *str, *line;
+       int i, j, ncols = 0, nrows = 0;
+       struct level *lvl;
+       struct cell *cell;
+
+       str = line = descstr;
+
+       while(*str) {
+               if(*str == '\n') {
+                       if(ncols > 0 && str > line && str - line != ncols) {
+                               panic(get_pc(), "init_level: inconsistent ncols (%d != %d)\n", str - line, ncols);
+                       }
+                       ncols = str - line;
+                       nrows++;
+                       while(*++str == '\n');
+                       line = str;
+               } else {
+                       str++;
+               }
+       }
+
+       if(!ispow2(ncols)) {
+               panic(get_pc(), "init_level: width is not pow2 (%d)\n", ncols);
+       }
+
+       lvl = malloc_nf(sizeof *lvl);
+       lvl->width = ncols;
+       lvl->xmask = ncols - 1;
+       lvl->height = nrows;
+       lvl->cells = calloc_nf(ncols * nrows, sizeof *lvl->cells);
+       lvl->mobs = 0;
+       lvl->items = 0;
+
+       str = descstr;
+       cell = lvl->cells;
+
+       for(i=0; i<nrows; i++) {
+               for(j=0; j<ncols; j++) {
+                       cell->x = j;
+                       cell->y = i;
+                       if(*str == '#') {
+                               cell->type = CELL_SOLID;
+                       } else {
+                               cell->type = CELL_WALK;
+                       }
+                       cell++;
+                       while(*++str == '\n') str++;
+               }
+       }
+
+       return lvl;
+}
+
+void free_level(struct level *lvl)
+{
+       void *tmp;
+
+       free(lvl->cells);
+
+       while(lvl->mobs) {
+               tmp = lvl->mobs;
+               lvl->mobs = lvl->mobs->next;
+               free(tmp);
+       }
+       while(lvl->items) {
+               tmp = lvl->items;
+               lvl->items = lvl->items->next;
+               free(tmp);
+       }
+}
diff --git a/src/level.h b/src/level.h
new file mode 100644 (file)
index 0000000..0bcf578
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef LEVEL_H_
+#define LEVEL_H_
+
+#include <stdint.h>
+
+enum { MOBS_DEAD, MOBS_IDLE, MOBS_ENGAGE, MOBS_RUN };
+
+struct mob {
+       uint8_t type;
+       uint8_t x, y;
+       uint8_t state;
+       struct mob *next;
+       struct mob *cellnext;
+
+       void (*update)(void);
+};
+
+struct item {
+       uint8_t type;
+       uint8_t x, y;
+       uint8_t pad;
+       struct item *next;
+       struct item *cellnext;
+};
+
+enum { CELL_SOLID, CELL_WALK };
+
+struct cell {
+       uint8_t type;
+       uint8_t x, y;
+       uint8_t pad;
+       struct mob *mobs;
+       struct item *items;
+};
+
+struct level {
+       int width, height;
+       unsigned int xmask;
+       struct cell *cells;
+
+       struct mob *mobs;
+       struct item *items;
+};
+
+
+struct level *init_level(const char *descstr);
+void free_level(struct level *lvl);
+
+#endif /* LEVEL_H_ */
index 9bba42f..c734f85 100644 (file)
@@ -1,3 +1,5 @@
+#include <stdlib.h>
+#include <string.h>
 #include "util.h"
 #include "debug.h"
 
@@ -23,3 +25,54 @@ void *iwram_sbrk(intptr_t delta)
        iwram_brk(top + delta);
        return prev;
 }
+
+int ispow2(unsigned int x)
+{
+       int cnt = 0;
+       while(x) {
+               if(x & 1) cnt++;
+               x >>= 1;
+       }
+       return cnt == 1;
+}
+
+
+
+void *malloc_nf_impl(size_t sz, const char *file, int line)
+{
+       void *p;
+       if(!(p = malloc(sz))) {
+               panic(get_pc(), "%s:%d malloc %lu\n", file, line, (unsigned long)sz);
+       }
+       return p;
+}
+
+void *calloc_nf_impl(size_t num, size_t sz, const char *file, int line)
+{
+       void *p;
+       if(!(p = calloc(num, sz))) {
+               panic(get_pc(), "%s:%d calloc %lu\n", file, line, (unsigned long)(num * sz));
+       }
+       return p;
+}
+
+void *realloc_nf_impl(void *p, size_t sz, const char *file, int line)
+{
+       if(!(p = realloc(p, sz))) {
+               panic(get_pc(), "%s:%d realloc %lu\n", file, line, (unsigned long)sz);
+       }
+       return p;
+}
+
+char *strdup_nf_impl(const char *s, const char *file, int line)
+{
+       int len;
+       char *res;
+
+       len = strlen(s);
+       if(!(res = malloc(len + 1))) {
+               panic(get_pc(), "%s:%d strdup\n", file, line);
+       }
+       memcpy(res, s, len + 1);
+       return res;
+}
index 789e63e..18c513e 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef UTIL_H_
 #define UTIL_H_
 
+#include <stdlib.h>
 #include <stdint.h>
 
 #define wait_vblank() \
@@ -33,4 +34,19 @@ void fillblock_16byte(void *dest, uint32_t val, int count);
 void *get_pc(void);
 void *get_sp(void);
 
+int ispow2(unsigned int x);
+
+/* Non-failing versions of malloc/calloc/realloc. They never return 0, they call
+ * demo_abort on failure. Use the macros, don't call the *_impl functions.
+ */
+#define malloc_nf(sz)  malloc_nf_impl(sz, __FILE__, __LINE__)
+void *malloc_nf_impl(size_t sz, const char *file, int line);
+#define calloc_nf(n, sz)       calloc_nf_impl(n, sz, __FILE__, __LINE__)
+void *calloc_nf_impl(size_t num, size_t sz, const char *file, int line);
+#define realloc_nf(p, sz)      realloc_nf_impl(p, sz, __FILE__, __LINE__)
+void *realloc_nf_impl(void *p, size_t sz, const char *file, int line);
+#define strdup_nf(s)   strdup_nf_impl(s, __FILE__, __LINE__)
+char *strdup_nf_impl(const char *s, const char *file, int line);
+
+
 #endif /* UTIL_H_ */