From: John Tsiombikas Date: Wed, 22 Nov 2023 23:55:41 +0000 (+0200) Subject: initial commit X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=commitdiff_plain;h=025dd0178312f99c64b945a99031f62a753614ea;p=dos_low3d initial commit --- 025dd0178312f99c64b945a99031f62a753614ea diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85af462 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.o +*.swp +*.obj +*.OBJ +*.exe +*.EXE +*.map +*.MAP +*.lnk +*.LNK diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..15e0118 --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ + +!ifdef __UNIX__ +obj = src/main.obj src/video.obj src/3dgfx.obj src/3dgfx_s.obj src/polyfill.obj +!else +obj = src\main.obj src\video.obj src\3dgfx.obj src\3dgfx_s.obj src\polyfill.obj +!endif +bin = low3d.exe + +opt = -3 -otexan +dbg = -d3 + +incpath = -Isrc + +AS = nasm +CC = wcc386 +ASFLAGS = -fobj +CFLAGS = $(dbg) $(opt) $(def) -zq -bt=dos $(incpath) +LDFLAGS = option map +LD = wlink + +$(bin): $(obj) + %write objlist.lnk $(obj) + $(LD) debug all name $@ system dos4g file { @objlist } $(LDFLAGS) + +.c: src +.asm: src + +.c.obj: .autodepend + $(CC) -fo=$@ $(CFLAGS) $[* + +.asm.obj: + $(AS) $(ASFLAGS) -o $@ $[*.asm + +!ifdef __UNIX__ +clean: .symbolic + rm -f $(obj) $(bin) +!else +clean: .symbolic + del src\*.obj + del *.lnk + del *.map + del $(bin) +!endif diff --git a/src/3dgfx.c b/src/3dgfx.c new file mode 100644 index 0000000..8dee789 --- /dev/null +++ b/src/3dgfx.c @@ -0,0 +1,37 @@ +#include +#include +#include "3dgfx.h" + +static int32_t mvmat[16]; +static int32_t pmat[16]; + +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; + return 0; +} + +void g3d_shutdown(void) +{ +} + +void g3d_framebuf(int width, int height, void *fb) +{ +} + +void g3d_modelview(const int32_t *m) +{ + memcpy(mvmat, m, sizeof mvmat); +} + +void g3d_projection(const int32_t *m) +{ + memcpy(pmat, m, sizeof pmat); +} + +void g3d_draw(int prim, struct g3d_vertex *varr, int vcount) +{ +} diff --git a/src/3dgfx.h b/src/3dgfx.h new file mode 100644 index 0000000..f143f24 --- /dev/null +++ b/src/3dgfx.h @@ -0,0 +1,28 @@ +#ifndef GFX3D_H_ +#define GFX3D_H_ + +#include "types.h" + +struct g3d_vertex { + int32_t x, y, z; +}; + +enum { + G3D_POINTS, + G3D_LINES, + G3D_TRIANGLES +}; + +int g3d_init(void); +void g3d_shutdown(void); + +void g3d_framebuf(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_draw(int prim, struct g3d_vertex *varr, int vcount); + +#endif /* GFX3D_H_ */ diff --git a/src/3dgfx_s.asm b/src/3dgfx_s.asm new file mode 100644 index 0000000..8147e7a --- /dev/null +++ b/src/3dgfx_s.asm @@ -0,0 +1,54 @@ + bits 32 + section .text + + ; eax: vertex ptr, edx: matrix ptr + global g3d_xform_ +g3d_xform_: + push ebp + mov ebp, esp + sub esp, 8 + push ebx + push esi + push edi + + mov ebx, edx ; matrix to ebx + mov edi, eax ; vertex to edi + +%macro MULROW 0 + mov eax, [edi] ; eax <- X + imul dword [ebx] + mov ecx, eax + mov eax, [edi + 4] ; eax <- Y + imul dword [ebx + 4] + add ecx, eax + mov eax, [edi + 8] ; eax <- Z + imul dword [ebx + 8] + add ecx, eax + mov eax, [edi + 12] ; eax <- W + imul dword [ebx + 12] + add eax, ecx +%endmacro + + MULROW + mov [ebp - 12], eax + add ebx, 16 ; next matrix row + MULROW + mov [ebp - 8], eax + add ebx, 16 + MULROW + mov [ebp - 4], eax + add ebx, 16 + MULROW + mov [edi + 12], eax ; move W into place + ; move XYZ into place + mov esi, [ebp - 12] + movsd + movsd + movsd + + pop edi + pop esi + pop ebx + mov esp, ebp + pop ebp + ret diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..26bc2aa --- /dev/null +++ b/src/main.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include "video.h" +#include "3dgfx.h" + +void update(void); +void wait_vsync(void); +void handle_key(int key); +void interrupt timer_intr(); + +static int quit; +static unsigned char *fb; + +static volatile unsigned long nticks; + +static void interrupt (*prev_timer_intr)(); + +int main(void) +{ + long rate, nframes = 0; + long tstart, tdur; + + if(!(fb = malloc(64000))) { + fprintf(stderr, "failed to allocate framebuffer\n"); + return 1; + } + + init_video(); + + prev_timer_intr = _dos_getvect(0x1c); + _dos_setvect(0x1c, timer_intr); + _disable(); + tstart = nticks; + _enable(); + + for(;;) { + while(kbhit()) { + int c = getch(); + handle_key(c); + if(quit) goto end; + } + + update(); + nframes++; + } + +end: + _disable(); + tdur = nticks - tstart; + _enable(); + _dos_setvect(0x1c, prev_timer_intr); + + close_video(); + free(fb); + + rate = nframes * 100 * 18 / tdur; + printf("%ld frames in %ld sec, rate: %ld.%ld\n", nframes, tdur / 18, + rate / 100, rate % 100); + return 0; +} + +void update(void) +{ + memset(fb, 0, 64000); + + wait_vsync(); + memcpy((void*)0xa0000, fb, 64000); +} + +void handle_key(int key) +{ + switch(key) { + case 27: + quit = 1; + break; + } +} + +void interrupt timer_intr() +{ + nticks++; + _chain_intr(prev_timer_intr); +} diff --git a/src/polyfill.asm b/src/polyfill.asm new file mode 100644 index 0000000..1459ffd --- /dev/null +++ b/src/polyfill.asm @@ -0,0 +1,8 @@ + bits 32 + section .text + + global polyfill_ +polyfill_: + ret + +; vi:ft=nasm ts=8 sts=8 sw=8: diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..2a747c3 --- /dev/null +++ b/src/types.h @@ -0,0 +1,15 @@ +#ifndef TYPES_H_ +#define TYPES_H_ + +typedef signed char int8_t; +typedef short int16_t; +typedef long int32_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; + +typedef long intptr_t; +typedef unsigned long uintptr_t; + +#endif /* TYPES_H_ */ diff --git a/src/video.c b/src/video.c new file mode 100644 index 0000000..9adaf2f --- /dev/null +++ b/src/video.c @@ -0,0 +1,18 @@ +#include +#include "video.h" + +void init_video(void) +{ + union REGS regs = {0}; + + regs.w.ax = 0x13; + int386(0x10, ®s, ®s); +} + +void close_video(void) +{ + union REGS regs = {0}; + + regs.w.ax = 3; + int386(0x10, ®s, ®s); +} diff --git a/src/video.h b/src/video.h new file mode 100644 index 0000000..672eb6a --- /dev/null +++ b/src/video.h @@ -0,0 +1,20 @@ +#ifndef VIDEO_H_ +#define VIDEO_H_ + +void init_video(void); +void close_video(void); + +void wait_vsync(void); +#pragma aux wait_vsync = \ + "mov dx, 0x3da" \ + "invb:" \ + "in al, dx" \ + "and al, 8" \ + "jnz invb" \ + "waitvb:" \ + "in al, dx" \ + "and al, 8" \ + "jz waitvb" \ + modify [eax edx]; + +#endif /* VIDEO_H_ */