summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/r_surf.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2018-02-11 15:34:30 -0500
committerFranklin Wei <git@fwei.tk>2019-07-19 22:37:40 -0400
commit5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4 (patch)
tree84406e21639529a185556a33e5de7f43cffc277b /apps/plugins/sdl/progs/quake/r_surf.c
parentb70fecf21ddc21877ec1ae7888d9c18a979e37ad (diff)
downloadrockbox-5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4.tar.gz
rockbox-5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4.zip
Quake!
This ports id Software's Quake to run on the SDL plugin runtime. The source code originated from id under the GPLv2 license. I used https://github.com/ahefner/sdlquake as the base of my port. Performance is, unsurprisingly, not on par with what you're probably used to on PC. I average about 10FPS on ipod6g, but it's still playable. Sound works well enough, but in-game music is not supported. I've written ARM assembly routines for the inner sound loop. Make sure you turn the "brightness" all the way down, or colors will look funky. To run, extract Quake's data files to /.rockbox/quake. Have fun! Change-Id: I4285036e967d7f0722802d43cf2096c808ca5799
Diffstat (limited to 'apps/plugins/sdl/progs/quake/r_surf.c')
-rw-r--r--apps/plugins/sdl/progs/quake/r_surf.c678
1 files changed, 678 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/r_surf.c b/apps/plugins/sdl/progs/quake/r_surf.c
new file mode 100644
index 0000000000..a2436d51b2
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/r_surf.c
@@ -0,0 +1,678 @@
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20// r_surf.c: surface-related refresh code
21
22#include "quakedef.h"
23#include "r_local.h"
24
25drawsurf_t r_drawsurf;
26
27int lightleft, sourcesstep, blocksize, sourcetstep;
28int lightdelta, lightdeltastep;
29int lightright, lightleftstep, lightrightstep, blockdivshift;
30unsigned blockdivmask;
31void *prowdestbase;
32unsigned char *pbasesource;
33int surfrowbytes; // used by ASM files
34unsigned *r_lightptr;
35int r_stepback;
36int r_lightwidth;
37int r_numhblocks, r_numvblocks;
38unsigned char *r_source, *r_sourcemax;
39
40void R_DrawSurfaceBlock8_mip0 (void);
41void R_DrawSurfaceBlock8_mip1 (void);
42void R_DrawSurfaceBlock8_mip2 (void);
43void R_DrawSurfaceBlock8_mip3 (void);
44
45static void (*surfmiptable[4])(void) = {
46 R_DrawSurfaceBlock8_mip0,
47 R_DrawSurfaceBlock8_mip1,
48 R_DrawSurfaceBlock8_mip2,
49 R_DrawSurfaceBlock8_mip3
50};
51
52
53
54unsigned blocklights[18*18];
55
56/*
57===============
58R_AddDynamicLights
59===============
60*/
61void R_AddDynamicLights (void)
62{
63 msurface_t *surf;
64 int lnum;
65 int sd, td;
66 float dist, rad, minlight;
67 vec3_t impact, local;
68 int s, t;
69 int i;
70 int smax, tmax;
71 mtexinfo_t *tex;
72
73 surf = r_drawsurf.surf;
74 smax = (surf->extents[0]>>4)+1;
75 tmax = (surf->extents[1]>>4)+1;
76 tex = surf->texinfo;
77
78 for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
79 {
80 if ( !(surf->dlightbits & (1<<lnum) ) )
81 continue; // not lit by this light
82
83 rad = cl_dlights[lnum].radius;
84 dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
85 surf->plane->dist;
86 rad -= fabs(dist);
87 minlight = cl_dlights[lnum].minlight;
88 if (rad < minlight)
89 continue;
90 minlight = rad - minlight;
91
92 for (i=0 ; i<3 ; i++)
93 {
94 impact[i] = cl_dlights[lnum].origin[i] -
95 surf->plane->normal[i]*dist;
96 }
97
98 local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
99 local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
100
101 local[0] -= surf->texturemins[0];
102 local[1] -= surf->texturemins[1];
103
104 for (t = 0 ; t<tmax ; t++)
105 {
106 td = local[1] - t*16;
107 if (td < 0)
108 td = -td;
109 for (s=0 ; s<smax ; s++)
110 {
111 sd = local[0] - s*16;
112 if (sd < 0)
113 sd = -sd;
114 if (sd > td)
115 dist = sd + (td>>1);
116 else
117 dist = td + (sd>>1);
118 if (dist < minlight)
119#ifdef QUAKE2
120 {
121 unsigned temp;
122 temp = (rad - dist)*256;
123 i = t*smax + s;
124 if (!cl_dlights[lnum].dark)
125 blocklights[i] += temp;
126 else
127 {
128 if (blocklights[i] > temp)
129 blocklights[i] -= temp;
130 else
131 blocklights[i] = 0;
132 }
133 }
134#else
135 blocklights[t*smax + s] += (rad - dist)*256;
136#endif
137 }
138 }
139 }
140}
141
142/*
143===============
144R_BuildLightMap
145
146Combine and scale multiple lightmaps into the 8.8 format in blocklights
147===============
148*/
149void R_BuildLightMap (void)
150{
151 int smax, tmax;
152 int t;
153 int i, size;
154 byte *lightmap;
155 unsigned scale;
156 int maps;
157 msurface_t *surf;
158
159 surf = r_drawsurf.surf;
160
161 smax = (surf->extents[0]>>4)+1;
162 tmax = (surf->extents[1]>>4)+1;
163 size = smax*tmax;
164 lightmap = surf->samples;
165
166 if (r_fullbright.value || !cl.worldmodel->lightdata)
167 {
168 for (i=0 ; i<size ; i++)
169 blocklights[i] = 0;
170 return;
171 }
172
173// clear to ambient
174 for (i=0 ; i<size ; i++)
175 blocklights[i] = r_refdef.ambientlight<<8;
176
177
178// add all the lightmaps
179 if (lightmap)
180 for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
181 maps++)
182 {
183 scale = r_drawsurf.lightadj[maps]; // 8.8 fraction
184 for (i=0 ; i<size ; i++)
185 blocklights[i] += lightmap[i] * scale;
186 lightmap += size; // skip to next lightmap
187 }
188
189// add all the dynamic lights
190 if (surf->dlightframe == r_framecount)
191 R_AddDynamicLights ();
192
193// bound, invert, and shift
194 for (i=0 ; i<size ; i++)
195 {
196 t = (255*256 - (int)blocklights[i]) >> (8 - VID_CBITS);
197
198 if (t < (1 << 6))
199 t = (1 << 6);
200
201 blocklights[i] = t;
202 }
203}
204
205
206/*
207===============
208R_TextureAnimation
209
210Returns the proper texture for a given time and base texture
211===============
212*/
213texture_t *R_TextureAnimation (texture_t *base)
214{
215 int reletive;
216 int count;
217
218 if (currententity->frame)
219 {
220 if (base->alternate_anims)
221 base = base->alternate_anims;
222 }
223
224 if (!base->anim_total)
225 return base;
226
227 reletive = (int)(cl.time*10) % base->anim_total;
228
229 count = 0;
230 while (base->anim_min > reletive || base->anim_max <= reletive)
231 {
232 base = base->anim_next;
233 if (!base)
234 Sys_Error ("R_TextureAnimation: broken cycle");
235 if (++count > 100)
236 Sys_Error ("R_TextureAnimation: infinite cycle");
237 }
238
239 return base;
240}
241
242
243/*
244===============
245R_DrawSurface
246===============
247*/
248void R_DrawSurface (void)
249{
250 unsigned char *basetptr;
251 int smax, tmax, twidth;
252 int u;
253 int soffset, basetoffset, texwidth;
254 int horzblockstep;
255 unsigned char *pcolumndest;
256 void (*pblockdrawer)(void);
257 texture_t *mt;
258
259// calculate the lightings
260 R_BuildLightMap ();
261
262 surfrowbytes = r_drawsurf.rowbytes;
263
264 mt = r_drawsurf.texture;
265
266 r_source = (byte *)mt + mt->offsets[r_drawsurf.surfmip];
267
268// the fractional light values should range from 0 to (VID_GRADES - 1) << 16
269// from a source range of 0 - 255
270
271 texwidth = mt->width >> r_drawsurf.surfmip;
272
273 blocksize = 16 >> r_drawsurf.surfmip;
274 blockdivshift = 4 - r_drawsurf.surfmip;
275 blockdivmask = (1 << blockdivshift) - 1;
276
277 r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1;
278
279 r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
280 r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
281
282//==============================
283
284 if (r_pixbytes == 1)
285 {
286 pblockdrawer = surfmiptable[r_drawsurf.surfmip];
287 // TODO: only needs to be set when there is a display settings change
288 horzblockstep = blocksize;
289 }
290 else
291 {
292 pblockdrawer = R_DrawSurfaceBlock16;
293 // TODO: only needs to be set when there is a display settings change
294 horzblockstep = blocksize << 1;
295 }
296
297 smax = mt->width >> r_drawsurf.surfmip;
298 twidth = texwidth;
299 tmax = mt->height >> r_drawsurf.surfmip;
300 sourcetstep = texwidth;
301 r_stepback = tmax * twidth;
302
303 r_sourcemax = r_source + (tmax * smax);
304
305 soffset = r_drawsurf.surf->texturemins[0];
306 basetoffset = r_drawsurf.surf->texturemins[1];
307
308// << 16 components are to guarantee positive values for %
309 soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
310 basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip)
311 + (tmax << 16)) % tmax) * twidth)];
312
313 pcolumndest = r_drawsurf.surfdat;
314
315 for (u=0 ; u<r_numhblocks; u++)
316 {
317 r_lightptr = blocklights + u;
318
319 prowdestbase = pcolumndest;
320
321 pbasesource = basetptr + soffset;
322
323 (*pblockdrawer)();
324
325 soffset = soffset + blocksize;
326 if (soffset >= smax)
327 soffset = 0;
328
329 pcolumndest += horzblockstep;
330 }
331}
332
333
334//=============================================================================
335
336#if !id386
337
338/*
339================
340R_DrawSurfaceBlock8_mip0
341================
342*/
343void R_DrawSurfaceBlock8_mip0 (void)
344{
345 int v, i, b, lightstep, lighttemp, light;
346 unsigned char pix, *psource, *prowdest;
347
348 psource = pbasesource;
349 prowdest = prowdestbase;
350
351 for (v=0 ; v<r_numvblocks ; v++)
352 {
353 // FIXME: make these locals?
354 // FIXME: use delta rather than both right and left, like ASM?
355 lightleft = r_lightptr[0];
356 lightright = r_lightptr[1];
357 r_lightptr += r_lightwidth;
358 lightleftstep = (r_lightptr[0] - lightleft) >> 4;
359 lightrightstep = (r_lightptr[1] - lightright) >> 4;
360
361 for (i=0 ; i<16 ; i++)
362 {
363 lighttemp = lightleft - lightright;
364 lightstep = lighttemp >> 4;
365
366 light = lightright;
367
368 for (b=15; b>=0; b--)
369 {
370 pix = psource[b];
371 prowdest[b] = ((unsigned char *)vid.colormap)
372 [(light & 0xFF00) + pix];
373 light += lightstep;
374 }
375
376 psource += sourcetstep;
377 lightright += lightrightstep;
378 lightleft += lightleftstep;
379 prowdest += surfrowbytes;
380 }
381
382 if (psource >= r_sourcemax)
383 psource -= r_stepback;
384 }
385}
386
387
388/*
389================
390R_DrawSurfaceBlock8_mip1
391================
392*/
393void R_DrawSurfaceBlock8_mip1 (void)
394{
395 int v, i, b, lightstep, lighttemp, light;
396 unsigned char pix, *psource, *prowdest;
397
398 psource = pbasesource;
399 prowdest = prowdestbase;
400
401 for (v=0 ; v<r_numvblocks ; v++)
402 {
403 // FIXME: make these locals?
404 // FIXME: use delta rather than both right and left, like ASM?
405 lightleft = r_lightptr[0];
406 lightright = r_lightptr[1];
407 r_lightptr += r_lightwidth;
408 lightleftstep = (r_lightptr[0] - lightleft) >> 3;
409 lightrightstep = (r_lightptr[1] - lightright) >> 3;
410
411 for (i=0 ; i<8 ; i++)
412 {
413 lighttemp = lightleft - lightright;
414 lightstep = lighttemp >> 3;
415
416 light = lightright;
417
418 for (b=7; b>=0; b--)
419 {
420 pix = psource[b];
421 prowdest[b] = ((unsigned char *)vid.colormap)
422 [(light & 0xFF00) + pix];
423 light += lightstep;
424 }
425
426 psource += sourcetstep;
427 lightright += lightrightstep;
428 lightleft += lightleftstep;
429 prowdest += surfrowbytes;
430 }
431
432 if (psource >= r_sourcemax)
433 psource -= r_stepback;
434 }
435}
436
437
438/*
439================
440R_DrawSurfaceBlock8_mip2
441================
442*/
443void R_DrawSurfaceBlock8_mip2 (void)
444{
445 int v, i, b, lightstep, lighttemp, light;
446 unsigned char pix, *psource, *prowdest;
447
448 psource = pbasesource;
449 prowdest = prowdestbase;
450
451 for (v=0 ; v<r_numvblocks ; v++)
452 {
453 // FIXME: make these locals?
454 // FIXME: use delta rather than both right and left, like ASM?
455 lightleft = r_lightptr[0];
456 lightright = r_lightptr[1];
457 r_lightptr += r_lightwidth;
458 lightleftstep = (r_lightptr[0] - lightleft) >> 2;
459 lightrightstep = (r_lightptr[1] - lightright) >> 2;
460
461 for (i=0 ; i<4 ; i++)
462 {
463 lighttemp = lightleft - lightright;
464 lightstep = lighttemp >> 2;
465
466 light = lightright;
467
468 for (b=3; b>=0; b--)
469 {
470 pix = psource[b];
471 prowdest[b] = ((unsigned char *)vid.colormap)
472 [(light & 0xFF00) + pix];
473 light += lightstep;
474 }
475
476 psource += sourcetstep;
477 lightright += lightrightstep;
478 lightleft += lightleftstep;
479 prowdest += surfrowbytes;
480 }
481
482 if (psource >= r_sourcemax)
483 psource -= r_stepback;
484 }
485}
486
487
488/*
489================
490R_DrawSurfaceBlock8_mip3
491================
492*/
493void R_DrawSurfaceBlock8_mip3 (void)
494{
495 int v, i, b, lightstep, lighttemp, light;
496 unsigned char pix, *psource, *prowdest;
497
498 psource = pbasesource;
499 prowdest = prowdestbase;
500
501 for (v=0 ; v<r_numvblocks ; v++)
502 {
503 // FIXME: make these locals?
504 // FIXME: use delta rather than both right and left, like ASM?
505 lightleft = r_lightptr[0];
506 lightright = r_lightptr[1];
507 r_lightptr += r_lightwidth;
508 lightleftstep = (r_lightptr[0] - lightleft) >> 1;
509 lightrightstep = (r_lightptr[1] - lightright) >> 1;
510
511 for (i=0 ; i<2 ; i++)
512 {
513 lighttemp = lightleft - lightright;
514 lightstep = lighttemp >> 1;
515
516 light = lightright;
517
518 for (b=1; b>=0; b--)
519 {
520 pix = psource[b];
521 prowdest[b] = ((unsigned char *)vid.colormap)
522 [(light & 0xFF00) + pix];
523 light += lightstep;
524 }
525
526 psource += sourcetstep;
527 lightright += lightrightstep;
528 lightleft += lightleftstep;
529 prowdest += surfrowbytes;
530 }
531
532 if (psource >= r_sourcemax)
533 psource -= r_stepback;
534 }
535}
536
537
538/*
539================
540R_DrawSurfaceBlock16
541
542FIXME: make this work
543================
544*/
545void R_DrawSurfaceBlock16 (void)
546{
547 int k;
548 unsigned char *psource;
549 int lighttemp, lightstep, light;
550 unsigned short *prowdest;
551
552 prowdest = (unsigned short *)prowdestbase;
553
554 for (k=0 ; k<blocksize ; k++)
555 {
556 unsigned short *pdest;
557 unsigned char pix;
558 int b;
559
560 psource = pbasesource;
561 lighttemp = lightright - lightleft;
562 lightstep = lighttemp >> blockdivshift;
563
564 light = lightleft;
565 pdest = prowdest;
566
567 for (b=0; b<blocksize; b++)
568 {
569 pix = *psource;
570 *pdest = vid.colormap16[(light & 0xFF00) + pix];
571 psource += sourcesstep;
572 pdest++;
573 light += lightstep;
574 }
575
576 pbasesource += sourcetstep;
577 lightright += lightrightstep;
578 lightleft += lightleftstep;
579 prowdest = (unsigned short *)((long)prowdest + surfrowbytes);
580 }
581
582 prowdestbase = prowdest;
583}
584
585#endif
586
587
588//============================================================================
589
590/*
591================
592R_GenTurbTile
593================
594*/
595void R_GenTurbTile (pixel_t *pbasetex, void *pdest)
596{
597 int *turb;
598 int i, j, s, t;
599 byte *pd;
600
601 turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
602 pd = (byte *)pdest;
603
604 for (i=0 ; i<TILE_SIZE ; i++)
605 {
606 for (j=0 ; j<TILE_SIZE ; j++)
607 {
608 s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
609 t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
610 *pd++ = *(pbasetex + (t<<6) + s);
611 }
612 }
613}
614
615
616/*
617================
618R_GenTurbTile16
619================
620*/
621void R_GenTurbTile16 (pixel_t *pbasetex, void *pdest)
622{
623 int *turb;
624 int i, j, s, t;
625 unsigned short *pd;
626
627 turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
628 pd = (unsigned short *)pdest;
629
630 for (i=0 ; i<TILE_SIZE ; i++)
631 {
632 for (j=0 ; j<TILE_SIZE ; j++)
633 {
634 s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
635 t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
636 *pd++ = d_8to16table[*(pbasetex + (t<<6) + s)];
637 }
638 }
639}
640
641
642/*
643================
644R_GenTile
645================
646*/
647void R_GenTile (msurface_t *psurf, void *pdest)
648{
649 if (psurf->flags & SURF_DRAWTURB)
650 {
651 if (r_pixbytes == 1)
652 {
653 R_GenTurbTile ((pixel_t *)
654 ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
655 }
656 else
657 {
658 R_GenTurbTile16 ((pixel_t *)
659 ((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
660 }
661 }
662 else if (psurf->flags & SURF_DRAWSKY)
663 {
664 if (r_pixbytes == 1)
665 {
666 R_GenSkyTile (pdest);
667 }
668 else
669 {
670 R_GenSkyTile16 (pdest);
671 }
672 }
673 else
674 {
675 Sys_Error ("Unknown tile type");
676 }
677}
678