2 Deep Runner - 6dof shooter game for the SGI O2.
3 Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
23 static struct pimage textures[MAX_TEXTURES];
25 void gaw_sw_reset(void)
32 void gaw_sw_init(void)
39 void gaw_sw_destroy(void)
46 void gaw_sw_framebuffer(int width, int height, void *pixels)
48 static int max_height;
49 static int max_npixels;
50 int npixels = width * height;
52 if(npixels > max_npixels) {
54 pfill_zbuf = malloc_nf(npixels * sizeof *pfill_zbuf);
55 max_npixels = npixels;
58 if(height > max_height) {
59 polyfill_fbheight(height);
66 pfill_fb.pixels = pixels;
67 pfill_fb.width = width;
68 pfill_fb.height = height;
70 gaw_viewport(0, 0, width, height);
73 /* set the framebuffer pointer, without resetting the size */
74 void gaw_sw_framebuffer_addr(void *pixels)
76 pfill_fb.pixels = pixels;
79 void gaw_enable(int what)
81 gaw_swtnl_enable(what);
84 void gaw_disable(int what)
86 gaw_swtnl_disable(what);
89 void gaw_clear(unsigned int flags)
91 int i, npix = pfill_fb.width * pfill_fb.height;
93 if(flags & GAW_COLORBUF) {
94 for(i=0; i<npix; i++) {
95 pfill_fb.pixels[i] = ST->clear_color;
99 if(flags & GAW_DEPTHBUF) {
100 for(i=0; i<npix; i++) {
101 pfill_zbuf[i] = ST->clear_depth;
106 void gaw_color_mask(int rmask, int gmask, int bmask, int amask)
108 gaw_swtnl_color_mask(rmask, gmask, bmask, amask);
111 void gaw_depth_mask(int mask)
113 gaw_swtnl_depth_mask(mask);
116 static int alloc_tex(void)
119 for(i=0; i<MAX_TEXTURES; i++) {
120 if(ST->textypes[i] == 0) {
127 unsigned int gaw_create_tex1d(int texfilter)
130 if((idx = alloc_tex()) == -1) {
133 ST->textypes[idx] = 1;
135 memset(textures + idx, 0, sizeof *textures);
140 unsigned int gaw_create_tex2d(int texfilter)
143 if((idx = alloc_tex()) == -1) {
146 ST->textypes[idx] = 2;
148 memset(textures + idx, 0, sizeof *textures);
153 void gaw_destroy_tex(unsigned int texid)
157 if(!ST->textypes[idx]) return;
159 free(textures[idx].pixels);
160 ST->textypes[idx] = 0;
163 void gaw_texfilter1d(int texfilter)
167 void gaw_texfilter2d(int texfilter)
171 void gaw_texwrap1d(int wrap)
175 void gaw_texwrap2d(int uwrap, int vwrap)
180 static __inline int calc_shift(unsigned int x)
190 void gaw_tex1d(int ifmt, int xsz, int fmt, void *pix)
192 gaw_tex2d(ifmt, xsz, 1, fmt, pix);
195 void gaw_tex2d(int ifmt, int xsz, int ysz, int fmt, void *pix)
200 if(ST->cur_tex < 0) return;
201 img = textures + ST->cur_tex;
206 img->pixels = malloc_nf(npix * sizeof *img->pixels);
210 img->xmask = xsz - 1;
211 img->ymask = ysz - 1;
212 img->xshift = calc_shift(xsz);
213 img->yshift = calc_shift(ysz);
215 gaw_subtex2d(0, 0, 0, xsz, ysz, fmt, pix);
218 void gaw_subtex2d(int lvl, int x, int y, int xsz, int ysz, int fmt, void *pix)
220 int i, j, r, g, b, val;
225 if(ST->cur_tex < 0) return;
226 img = textures + ST->cur_tex;
228 dest = img->pixels + (y << img->xshift) + x;
233 for(i=0; i<ysz; i++) {
234 for(j=0; j<xsz; j++) {
236 dest[j] = PACK_RGBA(val, val, val, 255);
243 for(i=0; i<ysz; i++) {
244 for(j=0; j<xsz; j++) {
249 dest[j] = PACK_RGBA(r, g, b, 255);
256 for(i=0; i<ysz; i++) {
257 for(j=0; j<xsz; j++) {
258 dest[j] = *((uint32_t*)src);
270 void gaw_bind_tex1d(int tex)
272 ST->cur_tex = (int)tex - 1;
273 pfill_tex = textures[ST->cur_tex];
276 void gaw_bind_tex2d(int tex)
278 ST->cur_tex = (int)tex - 1;
279 pfill_tex = textures[ST->cur_tex];
282 static void dump_texture(struct pimage *img, const char *fname)
284 int i, npix = img->width * img->height;
285 FILE *fp = fopen(fname, "wb");
288 fprintf(fp, "P6\n%d %d\n255\n", img->width, img->height);
289 for(i=0; i<npix; i++) {
290 int r = UNPACK_R(img->pixels[i]);
291 int g = UNPACK_G(img->pixels[i]);
292 int b = UNPACK_B(img->pixels[i]);
300 void gaw_sw_dump_textures(void)
305 for(i=0; i<MAX_TEXTURES; i++) {
306 if(ST->textypes[i] <= 0) continue;
308 sprintf(buf, "tex%04d.ppm", i);
309 printf("dumping %s ...\n", buf);
310 dump_texture(textures + i, buf);
314 void gaw_swtnl_drawprim(int prim, struct vertex *v, int vnum)
317 struct pvertex pv[16];
319 for(i=0; i<vnum; i++) {
320 /* viewport transformation */
321 v[i].x = (v[i].x * 0.5f + 0.5f) * (float)ST->vport[2] + ST->vport[0];
322 v[i].y = (v[i].y * 0.5f + 0.5f) * (float)ST->vport[3] + ST->vport[1];
323 v[i].y = pfill_fb.height - v[i].y - 1;
325 /* convert pos to 24.8 fixed point */
326 pv[i].x = cround64(v[i].x * 256.0f);
327 pv[i].y = cround64(v[i].y * 256.0f);
329 if(ST->opt & (1 << GAW_DEPTH_TEST)) {
330 /* after div/w z is in [-1, 1], remap it to [0, 0xffffff] */
331 pv[i].z = cround64(v[i].z * 8388607.5f + 8388607.5f);
334 /* convert tex coords to 16.16 fixed point */
335 pv[i].u = cround64(v[i].u * 65536.0f);
336 pv[i].v = cround64(v[i].v * 65536.0f);
337 /* pass the color through as is */
344 /* backface culling */
345 #if 0 /* TODO fix culling */
346 if(vnum > 2 && (ST->opt & (1 << GAW_CULL_FACE))) {
347 int32_t ax = pv[1].x - pv[0].x;
348 int32_t ay = pv[1].y - pv[0].y;
349 int32_t bx = pv[2].x - pv[0].x;
350 int32_t by = pv[2].y - pv[0].y;
351 int32_t cross_z = (ax >> 4) * (by >> 4) - (ay >> 4) * (bx >> 4);
352 int sign = (cross_z >> 31) & 1;
354 if(!(sign ^ ST->frontface)) {
355 continue; /* back-facing */
368 fill_mode = ST->polymode;
369 if(ST->opt & ((1 << GAW_TEXTURE_2D) | (1 << GAW_TEXTURE_1D))) {
370 fill_mode |= POLYFILL_TEX_BIT;
372 if((ST->opt & (1 << GAW_BLEND)) && (ST->bsrc == GAW_SRC_ALPHA)) {
373 fill_mode |= POLYFILL_ALPHA_BIT;
374 } else if((ST->opt & (1 << GAW_BLEND)) && (ST->bsrc == GAW_ONE)) {
375 fill_mode |= POLYFILL_ADD_BIT;
377 if(ST->opt & (1 << GAW_DEPTH_TEST)) {
378 fill_mode |= POLYFILL_ZBUF_BIT;
380 polyfill(fill_mode, pv, vnum);