summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/d_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/d_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/d_surf.c')
-rw-r--r--apps/plugins/sdl/progs/quake/d_surf.c335
1 files changed, 335 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/d_surf.c b/apps/plugins/sdl/progs/quake/d_surf.c
new file mode 100644
index 0000000000..b09c5f896e
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/d_surf.c
@@ -0,0 +1,335 @@
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// d_surf.c: rasterization driver surface heap manager
21
22#include "quakedef.h"
23#include "d_local.h"
24#include "r_local.h"
25
26float surfscale;
27qboolean r_cache_thrash; // set if surface cache is thrashing
28
29int sc_size;
30surfcache_t *sc_rover, *sc_base;
31
32#define GUARDSIZE 4
33
34
35int D_SurfaceCacheForRes (int width, int height)
36{
37 int size, pix;
38
39 if (COM_CheckParm ("-surfcachesize"))
40 {
41 size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024;
42 return size;
43 }
44
45 size = SURFCACHE_SIZE_AT_320X200;
46
47 pix = width*height;
48 if (pix > 64000)
49 size += (pix-64000)*3;
50
51
52 return size;
53}
54
55void D_CheckCacheGuard (void)
56{
57 byte *s;
58 int i;
59
60 s = (byte *)sc_base + sc_size;
61 for (i=0 ; i<GUARDSIZE ; i++)
62 if (s[i] != (byte)i)
63 Sys_Error ("D_CheckCacheGuard: failed");
64}
65
66void D_ClearCacheGuard (void)
67{
68 byte *s;
69 int i;
70
71 s = (byte *)sc_base + sc_size;
72 for (i=0 ; i<GUARDSIZE ; i++)
73 s[i] = (byte)i;
74}
75
76
77/*
78================
79D_InitCaches
80
81================
82*/
83void D_InitCaches (void *buffer, int size)
84{
85
86 if (!msg_suppress_1)
87 Con_Printf ("%ik surface cache\n", size/1024);
88
89 sc_size = size - GUARDSIZE;
90 sc_base = (surfcache_t *)buffer;
91 sc_rover = sc_base;
92
93 sc_base->next = NULL;
94 sc_base->owner = NULL;
95 sc_base->size = sc_size;
96
97 D_ClearCacheGuard ();
98}
99
100
101/*
102==================
103D_FlushCaches
104==================
105*/
106void D_FlushCaches (void)
107{
108 surfcache_t *c;
109
110 if (!sc_base)
111 return;
112
113 for (c = sc_base ; c ; c = c->next)
114 {
115 if (c->owner)
116 *c->owner = NULL;
117 }
118
119 sc_rover = sc_base;
120 sc_base->next = NULL;
121 sc_base->owner = NULL;
122 sc_base->size = sc_size;
123}
124
125/*
126=================
127D_SCAlloc
128=================
129*/
130surfcache_t *D_SCAlloc (int width, int size)
131{
132 surfcache_t *new;
133 qboolean wrapped_this_time;
134
135 if ((width < 0) || (width > 256))
136 Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
137
138 if ((size <= 0) || (size > 0x10000))
139 Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
140
141 size = (int)&((surfcache_t *)0)->data[size];
142 size = (size + 3) & ~3;
143 if (size > sc_size)
144 Sys_Error ("D_SCAlloc: %i > cache size",size);
145
146// if there is not size bytes after the rover, reset to the start
147 wrapped_this_time = false;
148
149 if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
150 {
151 if (sc_rover)
152 {
153 wrapped_this_time = true;
154 }
155 sc_rover = sc_base;
156 }
157
158// colect and free surfcache_t blocks until the rover block is large enough
159 new = sc_rover;
160 if (sc_rover->owner)
161 *sc_rover->owner = NULL;
162
163 while (new->size < size)
164 {
165 // free another
166 sc_rover = sc_rover->next;
167 if (!sc_rover)
168 Sys_Error ("D_SCAlloc: hit the end of memory");
169 if (sc_rover->owner)
170 *sc_rover->owner = NULL;
171
172 new->size += sc_rover->size;
173 new->next = sc_rover->next;
174 }
175
176// create a fragment out of any leftovers
177 if (new->size - size > 256)
178 {
179 sc_rover = (surfcache_t *)( (byte *)new + size);
180 sc_rover->size = new->size - size;
181 sc_rover->next = new->next;
182 sc_rover->width = 0;
183 sc_rover->owner = NULL;
184 new->next = sc_rover;
185 new->size = size;
186 }
187 else
188 sc_rover = new->next;
189
190 new->width = width;
191// DEBUG
192 if (width > 0)
193 new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
194
195 new->owner = NULL; // should be set properly after return
196
197 if (d_roverwrapped)
198 {
199 if (wrapped_this_time || (sc_rover >= d_initial_rover))
200 r_cache_thrash = true;
201 }
202 else if (wrapped_this_time)
203 {
204 d_roverwrapped = true;
205 }
206
207D_CheckCacheGuard (); // DEBUG
208 return new;
209}
210
211
212/*
213=================
214D_SCDump
215=================
216*/
217void D_SCDump (void)
218{
219 surfcache_t *test;
220
221 for (test = sc_base ; test ; test = test->next)
222 {
223 if (test == sc_rover)
224 Sys_Printf ("ROVER:\n");
225 printf ("%p : %i bytes %i width\n",test, test->size, test->width);
226 }
227}
228
229//=============================================================================
230
231// if the num is not a power of 2, assume it will not repeat
232
233int MaskForNum (int num)
234{
235 if (num==128)
236 return 127;
237 if (num==64)
238 return 63;
239 if (num==32)
240 return 31;
241 if (num==16)
242 return 15;
243 return 255;
244}
245
246int D_log2 (int num)
247{
248 int c;
249
250 c = 0;
251
252 while (num>>=1)
253 c++;
254 return c;
255}
256
257//=============================================================================
258
259/*
260================
261D_CacheSurface
262================
263*/
264surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
265{
266 surfcache_t *cache;
267
268//
269// if the surface is animating or flashing, flush the cache
270//
271 r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
272 r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
273 r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
274 r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
275 r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
276
277//
278// see if the cache holds apropriate data
279//
280 cache = surface->cachespots[miplevel];
281
282 if (cache && !cache->dlight && surface->dlightframe != r_framecount
283 && cache->texture == r_drawsurf.texture
284 && cache->lightadj[0] == r_drawsurf.lightadj[0]
285 && cache->lightadj[1] == r_drawsurf.lightadj[1]
286 && cache->lightadj[2] == r_drawsurf.lightadj[2]
287 && cache->lightadj[3] == r_drawsurf.lightadj[3] )
288 return cache;
289
290//
291// determine shape of surface
292//
293 surfscale = 1.0 / (1<<miplevel);
294 r_drawsurf.surfmip = miplevel;
295 r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
296 r_drawsurf.rowbytes = r_drawsurf.surfwidth;
297 r_drawsurf.surfheight = surface->extents[1] >> miplevel;
298
299//
300// allocate memory if needed
301//
302 if (!cache) // if a texture just animated, don't reallocate it
303 {
304 cache = D_SCAlloc (r_drawsurf.surfwidth,
305 r_drawsurf.surfwidth * r_drawsurf.surfheight);
306 surface->cachespots[miplevel] = cache;
307 cache->owner = &surface->cachespots[miplevel];
308 cache->mipscale = surfscale;
309 }
310
311 if (surface->dlightframe == r_framecount)
312 cache->dlight = 1;
313 else
314 cache->dlight = 0;
315
316 r_drawsurf.surfdat = (pixel_t *)cache->data;
317
318 cache->texture = r_drawsurf.texture;
319 cache->lightadj[0] = r_drawsurf.lightadj[0];
320 cache->lightadj[1] = r_drawsurf.lightadj[1];
321 cache->lightadj[2] = r_drawsurf.lightadj[2];
322 cache->lightadj[3] = r_drawsurf.lightadj[3];
323
324//
325// draw and light the surface texture
326//
327 r_drawsurf.surf = surface;
328
329 c_surf++;
330 R_DrawSurface ();
331
332 return surface->cachespots[miplevel];
333}
334
335