broken, adding the voxelburg code and fixing it up for real mode
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 31 Aug 2024 03:08:10 +0000 (06:08 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 31 Aug 2024 03:08:10 +0000 (06:08 +0300)
.gitignore
Makefile
src/dos/main.c
src/game.c [new file with mode: 0644]
src/game.h [new file with mode: 0644]
src/gamescr.c [new file with mode: 0644]
src/lut.asm [new file with mode: 0644]
src/menuscr.c [new file with mode: 0644]
src/util.h [new file with mode: 0644]
src/voxscape.c [new file with mode: 0644]
src/voxscape.h [new file with mode: 0644]

index d433bc9..11de58e 100644 (file)
@@ -6,3 +6,4 @@
 *.lnk
 *.map
 *.zip
+*.err
index 9f4970d..584997a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,9 @@
 !ifdef __UNIX__
-obj = src/dos/main.obj src/dos/video.obj
+obj = src/dos/main.obj src/dos/video.obj src/gamescr.obj src/menuscr.obj &
+       src/voxscape.obj src/lut.obj
 !else
-obj = src\dos\main.obj src\dos\video.obj
+obj = src\dos\main.obj src\dos\video.obj src\gamescr.obj src\menuscr.obj &
+       src\voxscape.obj src\lut.obj
 !endif
 bin = game.com
 
index 962ed5d..bc8d89d 100644 (file)
@@ -1,5 +1,6 @@
 #include <conio.h>
 #include "video.h"
+#include "game.h"
 
 static void draw(void);
 void handle_key(int key);
@@ -9,8 +10,13 @@ static int quit;
 
 int main(void)
 {
+       if(init_screens() == -1) {
+               return 1;
+       }
+
        init_video();
 
+       change_screen(scrlist[SCR_GAME]);
        for(;;) {
                while(kbhit()) {
                        int c = getch();
@@ -30,6 +36,7 @@ static void draw(void)
 {
        vid_clearfb();
 
+       curscr->draw();
 
        vid_pgflip(1);
 }
@@ -41,6 +48,8 @@ void handle_key(int key)
        case 27:
                quit = 1;
                break;
+
+       default:
+               curscr->keypress(key);
        }
 }
-
diff --git a/src/game.c b/src/game.c
new file mode 100644 (file)
index 0000000..d543b61
--- /dev/null
@@ -0,0 +1,30 @@
+#include "game.h"
+
+int gamescr_init(void);
+int menuscr_init(void);
+
+struct screen *scrlist[NUM_SCREENS];
+struct screen *curscr;
+
+int init_screens(void)
+{
+       if(menuscr_init() == -1) {
+               return -1;
+       }
+       if(gamescr_init() == -1) {
+               return -1;
+       }
+       return 0;
+}
+
+int change_screen(struct screen *scr)
+{
+       if(scr->start() == -1) {
+               return -1;
+       }
+       if(curscr) {
+               curscr->stop();
+       }
+       curscr = scr;
+       return 0;
+}
diff --git a/src/game.h b/src/game.h
new file mode 100644 (file)
index 0000000..e4cbf98
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef GAME_H_
+#define GAME_H_
+
+enum {
+       SCR_MENU,
+       SCR_GAME,
+
+       NUM_SCREENS
+};
+
+struct screen {
+       int (*start)(void);
+       void (*stop)(void);
+       void (*draw)(void);
+       void (*keypress)(int key);
+};
+
+extern struct screen *scrlist[NUM_SCREENS];
+extern struct screen *curscr;
+
+#define FBWIDTH                320
+#define FBHEIGHT       200
+
+int init_screens(void);
+int change_screen(struct screen *scr);
+
+void panic(const char *fmt, ...);
+
+#endif /* GAME_H_ */
diff --git a/src/gamescr.c b/src/gamescr.c
new file mode 100644 (file)
index 0000000..cd4b4b8
--- /dev/null
@@ -0,0 +1,34 @@
+#include "game.h"
+
+static int gamescr_start(void);
+static void gamescr_stop(void);
+static void gamescr_draw(void);
+static void gamescr_keypress(int key);
+
+static struct screen gamescr = {
+       gamescr_start, gamescr_stop,
+       gamescr_draw,
+       gamescr_keypress
+};
+
+int gamescr_init(void)
+{
+       return 0;
+}
+
+static int gamescr_start(void)
+{
+       return 0;
+}
+
+static void gamescr_stop(void)
+{
+}
+
+static void gamescr_draw(void)
+{
+}
+
+static void gamescr_keypress(int key)
+{
+}
diff --git a/src/lut.asm b/src/lut.asm
new file mode 100644 (file)
index 0000000..381cab1
--- /dev/null
@@ -0,0 +1,261 @@
+       bits 16
+segment DATA
+
+       global _sinlut
+_sinlut:
+       dw 0
+       dw 804
+       dw 1607
+       dw 2410
+       dw 3211
+       dw 4011
+       dw 4807
+       dw 5601
+       dw 6392
+       dw 7179
+       dw 7961
+       dw 8739
+       dw 9511
+       dw 10278
+       dw 11038
+       dw 11792
+       dw 12539
+       dw 13278
+       dw 14009
+       dw 14732
+       dw 15446
+       dw 16150
+       dw 16845
+       dw 17530
+       dw 18204
+       dw 18867
+       dw 19519
+       dw 20159
+       dw 20787
+       dw 21402
+       dw 22004
+       dw 22594
+       dw 23169
+       dw 23731
+       dw 24278
+       dw 24811
+       dw 25329
+       dw 25831
+       dw 26318
+       dw 26789
+       dw 27244
+       dw 27683
+       dw 28105
+       dw 28510
+       dw 28897
+       dw 29268
+       dw 29621
+       dw 29955
+       dw 30272
+       dw 30571
+       dw 30851
+       dw 31113
+       dw 31356
+       dw 31580
+       dw 31785
+       dw 31970
+       dw 32137
+       dw 32284
+       dw 32412
+       dw 32520
+       dw 32609
+       dw 32678
+       dw 32727
+       dw 32757
+       dw 32766
+       dw 32757
+       dw 32727
+       dw 32678
+       dw 32609
+       dw 32520
+       dw 32412
+       dw 32284
+       dw 32137
+       dw 31970
+       dw 31785
+       dw 31580
+       dw 31356
+       dw 31113
+       dw 30851
+       dw 30571
+       dw 30272
+       dw 29955
+       dw 29621
+       dw 29268
+       dw 28897
+       dw 28510
+       dw 28105
+       dw 27683
+       dw 27244
+       dw 26789
+       dw 26318
+       dw 25831
+       dw 25329
+       dw 24811
+       dw 24278
+       dw 23731
+       dw 23169
+       dw 22594
+       dw 22004
+       dw 21402
+       dw 20787
+       dw 20159
+       dw 19519
+       dw 18867
+       dw 18204
+       dw 17530
+       dw 16845
+       dw 16150
+       dw 15446
+       dw 14732
+       dw 14009
+       dw 13278
+       dw 12539
+       dw 11792
+       dw 11038
+       dw 10278
+       dw 9511
+       dw 8739
+       dw 7961
+       dw 7179
+       dw 6392
+       dw 5601
+       dw 4807
+       dw 4011
+       dw 3211
+       dw 2410
+       dw 1607
+       dw 804
+       dw 0
+       dw -804
+       dw -1607
+       dw -2410
+       dw -3211
+       dw -4011
+       dw -4807
+       dw -5601
+       dw -6392
+       dw -7179
+       dw -7961
+       dw -8739
+       dw -9511
+       dw -10278
+       dw -11038
+       dw -11792
+       dw -12539
+       dw -13278
+       dw -14009
+       dw -14732
+       dw -15446
+       dw -16150
+       dw -16845
+       dw -17530
+       dw -18204
+       dw -18867
+       dw -19519
+       dw -20159
+       dw -20787
+       dw -21402
+       dw -22004
+       dw -22594
+       dw -23169
+       dw -23731
+       dw -24278
+       dw -24811
+       dw -25329
+       dw -25831
+       dw -26318
+       dw -26789
+       dw -27244
+       dw -27683
+       dw -28105
+       dw -28510
+       dw -28897
+       dw -29268
+       dw -29621
+       dw -29955
+       dw -30272
+       dw -30571
+       dw -30851
+       dw -31113
+       dw -31356
+       dw -31580
+       dw -31785
+       dw -31970
+       dw -32137
+       dw -32284
+       dw -32412
+       dw -32520
+       dw -32609
+       dw -32678
+       dw -32727
+       dw -32757
+       dw -32766
+       dw -32757
+       dw -32727
+       dw -32678
+       dw -32609
+       dw -32520
+       dw -32412
+       dw -32284
+       dw -32137
+       dw -31970
+       dw -31785
+       dw -31580
+       dw -31356
+       dw -31113
+       dw -30851
+       dw -30571
+       dw -30272
+       dw -29955
+       dw -29621
+       dw -29268
+       dw -28897
+       dw -28510
+       dw -28105
+       dw -27683
+       dw -27244
+       dw -26789
+       dw -26318
+       dw -25831
+       dw -25329
+       dw -24811
+       dw -24278
+       dw -23731
+       dw -23169
+       dw -22594
+       dw -22004
+       dw -21402
+       dw -20787
+       dw -20159
+       dw -19519
+       dw -18867
+       dw -18204
+       dw -17530
+       dw -16845
+       dw -16150
+       dw -15446
+       dw -14732
+       dw -14009
+       dw -13278
+       dw -12539
+       dw -11792
+       dw -11038
+       dw -10278
+       dw -9511
+       dw -8739
+       dw -7961
+       dw -7179
+       dw -6392
+       dw -5601
+       dw -4807
+       dw -4011
+       dw -3211
+       dw -2410
+       dw -1607
+       dw -804
diff --git a/src/menuscr.c b/src/menuscr.c
new file mode 100644 (file)
index 0000000..0579e01
--- /dev/null
@@ -0,0 +1,34 @@
+#include "game.h"
+
+static int menuscr_start(void);
+static void menuscr_stop(void);
+static void menuscr_draw(void);
+static void menuscr_keypress(int key);
+
+static struct screen menuscr = {
+       menuscr_start, menuscr_stop,
+       menuscr_draw,
+       menuscr_keypress
+};
+
+int menuscr_init(void)
+{
+       return 0;
+}
+
+static int menuscr_start(void)
+{
+       return 0;
+}
+
+static void menuscr_stop(void)
+{
+}
+
+static void menuscr_draw(void)
+{
+}
+
+static void menuscr_keypress(int key)
+{
+}
diff --git a/src/util.h b/src/util.h
new file mode 100644 (file)
index 0000000..c9a3443
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef UTIL_H_
+#define UTIL_H_
+
+extern short sinlut[];
+
+#define SINLUT_BITS            8
+#define SINLUT_SIZE            (1 << SINLUT_BITS)
+
+#define SIN(angle) \
+       sinlut[((angle) >> (16 - SINLUT_BITS)) & (SINLUT_SIZE - 1)]
+
+#define COS(angle) \
+       sinlut[(((angle) >> (16 - SINLUT_BITS)) + (SINLUT_SIZE / 4)) & (SINLUT_SIZE - 1)]
+
+
+
+#endif /* UTIL_H_ */
diff --git a/src/voxscape.c b/src/voxscape.c
new file mode 100644 (file)
index 0000000..41cd0ea
--- /dev/null
@@ -0,0 +1,267 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <math.h>
+#include <assert.h>
+#include "game.h"
+#include "util.h"
+#include "voxscape.h"
+
+#define FBPITCH                FBWIDTH
+#define NO_LERP
+
+#define XLERP(a, b, t, fp) \
+       ((((a) << (fp)) + ((b) - (a)) * (t)) >> fp)
+
+enum {
+       SLICELEN        = 1
+};
+
+static unsigned int xsz, ysz, xshift, xmask, ymask, hscale;
+static unsigned char far *vox_hmap;
+static unsigned char far *vox_color;
+/* framebuffer */
+static uint16_t *vox_fb;
+static int *vox_coltop;
+static int vox_horizon;
+/* view */
+static int32_t vox_x, vox_y, vox_angle;
+static int vox_vheight;
+/* projection */
+static int vox_fov, vox_znear, vox_zfar;
+static int vox_nslices;
+static int32_t *vox_slicelen;
+
+static unsigned int vox_valid;
+
+static struct vox_object *vox_obj;
+static int vox_num_obj, vox_obj_stride;
+
+int *projlut;
+
+int vox_init(int xsz, int ysz, uint8_t far *himg, uint8_t far *cimg)
+{
+       vox_hmap = himg;
+       vox_color = cimg;
+
+       vox_fb = 0;
+       vox_coltop = 0;
+       vox_horizon = 0;
+       vox_x = vox_y = vox_angle = 0;
+       vox_fov = 0;
+       vox_znear = vox_zfar = 0;
+       vox_nslices = 0;
+       vox_slicelen = 0;
+       vox_valid = 0;
+       projlut = 0;
+
+       vox_vheight = 80;
+
+       return 0;
+}
+
+void vox_destroy(void)
+{
+       _ffree(vox_coltop);
+       vox_coltop = 0;
+       _ffree(vox_slicelen);
+       vox_slicelen = 0;
+       _ffree(projlut);
+}
+
+#define H(x, y)        \
+       vox_hmap[((((y) >> 16) & ymask) << xshift) + (((x) >> 16) & xmask)]
+#define C(x, y) \
+       vox_color[((((y) >> 16) & ymask) << xshift) + (((x) >> 16) & xmask)]
+
+void vox_framebuf(int xres, int yres, void *fb, int horizon)
+{
+       if(!vox_coltop) {
+               if(!(vox_coltop = _fmalloc(xres * sizeof *vox_coltop))) {
+                       panic("vox_framebuf: failed to allocate column table (%d)\n", xres);
+               }
+       }
+       vox_fb = fb;
+       vox_horizon = horizon >= 0 ? horizon : (FBHEIGHT >> 1);
+}
+
+int vox_view(int32_t x, int32_t y, int h, int32_t angle)
+{
+       if(h < 0) {
+               h = H(x, y) - h;
+       }
+
+       vox_x = x;
+       vox_y = y;
+       vox_vheight = h;
+       vox_angle = angle;
+
+       vox_valid &= ~SLICELEN;
+
+       return h;
+}
+
+void vox_proj(int fov, int znear, int zfar)
+{
+       vox_fov = fov;
+       vox_znear = znear;
+       vox_zfar = zfar;
+
+       vox_nslices = vox_zfar - vox_znear;
+       if(!vox_slicelen) {
+               if(!(vox_slicelen = _fmalloc(vox_nslices * sizeof *vox_slicelen))) {
+                       panic("vox_proj: failed to allocate slice length table (%d)\n", vox_nslices);
+               }
+               if(!(projlut = _fmalloc(vox_nslices * sizeof *projlut))) {
+                       panic("vox_framebuf: failed to allocate projection table (%d)\n", vox_nslices);
+               }
+       }
+
+       vox_valid &= ~SLICELEN;
+}
+
+/* algorithm:
+ * calculate extents of horizontal equidistant line from the viewer based on fov
+ * for each column step along this line and compute height for each pixel
+ * fill the visible (top) part of each column
+ */
+void vox_render(void)
+{
+       int i;
+
+       vox_begin();
+
+       for(i=0; i<vox_nslices; i++) {
+               vox_render_slice(i);
+       }
+}
+
+void vox_begin(void)
+{
+       int i;
+
+       memset(vox_coltop, 0, FBWIDTH * sizeof *vox_coltop);
+
+       if(!(vox_valid & SLICELEN)) {
+               float theta = (float)vox_fov * M_PI / 360.0f;   /* half angle */
+               for(i=0; i<vox_nslices; i++) {
+                       vox_slicelen[i] = (int32_t)((vox_znear + i) * tan(theta) * 4.0f * 65536.0f);
+                       projlut[i] = (hscale << 8) / (vox_znear + i);
+               }
+               vox_valid |= SLICELEN;
+       }
+}
+
+void vox_render_slice(int n)
+{
+       int i, j, hval, last_hval, colstart, colheight, col, z, offs, last_offs = -1;
+       int32_t x, y, len, xstep, ystep;
+       uint8_t color, last_col;
+       uint16_t *fbptr;
+       /*int proj;*/
+       struct vox_object *obj;
+
+       z = vox_znear + n;
+
+       len = vox_slicelen[n] >> 8;
+       xstep = (((COS(vox_angle) >> 4) * len) >> 4) / (FBWIDTH / 2);
+       ystep = (((SIN(vox_angle) >> 4) * len) >> 4) / (FBWIDTH / 2);
+
+       x = vox_x - SIN(vox_angle) * z - xstep * (FBWIDTH / 4);
+       y = vox_y + COS(vox_angle) * z - ystep * (FBWIDTH / 4);
+
+       /*proj = (HSCALE << 8) / (vox_znear + n);*/
+
+       for(i=0; i<FBWIDTH/2; i++) {
+               col = i << 1;
+               offs = (((y >> 16) & ymask) << xshift) + ((x >> 16) & xmask);
+               if(offs == last_offs) {
+                       hval = last_hval;
+                       color = last_col;
+               } else {
+                       hval = vox_hmap[offs] - vox_vheight;
+                       hval = ((hval * projlut[n]) >> 8) + vox_horizon;
+                       if(hval > FBHEIGHT) hval = FBHEIGHT;
+                       color = vox_color[offs];
+                       last_offs = offs;
+                       last_hval = hval;
+                       last_col = color;
+               }
+               if(hval >= vox_coltop[col]) {
+                       colstart = FBHEIGHT - hval;
+                       colheight = hval - vox_coltop[col];
+                       fbptr = vox_fb + colstart * (FBPITCH / 2) + i;
+
+                       for(j=0; j<colheight; j++) {
+                               *fbptr = color | ((uint16_t)color << 8);
+                               fbptr += FBPITCH / 2;
+                       }
+                       vox_coltop[col] = hval;
+
+                       /* check to see if there's an object here */
+                       if(color >= CMAP_SPAWN0) {
+                               int idx = color - CMAP_SPAWN0;
+                               obj = (struct vox_object*)((char*)vox_obj + (idx << OBJ_STRIDE_SHIFT));
+                               obj->px = col;
+                               obj->py = colstart;
+                               obj->scale = projlut[n];
+                       }
+               }
+               x += xstep;
+               y += ystep;
+       }
+}
+
+void vox_sky_solid(uint8_t color)
+{
+       int i, j, colheight;
+       uint16_t *fbptr;
+
+       for(i=0; i<FBWIDTH / 2; i++) {
+               fbptr = vox_fb + i;
+               colheight = FBHEIGHT - vox_coltop[i << 1];
+
+               for(j=0; j<colheight; j++) {
+                       *fbptr = color | ((uint16_t)color << 8);
+                       fbptr += FBPITCH / 2;
+               }
+       }
+}
+
+void vox_sky_grad(uint8_t chor, uint8_t ctop)
+{
+       int i, j, colheight, t;
+       int d = FBHEIGHT - vox_horizon;
+       uint8_t grad[FBHEIGHT];
+       uint16_t *fbptr;
+
+       for(i=0; i<d; i++) {
+               t = (i << 16) / d;
+               grad[i] = XLERP(ctop, chor, t, 16);
+       }
+       for(i=d; i<FBHEIGHT; i++) {
+               grad[i] = chor;
+       }
+
+       for(i=0; i<FBWIDTH / 2; i++) {
+               fbptr = vox_fb + i;
+               colheight = FBHEIGHT - vox_coltop[i << 1];
+
+               for(j=0; j<colheight; j++) {
+                       *fbptr = grad[j] | ((uint16_t)grad[j] << 8);
+                       fbptr += FBPITCH / 2;
+               }
+       }
+}
+
+int vox_height(int x, int y)
+{
+       return H(x, y);
+}
+
+int vox_check_vis(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
+{
+       /* TODO */
+       return 0;
+}
diff --git a/src/voxscape.h b/src/voxscape.h
new file mode 100644 (file)
index 0000000..c68700c
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef VOXSCAPE_H_
+#define VOXSCAPE_H_
+
+#include <stdint.h>
+
+enum {
+       VOX_NEAREST,
+       VOX_LINEAR
+};
+
+extern int *projlut;
+
+int vox_init(int xsz, int ysz, uint8_t far *himg, uint8_t far *cimg);
+void vox_destroy(void);
+
+void vox_framebuf(int xres, int yres, void *fb, int horizon);
+/* negative height for auto at -h above terrain */
+int vox_view(int32_t x, int32_t y, int h, int32_t angle);
+void vox_proj(int fov, int znear, int zfar);
+
+void vox_render(void);
+
+void vox_begin(void);
+void vox_render_slice(int n);
+
+void vox_sky_solid(uint8_t color);
+void vox_sky_grad(uint8_t chor, uint8_t ctop);
+
+int vox_height(int x, int y);
+int vox_check_vis(int32_t x0, int32_t y0, int32_t x1, int32_t y1);
+
+#endif /* VOXSCAPE_H_ */