From 1d2634072dc71cb983af64e6094d69da664ce6e9 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sat, 25 Nov 2023 07:33:44 +0200 Subject: [PATCH] foo --- Makefile | 14 ++++++- src/3dgfx.c | 98 ++++++++++++++++++++++++++++++++++++++++++-- src/3dgfx.h | 21 ++++++++-- src/3dgfx_s.asm | 12 ++++-- src/lut.asm | 59 +++++++++++++++++++++++++++ src/main.c | 36 ++++++++++++++-- src/polyfill.asm | 8 ---- src/polyfill.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 25 ++++++++++++ src/video.h | 16 ++++++++ tools/Makefile | 9 ++++ tools/genlut.c | 37 +++++++++++++++++ tools/packsrc | 5 +++ tools/packsrc.bat | 3 ++ 14 files changed, 438 insertions(+), 23 deletions(-) create mode 100644 src/lut.asm delete mode 100644 src/polyfill.asm create mode 100644 src/polyfill.c create mode 100644 src/util.h create mode 100644 tools/Makefile create mode 100644 tools/genlut.c create mode 100755 tools/packsrc create mode 100644 tools/packsrc.bat diff --git a/Makefile b/Makefile index 15e0118..2f619d6 100644 --- 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) diff --git a/src/3dgfx.c b/src/3dgfx.c index 8dee789..535fa98 100644 --- a/src/3dgfx.c +++ b/src/3dgfx.c @@ -1,16 +1,25 @@ +#include #include #include #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> 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; + } } diff --git a/src/3dgfx.h b/src/3dgfx.h index f143f24..f4a1d28 100644 --- a/src/3dgfx.h +++ b/src/3dgfx.h @@ -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_ */ diff --git a/src/3dgfx_s.asm b/src/3dgfx_s.asm index 8147e7a..30b2374 100644 --- a/src/3dgfx_s.asm +++ b/src/3dgfx_s.asm @@ -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 index 0000000..0501467 --- /dev/null +++ b/src/lut.asm @@ -0,0 +1,59 @@ + bits 32 + section .rodata + + global _sintab +_sintab: + dw 0, 100, 201, 301, 401, 502, 602, 702, 802, 902, 1002, 1102, 1202 + dw 1301, 1400, 1499, 1598, 1696, 1794, 1892, 1990, 2087, 2184, 2281 + dw 2378, 2474, 2569, 2664, 2759, 2854, 2948, 3041, 3134, 3227, 3319 + dw 3411, 3502, 3593, 3683, 3772, 3861, 3950, 4037, 4124, 4211, 4297 + dw 4382, 4467, 4551, 4634, 4717, 4798, 4879, 4960, 5039, 5118, 5196 + dw 5274, 5350, 5426, 5501, 5575, 5648, 5721, 5792, 5863, 5933, 6001 + dw 6069, 6136, 6203, 6268, 6332, 6395, 6458, 6519, 6579, 6639, 6697 + dw 6755, 6811, 6866, 6921, 6974, 7026, 7077, 7127, 7176, 7224, 7271 + dw 7317, 7361, 7405, 7447, 7489, 7529, 7568, 7606, 7643, 7678, 7713 + dw 7746, 7778, 7809, 7839, 7867, 7895, 7921, 7946, 7970, 7992, 8014 + dw 8034, 8053, 8071, 8087, 8103, 8117, 8130, 8142, 8152, 8161, 8169 + dw 8176, 8182, 8186, 8189, 8191, 8192, 8191, 8189, 8186, 8182, 8176 + dw 8169, 8161, 8152, 8142, 8130, 8117, 8103, 8087, 8071, 8053, 8034 + dw 8014, 7992, 7970, 7946, 7921, 7895, 7867, 7839, 7809, 7778, 7746 + dw 7713, 7678, 7643, 7606, 7568, 7529, 7489, 7447, 7405, 7361, 7317 + dw 7271, 7224, 7176, 7127, 7077, 7026, 6974, 6921, 6866, 6811, 6755 + dw 6697, 6639, 6579, 6519, 6458, 6395, 6332, 6268, 6203, 6136, 6069 + dw 6001, 5933, 5863, 5792, 5721, 5648, 5575, 5501, 5426, 5350, 5274 + dw 5196, 5118, 5039, 4960, 4879, 4798, 4717, 4634, 4551, 4467, 4382 + dw 4297, 4211, 4124, 4037, 3950, 3861, 3772, 3683, 3593, 3502, 3411 + dw 3319, 3227, 3134, 3041, 2948, 2854, 2759, 2664, 2569, 2474, 2378 + dw 2281, 2184, 2087, 1990, 1892, 1794, 1696, 1598, 1499, 1400, 1301 + dw 1202, 1102, 1002, 902, 802, 702, 602, 502, 401, 301, 201, 100 + dw 0, -100, -201, -301, -401, -502, -602, -702, -802, -902, -1002 + dw -1102, -1202, -1301, -1400, -1499, -1598, -1696, -1794, -1892 + dw -1990, -2087, -2184, -2281, -2378, -2474, -2569, -2664, -2759 + dw -2854, -2948, -3041, -3134, -3227, -3319, -3411, -3502, -3593 + dw -3683, -3772, -3861, -3950, -4037, -4124, -4211, -4297, -4382 + dw -4467, -4551, -4634, -4717, -4798, -4879, -4960, -5039, -5118 + dw -5196, -5274, -5350, -5426, -5501, -5575, -5648, -5721, -5792 + dw -5863, -5933, -6001, -6069, -6136, -6203, -6268, -6332, -6395 + dw -6458, -6519, -6579, -6639, -6697, -6755, -6811, -6866, -6921 + dw -6974, -7026, -7077, -7127, -7176, -7224, -7271, -7317, -7361 + dw -7405, -7447, -7489, -7529, -7568, -7606, -7643, -7678, -7713 + dw -7746, -7778, -7809, -7839, -7867, -7895, -7921, -7946, -7970 + dw -7992, -8014, -8034, -8053, -8071, -8087, -8103, -8117, -8130 + dw -8142, -8152, -8161, -8169, -8176, -8182, -8186, -8189, -8191 + dw -8192, -8191, -8189, -8186, -8182, -8176, -8169, -8161, -8152 + dw -8142, -8130, -8117, -8103, -8087, -8071, -8053, -8034, -8014 + dw -7992, -7970, -7946, -7921, -7895, -7867, -7839, -7809, -7778 + dw -7746, -7713, -7678, -7643, -7606, -7568, -7529, -7489, -7447 + dw -7405, -7361, -7317, -7271, -7224, -7176, -7127, -7077, -7026 + dw -6974, -6921, -6866, -6811, -6755, -6697, -6639, -6579, -6519 + dw -6458, -6395, -6332, -6268, -6203, -6136, -6069, -6001, -5933 + dw -5863, -5792, -5721, -5648, -5575, -5501, -5426, -5350, -5274 + dw -5196, -5118, -5039, -4960, -4879, -4798, -4717, -4634, -4551 + dw -4467, -4382, -4297, -4211, -4124, -4037, -3950, -3861, -3772 + dw -3683, -3593, -3502, -3411, -3319, -3227, -3134, -3041, -2948 + dw -2854, -2759, -2664, -2569, -2474, -2378, -2281, -2184, -2087 + dw -1990, -1892, -1794, -1696, -1598, -1499, -1400, -1301, -1202 + dw -1102, -1002, -902, -802, -702, -602, -502, -401, -301, -201, -100 + + +; vi:ft=nasm ts=8 sts=8 sw=8: diff --git a/src/main.c b/src/main.c index 26bc2aa..549ae6d 100644 --- a/src/main.c +++ b/src/main.c @@ -5,9 +5,9 @@ #include #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 index 1459ffd..0000000 --- a/src/polyfill.asm +++ /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 index 0000000..c5298d4 --- /dev/null +++ b/src/polyfill.c @@ -0,0 +1,118 @@ +#include +#include +#include "3dgfx.h" +#include "util.h" + +static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2); +static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2); + +void g3d_polyfill(struct g3d_vertex *verts) +{ + int i, topidx, botidx, mididx; + int32_t dx, dy, dym; + struct g3d_vertex vtmp; + + topidx = botidx = 0; + for(i=1; i<3; i++) { + if(verts[i].y < verts[topidx].y) { + topidx = i; + } + if(verts[i].y > verts[botidx].y) { + botidx = i; + } + } + mididx = (topidx + 1) % 3; + if(mididx == botidx) mididx = (mididx + 1) % 3; + + dy = verts[botidx].y - verts[topidx].y; + if(dy == 0) return; + + dx = verts[botidx].x - verts[topidx].x; + dym = verts[mididx].y - verts[topidx].y; + vtmp.x = muldiv(dx, dym, dy) + verts[topidx].x; /* dx * dym / dy + vtop.x */ + vtmp.y = verts[mididx].y; + + if(verts[topidx].y != verts[mididx].y) { + filltop(verts + topidx, verts + mididx, &vtmp); + } + if(verts[mididx].y != verts[botidx].y) { + fillbot(verts + mididx, &vtmp, verts + botidx); + } +} + +static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2) +{ + struct g3d_vertex *vtmp; + int x, xn, y, endy, len; + int32_t xl, xr, dxl, dxr, dxldy, dxrdy, dy; + unsigned char *fbptr; + + if(v1->x > v2->x) { + vtmp = v1; + v1 = v2; + v2 = vtmp; + } + + y = v0->y >> 8; + endy = v1->y >> 8; + x = v0->x >> 8; + + fbptr = g3d_fbpixels + y * XRES + x; + + xl = xr = v0->x; + dy = v1->y - v0->y; + dxl = v1->x - v0->x; + dxr = v2->x - v0->x; + dxldy = (dxl << 8) / dy; + dxrdy = (dxr << 8) / dy; + + while(y++ < endy) { + len = (xr - xl) >> 8; + if(len > 0) memset(fbptr, g3d_curcidx, len); + + xl += dxldy; + xr += dxrdy; + xn = xl >> 8; + fbptr += XRES + (xn - x); + x = xn; + } +} + +static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2) +{ + struct g3d_vertex *vtmp; + int x, xn, y, endy, len; + int32_t xl, xr, dxl, dxr, dxldy, dxrdy, dy; + unsigned char *fbptr; + + if(v0->x > v1->x) { + vtmp = v0; + v0 = v1; + v1 = vtmp; + } + + y = v0->y >> 8; + endy = v2->y >> 8; + x = v0->x >> 8; + + fbptr = g3d_fbpixels + y * XRES + x; + + xl = v0->x; + xr = v1->x; + dy = v2->y - v0->y; + dxl = v2->x - v0->x; + dxr = v2->x - v1->x; + dxldy = (dxl << 8) / dy; + dxrdy = (dxr << 8) / dy; + + while(y++ < endy) { + len = (xr - xl) >> 8; + if(len > 0) memset(fbptr, g3d_curcidx, len); + + xl += dxldy; + xr += dxrdy; + xn = xl >> 8; + fbptr += XRES + (xn - x); + x = xn; + } +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..9488b9b --- /dev/null +++ b/src/util.h @@ -0,0 +1,25 @@ +#ifndef UTIL_H_ +#define UTIL_H_ + +#include "types.h" + +#define SINLUT_SIZE 512 +#define SINLUT_MASK (SINLUT_SIZE - 1) +#define SINLUT_SCALE 8192 + +extern int16_t sintab[]; + +/* sin(x) lookup -> 16.16 fixed point */ +#define XSIN(x) (sintab[(x) & SINLUT_MASK] << 3) +#define XCOS(x) (sintab[((x) + SINLUT_SIZE / 4) & SINLUT_MASK] << 3) + +/* perform x * s / d without loss of precision */ +int32_t muldiv(int32_t x, int32_t s, int32_t d); +#pragma aux muldiv = \ + "imul ebx" \ + "idiv ecx" \ + parm [eax] [ebx] [ecx] \ + value [eax] \ + modify [eax edx]; + +#endif /* UTIL_H_ */ diff --git a/src/video.h b/src/video.h index 672eb6a..aa71d99 100644 --- a/src/video.h +++ b/src/video.h @@ -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 index 0000000..c0d9651 --- /dev/null +++ b/tools/Makefile @@ -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 index 0000000..cbd629c --- /dev/null +++ b/tools/genlut.c @@ -0,0 +1,37 @@ +#include +#include + +#define SINTAB_SIZE 512 +#define SINTAB_SCALE 8192 + +int main(void) +{ + int i, len; + + printf("\tbits 32\n"); + printf("\tsection .rodata\n\n"); + + printf("\tglobal _sintab\n"); + printf("_sintab:\n"); + + fputs("\tdw", stdout); + len = 10; + for(i=0; i= 72) { + putchar('\n'); + if(i < SINTAB_SIZE - 1) { + fputs("\tdw", stdout); + len = 10; + } + } else { + putchar(','); + len++; + } + } + printf("\n\n; vi:ft=nasm ts=8 sts=8 sw=8:\n"); + return 0; +} diff --git a/tools/packsrc b/tools/packsrc new file mode 100755 index 0000000..9931a29 --- /dev/null +++ b/tools/packsrc @@ -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 index 0000000..cd9e1e2 --- /dev/null +++ b/tools/packsrc.bat @@ -0,0 +1,3 @@ +del low3d.zip +zip low3d.zip Makefile src\*.c src\*.h src\*.asm packsrc *.bat +zip low3d.zip tools\*.c tools\Makefile -- 1.7.10.4