f53ead69e4cf7c2f98930a6eef3ed39a5840f878
[dos_low3d] / src / 3dgfx.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "3dgfx.h"
5 #include "util.h"
6
7 static int32_t mvmat[16];
8 static int32_t pmat[16];
9 static int vp[4];
10
11 unsigned char *g3d_fbpixels;
12 int g3d_width, g3d_height;
13 int g3d_curcidx;
14
15
16 int g3d_init(void)
17 {
18         memset(mvmat, 0, sizeof mvmat);
19         memset(pmat, 0, sizeof pmat);
20         mvmat[0] = mvmat[5] = mvmat[10] = mvmat[15] = 0x10000;
21         pmat[0] = pmat[5] = pmat[10] = pmat[15] = 0x10000;
22         g3d_curcidx = 0xff;
23         return 0;
24 }
25
26 void g3d_shutdown(void)
27 {
28 }
29
30 void g3d_framebuffer(int width, int height, void *fb)
31 {
32         g3d_fbpixels = fb;
33         g3d_width = width;
34         g3d_height = height;
35
36         vp[0] = vp[1] = 0;
37         vp[2] = width;
38         vp[3] = height;
39 }
40
41 void g3d_modelview(const int32_t *m)
42 {
43         memcpy(mvmat, m, sizeof mvmat);
44 }
45
46 void g3d_projection(const int32_t *m)
47 {
48         memcpy(pmat, m, sizeof pmat);
49 }
50
51 void g3d_color(int cidx)
52 {
53         g3d_curcidx = cidx;
54 }
55
56 static const int primverts[] = {1, 2, 3, 4};
57
58 void g3d_draw(int prim, struct g3d_vertex *varr, int vcount)
59 {
60         int i, prim_vnum;
61
62         prim_vnum = primverts[prim];
63
64         for(i=0; i<vcount; i+=prim_vnum) {
65                 g3d_draw_prim(prim, varr);
66                 varr += prim_vnum;
67         }
68 }
69
70 int32_t vpscale(int32_t x, int32_t s, int32_t shift);
71 #pragma aux vpscale = \
72         "add eax, 0x100" \
73         "imul ebx" \
74         "shrd eax, edx, cl" \
75         parm [eax] [ebx] [ecx] \
76         value [eax] \
77         modify [eax edx];
78
79
80 void g3d_draw_prim(int prim, struct g3d_vertex *varr)
81 {
82         int i, vcount, x, y, x1, y1;
83         struct g3d_vertex v[4];
84
85         vcount = primverts[prim];
86
87         for(i=0; i<vcount; i++) {
88                 v[i] = varr[i];
89
90                 /* transform to view space */
91                 g3d_xform(v + i, mvmat);
92
93                 /* transform to homogeneous clip space */
94                 g3d_xform(v + i, pmat);
95
96                 /* TODO clip */
97
98                 /* perspective division */
99                 if(v[i].w != 0) {
100                         v[i].x = (v[i].x << 4) / (v[i].w >> 4);
101                         v[i].y = (v[i].y << 4) / (v[i].w >> 4);
102                 } else {
103                         v[i].x >>= 8;
104                         v[i].y >>= 8;
105                 }
106
107                 /* viewport transform */
108                 v[i].x = vpscale(v[i].x, vp[2], 1) + (vp[0] << 8);
109                 v[i].y = vpscale(-v[i].y, vp[3], 1) + (vp[1] << 8);
110         }
111
112         switch(prim) {
113         case G3D_POINTS:
114                 x = v[0].x >> 8;
115                 y = v[0].y >> 8;
116                 if(x >= 0 && y >= 0 && x < XRES && y < YRES) {
117                         g3d_fbpixels[y * XRES + x] = g3d_curcidx;
118                 }
119                 break;
120
121         case G3D_LINES:
122                 break;  /* TODO */
123
124         case G3D_TRIANGLES:
125                 g3d_polyfill(v);
126                 break;
127
128         case G3D_QUADS:
129                 g3d_polyfill(v);
130                 v[1] = v[0];
131                 g3d_polyfill(v + 1);
132                 break;
133         }
134 }