foo
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 25 Nov 2023 05:33:44 +0000 (07:33 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 25 Nov 2023 05:33:44 +0000 (07:33 +0200)
14 files changed:
Makefile
src/3dgfx.c
src/3dgfx.h
src/3dgfx_s.asm
src/lut.asm [new file with mode: 0644]
src/main.c
src/polyfill.asm [deleted file]
src/polyfill.c [new file with mode: 0644]
src/util.h [new file with mode: 0644]
src/video.h
tools/Makefile [new file with mode: 0644]
tools/genlut.c [new file with mode: 0644]
tools/packsrc [new file with mode: 0755]
tools/packsrc.bat [new file with mode: 0644]

index 15e0118..2f619d6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,10 @@
 
 !ifdef __UNIX__
-obj = src/main.obj src/video.obj src/3dgfx.obj src/3dgfx_s.obj src/polyfill.obj
+obj = src/main.obj src/video.obj src/3dgfx.obj src/3dgfx_s.obj &
+       src/polyfill.obj src/lut.obj
 !else
-obj = src\main.obj src\video.obj src\3dgfx.obj src\3dgfx_s.obj src\polyfill.obj
+obj = src\main.obj src\video.obj src\3dgfx.obj src\3dgfx_s.obj &
+       src\polyfill.obj src\lut.obj
 !endif
 bin = low3d.exe
 
@@ -31,6 +33,14 @@ $(bin): $(obj)
 .asm.obj:
        $(AS) $(ASFLAGS) -o $@ $[*.asm
 
+src\lut.asm: tools\genlut.exe
+       tools\genlut.exe >$@
+
+tools\genlut.exe: tools\genlut.c
+       cd tools
+       wmake
+       cd ..
+
 !ifdef __UNIX__
 clean: .symbolic
        rm -f $(obj) $(bin)
index 8dee789..535fa98 100644 (file)
@@ -1,16 +1,25 @@
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "3dgfx.h"
+#include "util.h"
 
 static int32_t mvmat[16];
 static int32_t pmat[16];
+static int vp[4];
+
+unsigned char *g3d_fbpixels;
+int g3d_width, g3d_height;
+int g3d_curcidx;
+
 
 int g3d_init(void)
 {
        memset(mvmat, 0, sizeof mvmat);
        memset(pmat, 0, sizeof pmat);
-       mvmat[0] = mvmat[5] = mvmat[10] = mvmat[15] = 0;
-       pmat[0] = pmat[5] = pmat[10] = pmat[15] = 0;
+       mvmat[0] = mvmat[5] = mvmat[10] = mvmat[15] = 0x10000;
+       pmat[0] = pmat[5] = pmat[10] = pmat[15] = 0x10000;
+       g3d_curcidx = 0xff;
        return 0;
 }
 
@@ -18,8 +27,15 @@ void g3d_shutdown(void)
 {
 }
 
-void g3d_framebuf(int width, int height, void *fb)
+void g3d_framebuffer(int width, int height, void *fb)
 {
+       g3d_fbpixels = fb;
+       g3d_width = width;
+       g3d_height = height;
+
+       vp[0] = vp[1] = 0;
+       vp[2] = width;
+       vp[3] = height;
 }
 
 void g3d_modelview(const int32_t *m)
@@ -32,6 +48,82 @@ void g3d_projection(const int32_t *m)
        memcpy(pmat, m, sizeof pmat);
 }
 
+void g3d_color(int cidx)
+{
+       g3d_curcidx = cidx;
+}
+
+static const int primverts[] = {1, 2, 3, 4};
+
 void g3d_draw(int prim, struct g3d_vertex *varr, int vcount)
 {
+       int i, prim_vnum;
+
+       prim_vnum = primverts[prim];
+
+       for(i=0; i<vcount; i+=prim_vnum) {
+               g3d_draw_prim(prim, varr);
+               varr += prim_vnum;
+       }
+}
+
+int32_t vpscale(int32_t x, int32_t s, int32_t shift);
+#pragma aux vpscale = \
+       "add eax, 0x100" \
+       "mul ebx" \
+       "shrd eax, edx, cl" \
+       parm [eax] [ebx] [ecx] \
+       value [eax];
+
+void g3d_draw_prim(int prim, struct g3d_vertex *varr)
+{
+       int i, vcount, x, y, x1, y1;
+       struct g3d_vertex v[4];
+
+       vcount = primverts[prim];
+
+       for(i=0; i<vcount; i++) {
+               v[i] = varr[i];
+
+               /* transform to view space */
+               g3d_xform(v + i, mvmat);
+
+               /* transform to homogeneous clip space */
+               g3d_xform(v + i, pmat);
+
+               /* TODO clip */
+
+               /* perspective division */
+               if(v[i].w != 0) {
+                       v[i].x = (v[i].x << 4) / (v[i].w >> 4);
+                       v[i].y = (v[i].y << 4) / (v[i].w >> 4);
+               }
+
+               /* viewport transform */
+               v[i].x = vpscale(v[i].x, vp[2], 1) + (vp[0] << 8);
+               v[i].y = vpscale(-v[i].y, vp[3], 1) + (vp[1] << 8);
+       }
+
+       switch(prim) {
+       case G3D_POINTS:
+               x = v[0].x >> 8;
+               y = v[0].y >> 8;
+               if(x >= 0 && y >= 0 && x < XRES && y < YRES) {
+                       g3d_fbpixels[y * XRES + x] = g3d_curcidx;
+               }
+               break;
+
+       case G3D_LINES:
+               break;  /* TODO */
+
+       case G3D_TRIANGLES:
+               g3d_polyfill(v);
+               break;
+
+       case G3D_QUADS:
+               g3d_polyfill(v);
+               v[1] = v[0];
+               g3d_polyfill(v + 1);
+               break;
+       }
 }
index f143f24..f4a1d28 100644 (file)
@@ -3,26 +3,41 @@
 
 #include "types.h"
 
+#define XRES   320
+#define YRES   200
+
 struct g3d_vertex {
-       int32_t x, y, z;
+       int32_t x, y, z, w;
 };
 
 enum {
        G3D_POINTS,
        G3D_LINES,
-       G3D_TRIANGLES
+       G3D_TRIANGLES,
+       G3D_QUADS
 };
 
+extern unsigned char *g3d_fbpixels;
+extern int g3d_width, g3d_height;
+extern int g3d_curcidx;
+
+
 int g3d_init(void);
 void g3d_shutdown(void);
 
-void g3d_framebuf(int width, int height, void *fb);
+void g3d_framebuffer(int width, int height, void *fb);
 
 void g3d_modelview(const int32_t *m);
 void g3d_projection(const int32_t *m);
 
 void g3d_xform(struct g3d_vertex *v, const int32_t *m);
 
+void g3d_color(int cidx);
+
 void g3d_draw(int prim, struct g3d_vertex *varr, int vcount);
+void g3d_draw_prim(int prim, struct g3d_vertex *varr);
+
+/* defined in polyfill.asm */
+void g3d_polyfill(struct g3d_vertex *verts);
 
 #endif /* GFX3D_H_ */
index 8147e7a..30b2374 100644 (file)
@@ -1,12 +1,12 @@
        bits 32
-       section .text
+       section .text USE32
 
        ; eax: vertex ptr, edx: matrix ptr
        global g3d_xform_
 g3d_xform_:
        push ebp
        mov ebp, esp
-       sub esp, 8
+       sub esp, 12
        push ebx
        push esi
        push edi
@@ -17,15 +17,19 @@ g3d_xform_:
 %macro MULROW 0
        mov eax, [edi]          ; eax <- X
        imul dword [ebx]
+       shrd eax, edx, 16
        mov ecx, eax
        mov eax, [edi + 4]      ; eax <- Y
        imul dword [ebx + 4]
+       shrd eax, edx, 16
        add ecx, eax
        mov eax, [edi + 8]      ; eax <- Z
        imul dword [ebx + 8]
+       shrd eax, edx, 16
        add ecx, eax
        mov eax, [edi + 12]     ; eax <- W
        imul dword [ebx + 12]
+       shrd eax, edx, 16
        add eax, ecx
 %endmacro
 
@@ -41,7 +45,7 @@ g3d_xform_:
        MULROW
        mov [edi + 12], eax     ; move W into place
        ; move XYZ into place
-       mov esi, [ebp - 12]
+       lea esi, [ebp - 12]
        movsd
        movsd
        movsd
@@ -52,3 +56,5 @@ g3d_xform_:
        mov esp, ebp
        pop ebp
        ret
+
+; vi:ft=nasm ts=8 sts=8 sw=8:
diff --git a/src/lut.asm b/src/lut.asm
new file mode 100644 (file)
index 0000000..0501467
--- /dev/null
@@ -0,0 +1,59 @@
+       bits 32\r
+       section .rodata\r
+\r
+       global _sintab\r
+_sintab:\r
+       dw 0, 100, 201, 301, 401, 502, 602, 702, 802, 902, 1002, 1102, 1202\r
+       dw 1301, 1400, 1499, 1598, 1696, 1794, 1892, 1990, 2087, 2184, 2281\r
+       dw 2378, 2474, 2569, 2664, 2759, 2854, 2948, 3041, 3134, 3227, 3319\r
+       dw 3411, 3502, 3593, 3683, 3772, 3861, 3950, 4037, 4124, 4211, 4297\r
+       dw 4382, 4467, 4551, 4634, 4717, 4798, 4879, 4960, 5039, 5118, 5196\r
+       dw 5274, 5350, 5426, 5501, 5575, 5648, 5721, 5792, 5863, 5933, 6001\r
+       dw 6069, 6136, 6203, 6268, 6332, 6395, 6458, 6519, 6579, 6639, 6697\r
+       dw 6755, 6811, 6866, 6921, 6974, 7026, 7077, 7127, 7176, 7224, 7271\r
+       dw 7317, 7361, 7405, 7447, 7489, 7529, 7568, 7606, 7643, 7678, 7713\r
+       dw 7746, 7778, 7809, 7839, 7867, 7895, 7921, 7946, 7970, 7992, 8014\r
+       dw 8034, 8053, 8071, 8087, 8103, 8117, 8130, 8142, 8152, 8161, 8169\r
+       dw 8176, 8182, 8186, 8189, 8191, 8192, 8191, 8189, 8186, 8182, 8176\r
+       dw 8169, 8161, 8152, 8142, 8130, 8117, 8103, 8087, 8071, 8053, 8034\r
+       dw 8014, 7992, 7970, 7946, 7921, 7895, 7867, 7839, 7809, 7778, 7746\r
+       dw 7713, 7678, 7643, 7606, 7568, 7529, 7489, 7447, 7405, 7361, 7317\r
+       dw 7271, 7224, 7176, 7127, 7077, 7026, 6974, 6921, 6866, 6811, 6755\r
+       dw 6697, 6639, 6579, 6519, 6458, 6395, 6332, 6268, 6203, 6136, 6069\r
+       dw 6001, 5933, 5863, 5792, 5721, 5648, 5575, 5501, 5426, 5350, 5274\r
+       dw 5196, 5118, 5039, 4960, 4879, 4798, 4717, 4634, 4551, 4467, 4382\r
+       dw 4297, 4211, 4124, 4037, 3950, 3861, 3772, 3683, 3593, 3502, 3411\r
+       dw 3319, 3227, 3134, 3041, 2948, 2854, 2759, 2664, 2569, 2474, 2378\r
+       dw 2281, 2184, 2087, 1990, 1892, 1794, 1696, 1598, 1499, 1400, 1301\r
+       dw 1202, 1102, 1002, 902, 802, 702, 602, 502, 401, 301, 201, 100\r
+       dw 0, -100, -201, -301, -401, -502, -602, -702, -802, -902, -1002\r
+       dw -1102, -1202, -1301, -1400, -1499, -1598, -1696, -1794, -1892\r
+       dw -1990, -2087, -2184, -2281, -2378, -2474, -2569, -2664, -2759\r
+       dw -2854, -2948, -3041, -3134, -3227, -3319, -3411, -3502, -3593\r
+       dw -3683, -3772, -3861, -3950, -4037, -4124, -4211, -4297, -4382\r
+       dw -4467, -4551, -4634, -4717, -4798, -4879, -4960, -5039, -5118\r
+       dw -5196, -5274, -5350, -5426, -5501, -5575, -5648, -5721, -5792\r
+       dw -5863, -5933, -6001, -6069, -6136, -6203, -6268, -6332, -6395\r
+       dw -6458, -6519, -6579, -6639, -6697, -6755, -6811, -6866, -6921\r
+       dw -6974, -7026, -7077, -7127, -7176, -7224, -7271, -7317, -7361\r
+       dw -7405, -7447, -7489, -7529, -7568, -7606, -7643, -7678, -7713\r
+       dw -7746, -7778, -7809, -7839, -7867, -7895, -7921, -7946, -7970\r
+       dw -7992, -8014, -8034, -8053, -8071, -8087, -8103, -8117, -8130\r
+       dw -8142, -8152, -8161, -8169, -8176, -8182, -8186, -8189, -8191\r
+       dw -8192, -8191, -8189, -8186, -8182, -8176, -8169, -8161, -8152\r
+       dw -8142, -8130, -8117, -8103, -8087, -8071, -8053, -8034, -8014\r
+       dw -7992, -7970, -7946, -7921, -7895, -7867, -7839, -7809, -7778\r
+       dw -7746, -7713, -7678, -7643, -7606, -7568, -7529, -7489, -7447\r
+       dw -7405, -7361, -7317, -7271, -7224, -7176, -7127, -7077, -7026\r
+       dw -6974, -6921, -6866, -6811, -6755, -6697, -6639, -6579, -6519\r
+       dw -6458, -6395, -6332, -6268, -6203, -6136, -6069, -6001, -5933\r
+       dw -5863, -5792, -5721, -5648, -5575, -5501, -5426, -5350, -5274\r
+       dw -5196, -5118, -5039, -4960, -4879, -4798, -4717, -4634, -4551\r
+       dw -4467, -4382, -4297, -4211, -4124, -4037, -3950, -3861, -3772\r
+       dw -3683, -3593, -3502, -3411, -3319, -3227, -3134, -3041, -2948\r
+       dw -2854, -2759, -2664, -2569, -2474, -2378, -2281, -2184, -2087\r
+       dw -1990, -1892, -1794, -1696, -1598, -1499, -1400, -1301, -1202\r
+       dw -1102, -1002, -902, -802, -702, -602, -502, -401, -301, -201, -100\r
+\r
+\r
+; vi:ft=nasm ts=8 sts=8 sw=8:\r
index 26bc2aa..549ae6d 100644 (file)
@@ -5,9 +5,9 @@
 #include <dos.h>
 #include "video.h"
 #include "3dgfx.h"
+#include "util.h"
 
 void update(void);
-void wait_vsync(void);
 void handle_key(int key);
 void interrupt timer_intr();
 
@@ -30,6 +30,9 @@ int main(void)
 
        init_video();
 
+       g3d_init();
+       g3d_framebuffer(320, 200, fb);
+
        prev_timer_intr = _dos_getvect(0x1c);
        _dos_setvect(0x1c, timer_intr);
        _disable();
@@ -62,12 +65,37 @@ end:
        return 0;
 }
 
+struct g3d_vertex varr[] = {
+       {0, 0x8000, 0, 0x10000},
+       {-0x8f00, -0x8000, 0, 0x10000},
+       {0x8c00, -0x6000, 0, 0x10000}
+};
+
+void mat_rotz(int32_t *m, int theta)
+{
+       m[0] = XCOS(theta);
+       m[1] = XSIN(theta);
+       m[4] = -XSIN(theta);
+       m[5] = XCOS(theta);
+       m[10] = 0x10000;
+       m[15] = 0x10000;
+       m[2] = m[3] = m[6] = m[7] = m[8] = m[9] = m[11] = m[12] = m[13] = m[14] = 0;
+}
+
 void update(void)
 {
-       memset(fb, 0, 64000);
+       int32_t xform[16];
+
+       vid_clearfb(fb);
+
+       mat_rotz(xform, nticks);
+       g3d_modelview(xform);
+
+       g3d_color(15);
+       g3d_draw(G3D_TRIANGLES, varr, sizeof varr / sizeof *varr);
 
-       wait_vsync();
-       memcpy((void*)0xa0000, fb, 64000);
+       /*wait_vsync();*/
+       vid_copyfb(fb);
 }
 
 void handle_key(int key)
diff --git a/src/polyfill.asm b/src/polyfill.asm
deleted file mode 100644 (file)
index 1459ffd..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-       bits 32
-       section .text
-
-       global polyfill_
-polyfill_:
-       ret
-
-; vi:ft=nasm ts=8 sts=8 sw=8:
diff --git a/src/polyfill.c b/src/polyfill.c
new file mode 100644 (file)
index 0000000..c5298d4
--- /dev/null
@@ -0,0 +1,118 @@
+#include <stdio.h>\r
+#include <string.h>\r
+#include "3dgfx.h"\r
+#include "util.h"\r
+\r
+static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2);\r
+static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2);\r
+\r
+void g3d_polyfill(struct g3d_vertex *verts)\r
+{\r
+       int i, topidx, botidx, mididx;\r
+       int32_t dx, dy, dym;\r
+       struct g3d_vertex vtmp;\r
+\r
+       topidx = botidx = 0;\r
+       for(i=1; i<3; i++) {\r
+               if(verts[i].y < verts[topidx].y) {\r
+                       topidx = i;\r
+               }\r
+               if(verts[i].y > verts[botidx].y) {\r
+                       botidx = i;\r
+               }\r
+       }\r
+       mididx = (topidx + 1) % 3;\r
+       if(mididx == botidx) mididx = (mididx + 1) % 3;\r
+\r
+       dy = verts[botidx].y - verts[topidx].y;\r
+       if(dy == 0) return;\r
+\r
+       dx = verts[botidx].x - verts[topidx].x;\r
+       dym = verts[mididx].y - verts[topidx].y;\r
+       vtmp.x = muldiv(dx, dym, dy) + verts[topidx].x; /* dx * dym / dy + vtop.x */\r
+       vtmp.y = verts[mididx].y;\r
+\r
+       if(verts[topidx].y != verts[mididx].y) {\r
+               filltop(verts + topidx, verts + mididx, &vtmp);\r
+       }\r
+       if(verts[mididx].y != verts[botidx].y) {\r
+               fillbot(verts + mididx, &vtmp, verts + botidx);\r
+       }\r
+}\r
+\r
+static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2)\r
+{\r
+       struct g3d_vertex *vtmp;\r
+       int x, xn, y, endy, len;\r
+       int32_t xl, xr, dxl, dxr, dxldy, dxrdy, dy;\r
+       unsigned char *fbptr;\r
+\r
+       if(v1->x > v2->x) {\r
+               vtmp = v1;\r
+               v1 = v2;\r
+               v2 = vtmp;\r
+       }\r
+\r
+       y = v0->y >> 8;\r
+       endy = v1->y >> 8;\r
+       x = v0->x >> 8;\r
+\r
+       fbptr = g3d_fbpixels + y * XRES + x;\r
+\r
+       xl = xr = v0->x;\r
+       dy = v1->y - v0->y;\r
+       dxl = v1->x - v0->x;\r
+       dxr = v2->x - v0->x;\r
+       dxldy = (dxl << 8) / dy;\r
+       dxrdy = (dxr << 8) / dy;\r
+\r
+       while(y++ < endy) {\r
+               len = (xr - xl) >> 8;\r
+               if(len > 0) memset(fbptr, g3d_curcidx, len);\r
+\r
+               xl += dxldy;\r
+               xr += dxrdy;\r
+               xn = xl >> 8;\r
+               fbptr += XRES + (xn - x);\r
+               x = xn;\r
+       }\r
+}\r
+\r
+static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2)\r
+{\r
+       struct g3d_vertex *vtmp;\r
+       int x, xn, y, endy, len;\r
+       int32_t xl, xr, dxl, dxr, dxldy, dxrdy, dy;\r
+       unsigned char *fbptr;\r
+\r
+       if(v0->x > v1->x) {\r
+               vtmp = v0;\r
+               v0 = v1;\r
+               v1 = vtmp;\r
+       }\r
+\r
+       y = v0->y >> 8;\r
+       endy = v2->y >> 8;\r
+       x = v0->x >> 8;\r
+\r
+       fbptr = g3d_fbpixels + y * XRES + x;\r
+\r
+       xl = v0->x;\r
+       xr = v1->x;\r
+       dy = v2->y - v0->y;\r
+       dxl = v2->x - v0->x;\r
+       dxr = v2->x - v1->x;\r
+       dxldy = (dxl << 8) / dy;\r
+       dxrdy = (dxr << 8) / dy;\r
+\r
+       while(y++ < endy) {\r
+               len = (xr - xl) >> 8;\r
+               if(len > 0) memset(fbptr, g3d_curcidx, len);\r
+\r
+               xl += dxldy;\r
+               xr += dxrdy;\r
+               xn = xl >> 8;\r
+               fbptr += XRES + (xn - x);\r
+               x = xn;\r
+       }\r
+}\r
diff --git a/src/util.h b/src/util.h
new file mode 100644 (file)
index 0000000..9488b9b
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef UTIL_H_\r
+#define UTIL_H_\r
+\r
+#include "types.h"\r
+\r
+#define SINLUT_SIZE            512\r
+#define SINLUT_MASK            (SINLUT_SIZE - 1)\r
+#define SINLUT_SCALE   8192\r
+\r
+extern int16_t sintab[];\r
+\r
+/* sin(x) lookup -> 16.16 fixed point */\r
+#define XSIN(x)        (sintab[(x) & SINLUT_MASK] << 3)\r
+#define XCOS(x)        (sintab[((x) + SINLUT_SIZE / 4) & SINLUT_MASK] << 3)\r
+\r
+/* perform x * s / d without loss of precision */\r
+int32_t muldiv(int32_t x, int32_t s, int32_t d);\r
+#pragma aux muldiv = \\r
+       "imul ebx" \\r
+       "idiv ecx" \\r
+       parm [eax] [ebx] [ecx] \\r
+       value [eax] \\r
+       modify [eax edx];\r
+\r
+#endif /* UTIL_H_ */\r
index 672eb6a..aa71d99 100644 (file)
@@ -17,4 +17,20 @@ void wait_vsync(void);
        "jz waitvb" \
        modify [eax edx];
 
+void vid_clearfb(void *fb);
+#pragma aux vid_clearfb = \
+       "mov ecx, 16000" \
+       "xor eax, eax" \
+       "rep stosd" \
+       parm [edi] \
+       modify [eax ecx];
+
+void vid_copyfb(void *fb);
+#pragma aux vid_copyfb = \
+       "mov ecx, 16000" \
+       "mov edi, 0xa0000" \
+       "rep movsd" \
+       parm [esi] \
+       modify [ecx edi];
+
 #endif /* VIDEO_H_ */
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644 (file)
index 0000000..c0d9651
--- /dev/null
@@ -0,0 +1,9 @@
+genlut.exe: genlut.obj
+       wlink name $@ system dos file $<
+
+genlut.obj: genlut.c
+       wcc -fo=$@ -zq $<
+       
+clean: .symbolic
+       del genlut.obj
+       del genlut.exe
diff --git a/tools/genlut.c b/tools/genlut.c
new file mode 100644 (file)
index 0000000..cbd629c
--- /dev/null
@@ -0,0 +1,37 @@
+#include <stdio.h>\r
+#include <math.h>\r
+\r
+#define SINTAB_SIZE            512\r
+#define SINTAB_SCALE   8192\r
+\r
+int main(void)\r
+{\r
+       int i, len;\r
+\r
+       printf("\tbits 32\n");\r
+       printf("\tsection .rodata\n\n");\r
+\r
+       printf("\tglobal _sintab\n");\r
+       printf("_sintab:\n");\r
+\r
+       fputs("\tdw", stdout);\r
+       len = 10;\r
+       for(i=0; i<SINTAB_SIZE; i++) {\r
+               double theta = (double)i / (double)SINTAB_SIZE * 6.28318530718;\r
+               double sf = sin(theta);\r
+               int sx = (int)(sf * SINTAB_SCALE);\r
+               len += printf(" %d", sx);\r
+               if(len >= 72) {\r
+                       putchar('\n');\r
+                       if(i < SINTAB_SIZE - 1) {\r
+                               fputs("\tdw", stdout);\r
+                               len = 10;\r
+                       }\r
+               } else {\r
+                       putchar(',');\r
+                       len++;\r
+               }\r
+       }\r
+       printf("\n\n; vi:ft=nasm ts=8 sts=8 sw=8:\n");\r
+       return 0;\r
+}\r
diff --git a/tools/packsrc b/tools/packsrc
new file mode 100755 (executable)
index 0000000..9931a29
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+rm -f low3d.zip
+zip -r low3d.zip Makefile src/*.c src/*.h src/*.asm packsrc *.bat \
+       tools/*.c tools/Makefile
diff --git a/tools/packsrc.bat b/tools/packsrc.bat
new file mode 100644 (file)
index 0000000..cd9e1e2
--- /dev/null
@@ -0,0 +1,3 @@
+del low3d.zip\r
+zip low3d.zip Makefile src\*.c src\*.h src\*.asm packsrc *.bat\r
+zip low3d.zip tools\*.c tools\Makefile\r