foo
[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         "mul ebx" \
74         "shrd eax, edx, cl" \
75         parm [eax] [ebx] [ecx] \
76         value [eax];
77
78 void g3d_draw_prim(int prim, struct g3d_vertex *varr)
79 {
80         int i, vcount, x, y, x1, y1;
81         struct g3d_vertex v[4];
82
83         vcount = primverts[prim];
84
85         for(i=0; i<vcount; i++) {
86                 v[i] = varr[i];
87
88                 /* transform to view space */
89                 g3d_xform(v + i, mvmat);
90
91                 /* transform to homogeneous clip space */
92                 g3d_xform(v + i, pmat);
93
94                 /* TODO clip */
95
96                 /* perspective division */
97                 if(v[i].w != 0) {
98                         v[i].x = (v[i].x << 4) / (v[i].w >> 4);
99                         v[i].y = (v[i].y << 4) / (v[i].w >> 4);
100                 }
101
102                 /* viewport transform */
103                 v[i].x = vpscale(v[i].x, vp[2], 1) + (vp[0] << 8);
104                 v[i].y = vpscale(-v[i].y, vp[3], 1) + (vp[1] << 8);
105         }
106
107         switch(prim) {
108         case G3D_POINTS:
109                 x = v[0].x >> 8;
110                 y = v[0].y >> 8;
111                 if(x >= 0 && y >= 0 && x < XRES && y < YRES) {
112                         g3d_fbpixels[y * XRES + x] = g3d_curcidx;
113                 }
114                 break;
115
116         case G3D_LINES:
117                 break;  /* TODO */
118
119         case G3D_TRIANGLES:
120                 g3d_polyfill(v);
121                 break;
122
123         case G3D_QUADS:
124                 g3d_polyfill(v);
125                 v[1] = v[0];
126                 g3d_polyfill(v + 1);
127                 break;
128         }
129 }