summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/r_efrag.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_efrag.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_efrag.c')
-rw-r--r--apps/plugins/sdl/progs/quake/r_efrag.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/r_efrag.c b/apps/plugins/sdl/progs/quake/r_efrag.c
new file mode 100644
index 0000000000..5e4d3f9e06
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/r_efrag.c
@@ -0,0 +1,276 @@
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_efrag.c
21
22#include "quakedef.h"
23#include "r_local.h"
24
25mnode_t *r_pefragtopnode;
26
27
28//===========================================================================
29
30/*
31===============================================================================
32
33 ENTITY FRAGMENT FUNCTIONS
34
35===============================================================================
36*/
37
38efrag_t **lastlink;
39
40vec3_t r_emins, r_emaxs;
41
42entity_t *r_addent;
43
44
45/*
46================
47R_RemoveEfrags
48
49Call when removing an object from the world or moving it to another position
50================
51*/
52void R_RemoveEfrags (entity_t *ent)
53{
54 efrag_t *ef, *old, *walk, **prev;
55
56 ef = ent->efrag;
57
58 while (ef)
59 {
60 prev = &ef->leaf->efrags;
61 while (1)
62 {
63 walk = *prev;
64 if (!walk)
65 break;
66 if (walk == ef)
67 { // remove this fragment
68 *prev = ef->leafnext;
69 break;
70 }
71 else
72 prev = &walk->leafnext;
73 }
74
75 old = ef;
76 ef = ef->entnext;
77
78 // put it on the free list
79 old->entnext = cl.free_efrags;
80 cl.free_efrags = old;
81 }
82
83 ent->efrag = NULL;
84}
85
86/*
87===================
88R_SplitEntityOnNode
89===================
90*/
91void R_SplitEntityOnNode (mnode_t *node)
92{
93 efrag_t *ef;
94 mplane_t *splitplane;
95 mleaf_t *leaf;
96 int sides;
97
98 if (node->contents == CONTENTS_SOLID)
99 {
100 return;
101 }
102
103// add an efrag if the node is a leaf
104
105 if ( node->contents < 0)
106 {
107 if (!r_pefragtopnode)
108 r_pefragtopnode = node;
109
110 leaf = (mleaf_t *)node;
111
112// grab an efrag off the free list
113 ef = cl.free_efrags;
114 if (!ef)
115 {
116 Con_Printf ("Too many efrags!\n");
117 return; // no free fragments...
118 }
119 cl.free_efrags = cl.free_efrags->entnext;
120
121 ef->entity = r_addent;
122
123// add the entity link
124 *lastlink = ef;
125 lastlink = &ef->entnext;
126 ef->entnext = NULL;
127
128// set the leaf links
129 ef->leaf = leaf;
130 ef->leafnext = leaf->efrags;
131 leaf->efrags = ef;
132
133 return;
134 }
135
136// NODE_MIXED
137
138 splitplane = node->plane;
139 sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
140
141 if (sides == 3)
142 {
143 // split on this plane
144 // if this is the first splitter of this bmodel, remember it
145 if (!r_pefragtopnode)
146 r_pefragtopnode = node;
147 }
148
149// recurse down the contacted sides
150 if (sides & 1)
151 R_SplitEntityOnNode (node->children[0]);
152
153 if (sides & 2)
154 R_SplitEntityOnNode (node->children[1]);
155}
156
157
158/*
159===================
160R_SplitEntityOnNode2
161===================
162*/
163void R_SplitEntityOnNode2 (mnode_t *node)
164{
165 mplane_t *splitplane;
166 int sides;
167
168 if (node->visframe != r_visframecount)
169 return;
170
171 if (node->contents < 0)
172 {
173 if (node->contents != CONTENTS_SOLID)
174 r_pefragtopnode = node; // we've reached a non-solid leaf, so it's
175 // visible and not BSP clipped
176 return;
177 }
178
179 splitplane = node->plane;
180 sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
181
182 if (sides == 3)
183 {
184 // remember first splitter
185 r_pefragtopnode = node;
186 return;
187 }
188
189// not split yet; recurse down the contacted side
190 if (sides & 1)
191 R_SplitEntityOnNode2 (node->children[0]);
192 else
193 R_SplitEntityOnNode2 (node->children[1]);
194}
195
196
197/*
198===========
199R_AddEfrags
200===========
201*/
202void R_AddEfrags (entity_t *ent)
203{
204 model_t *entmodel;
205 int i;
206
207 if (!ent->model)
208 return;
209
210 if (ent == cl_entities)
211 return; // never add the world
212
213 r_addent = ent;
214
215 lastlink = &ent->efrag;
216 r_pefragtopnode = NULL;
217
218 entmodel = ent->model;
219
220 for (i=0 ; i<3 ; i++)
221 {
222 r_emins[i] = ent->origin[i] + entmodel->mins[i];
223 r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
224 }
225
226 R_SplitEntityOnNode (cl.worldmodel->nodes);
227
228 ent->topnode = r_pefragtopnode;
229}
230
231
232/*
233================
234R_StoreEfrags
235
236// FIXME: a lot of this goes away with edge-based
237================
238*/
239void R_StoreEfrags (efrag_t **ppefrag)
240{
241 entity_t *pent;
242 model_t *clmodel;
243 efrag_t *pefrag;
244
245
246 while ((pefrag = *ppefrag) != NULL)
247 {
248 pent = pefrag->entity;
249 clmodel = pent->model;
250
251 switch (clmodel->type)
252 {
253 case mod_alias:
254 case mod_brush:
255 case mod_sprite:
256 pent = pefrag->entity;
257
258 if ((pent->visframe != r_framecount) &&
259 (cl_numvisedicts < MAX_VISEDICTS))
260 {
261 cl_visedicts[cl_numvisedicts++] = pent;
262
263 // mark that we've recorded this entity for this frame
264 pent->visframe = r_framecount;
265 }
266
267 ppefrag = &pefrag->leafnext;
268 break;
269
270 default:
271 Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
272 }
273 }
274}
275
276