summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/vid_sdl.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/vid_sdl.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/vid_sdl.c')
-rw-r--r--apps/plugins/sdl/progs/quake/vid_sdl.c389
1 files changed, 389 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/vid_sdl.c b/apps/plugins/sdl/progs/quake/vid_sdl.c
new file mode 100644
index 0000000000..83d6a8486e
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/vid_sdl.c
@@ -0,0 +1,389 @@
1// vid_sdl.h -- sdl video driver
2
3#include "SDL.h"
4#include "quakedef.h"
5#include "d_local.h"
6
7viddef_t vid; // global video state
8unsigned short d_8to16table[256];
9
10// The original defaults
11//#define BASEWIDTH 320
12//#define BASEHEIGHT 200
13// Much better for high resolution displays
14#define BASEWIDTH LCD_WIDTH
15#define BASEHEIGHT LCD_HEIGHT
16
17int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes = 0;
18byte *VGA_pagebase;
19
20static SDL_Surface *screen = NULL;
21
22static qboolean mouse_avail;
23static float mouse_x, mouse_y;
24static int mouse_oldbuttonstate = 0;
25
26// No support for option menus
27void (*vid_menudrawfn)(void) = NULL;
28void (*vid_menukeyfn)(int key) = NULL;
29
30void VID_SetPalette (unsigned char *palette)
31{
32 int i;
33 SDL_Color colors[256];
34
35 for ( i=0; i<256; ++i )
36 {
37 colors[i].r = *palette++;
38 colors[i].g = *palette++;
39 colors[i].b = *palette++;
40 }
41 SDL_SetColors(screen, colors, 0, 256);
42}
43
44void VID_ShiftPalette (unsigned char *palette)
45{
46 VID_SetPalette(palette);
47}
48
49void VID_Init (unsigned char *palette)
50{
51 int pnum, chunk;
52 byte *cache;
53 int cachesize;
54 Uint8 video_bpp;
55 Uint16 video_w, video_h;
56 Uint32 flags;
57
58 // Load the SDL library
59 if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0)
60 Sys_Error("VID: Couldn't load SDL: %s", SDL_GetError());
61
62 // Set up display mode (width and height)
63 vid.width = BASEWIDTH;
64 vid.height = BASEHEIGHT;
65 vid.maxwarpwidth = WARP_WIDTH;
66 vid.maxwarpheight = WARP_HEIGHT;
67 if ((pnum=COM_CheckParm("-winsize")))
68 {
69 if (pnum >= com_argc-2)
70 Sys_Error("VID: -winsize <width> <height>\n");
71 vid.width = Q_atoi(com_argv[pnum+1]);
72 vid.height = Q_atoi(com_argv[pnum+2]);
73 if (!vid.width || !vid.height)
74 Sys_Error("VID: Bad window width/height\n");
75 }
76
77 // Set video width, height and flags
78 flags = (SDL_SWSURFACE|SDL_HWPALETTE);
79 if ( COM_CheckParm ("-fullscreen") )
80 flags |= SDL_FULLSCREEN;
81
82 // Initialize display
83 if (!(screen = SDL_SetVideoMode(vid.width, vid.height, 8, flags)))
84 Sys_Error("VID: Couldn't set video mode: %s\n", SDL_GetError());
85 VID_SetPalette(palette);
86 SDL_WM_SetCaption("sdlquake","sdlquake");
87 // now know everything we need to know about the buffer
88 VGA_width = vid.conwidth = vid.width;
89 VGA_height = vid.conheight = vid.height;
90 vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
91 vid.numpages = 1;
92 vid.colormap = host_colormap;
93 vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
94 VGA_pagebase = vid.buffer = screen->pixels;
95 VGA_rowbytes = vid.rowbytes = screen->pitch;
96 vid.conbuffer = vid.buffer;
97 vid.conrowbytes = vid.rowbytes;
98 vid.direct = 0;
99
100 // allocate z buffer and surface cache
101 chunk = vid.width * vid.height * sizeof (*d_pzbuffer);
102 cachesize = D_SurfaceCacheForRes (vid.width, vid.height);
103 chunk += cachesize;
104 d_pzbuffer = Hunk_HighAllocName(chunk, "video");
105 if (d_pzbuffer == NULL)
106 Sys_Error ("Not enough memory for video mode\n");
107
108 // initialize the cache memory
109 cache = (byte *) d_pzbuffer
110 + vid.width * vid.height * sizeof (*d_pzbuffer);
111 D_InitCaches (cache, cachesize);
112
113 // initialize the mouse
114 SDL_ShowCursor(0);
115}
116
117void VID_Shutdown (void)
118{
119 SDL_Quit();
120}
121
122void VID_Update (vrect_t *rects)
123{
124 SDL_Rect *sdlrects;
125 int n, i;
126 vrect_t *rect;
127
128 // Two-pass system, since Quake doesn't do it the SDL way...
129
130 // First, count the number of rectangles
131 n = 0;
132 for (rect = rects; rect; rect = rect->pnext)
133 ++n;
134
135 // Second, copy them to SDL rectangles and update
136 if (!(sdlrects = (SDL_Rect *)alloca(n*sizeof(*sdlrects))))
137 Sys_Error("Out of memory");
138 i = 0;
139 for (rect = rects; rect; rect = rect->pnext)
140 {
141 sdlrects[i].x = rect->x;
142 sdlrects[i].y = rect->y;
143 sdlrects[i].w = rect->width;
144 sdlrects[i].h = rect->height;
145 ++i;
146 }
147 SDL_UpdateRects(screen, n, sdlrects);
148}
149
150/*
151================
152D_BeginDirectRect
153================
154*/
155void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
156{
157 Uint8 *offset;
158
159
160 if (!screen) return;
161 if ( x < 0 ) x = screen->w+x-1;
162 offset = (Uint8 *)screen->pixels + y*screen->pitch + x;
163 while ( height-- )
164 {
165 memcpy(offset, pbitmap, width);
166 offset += screen->pitch;
167 pbitmap += width;
168 }
169}
170
171
172/*
173================
174D_EndDirectRect
175================
176*/
177void D_EndDirectRect (int x, int y, int width, int height)
178{
179 if (!screen) return;
180 if (x < 0) x = screen->w+x-1;
181 SDL_UpdateRect(screen, x, y, width, height);
182}
183
184
185/*
186================
187Sys_SendKeyEvents
188================
189*/
190
191void Sys_SendKeyEvents(void)
192{
193 SDL_Event event;
194 int sym, state;
195 int modstate;
196
197 while (SDL_PollEvent(&event))
198 {
199 switch (event.type) {
200
201 case SDL_KEYDOWN:
202 case SDL_KEYUP:
203 sym = event.key.keysym.sym;
204 state = event.key.state;
205 modstate = SDL_GetModState();
206 switch(sym)
207 {
208 case SDLK_DELETE: sym = K_DEL; break;
209 case SDLK_BACKSPACE: sym = K_BACKSPACE; break;
210 case SDLK_F1: sym = K_F1; break;
211 case SDLK_F2: sym = K_F2; break;
212 case SDLK_F3: sym = K_F3; break;
213 case SDLK_F4: sym = K_F4; break;
214 case SDLK_F5: sym = K_F5; break;
215 case SDLK_F6: sym = K_F6; break;
216 case SDLK_F7: sym = K_F7; break;
217 case SDLK_F8: sym = K_F8; break;
218 case SDLK_F9: sym = K_F9; break;
219 case SDLK_F10: sym = K_F10; break;
220 case SDLK_F11: sym = K_F11; break;
221 case SDLK_F12: sym = K_F12; break;
222 case SDLK_BREAK:
223 case SDLK_PAUSE: sym = K_PAUSE; break;
224 case SDLK_UP: sym = K_UPARROW; break;
225 case SDLK_DOWN: sym = K_DOWNARROW; break;
226 case SDLK_RIGHT: sym = K_RIGHTARROW; break;
227 case SDLK_LEFT: sym = K_LEFTARROW; break;
228 case SDLK_INSERT: sym = K_INS; break;
229 case SDLK_HOME: sym = K_HOME; break;
230 case SDLK_END: sym = K_END; break;
231 case SDLK_PAGEUP: sym = K_PGUP; break;
232 case SDLK_PAGEDOWN: sym = K_PGDN; break;
233 case SDLK_RSHIFT:
234 case SDLK_LSHIFT: sym = K_SHIFT; break;
235 case SDLK_RCTRL:
236 case SDLK_LCTRL: sym = K_CTRL; break;
237 case SDLK_RALT:
238 case SDLK_LALT: sym = K_ALT; break;
239 case SDLK_KP0:
240 if(modstate & KMOD_NUM) sym = K_INS;
241 else sym = SDLK_0;
242 break;
243 case SDLK_KP1:
244 if(modstate & KMOD_NUM) sym = K_END;
245 else sym = SDLK_1;
246 break;
247 case SDLK_KP2:
248 if(modstate & KMOD_NUM) sym = K_DOWNARROW;
249 else sym = SDLK_2;
250 break;
251 case SDLK_KP3:
252 if(modstate & KMOD_NUM) sym = K_PGDN;
253 else sym = SDLK_3;
254 break;
255 case SDLK_KP4:
256 if(modstate & KMOD_NUM) sym = K_LEFTARROW;
257 else sym = SDLK_4;
258 break;
259 case SDLK_KP5: sym = SDLK_5; break;
260 case SDLK_KP6:
261 if(modstate & KMOD_NUM) sym = K_RIGHTARROW;
262 else sym = SDLK_6;
263 break;
264 case SDLK_KP7:
265 if(modstate & KMOD_NUM) sym = K_HOME;
266 else sym = SDLK_7;
267 break;
268 case SDLK_KP8:
269 if(modstate & KMOD_NUM) sym = K_UPARROW;
270 else sym = SDLK_8;
271 break;
272 case SDLK_KP9:
273 if(modstate & KMOD_NUM) sym = K_PGUP;
274 else sym = SDLK_9;
275 break;
276 case SDLK_KP_PERIOD:
277 if(modstate & KMOD_NUM) sym = K_DEL;
278 else sym = SDLK_PERIOD;
279 break;
280 case SDLK_KP_DIVIDE: sym = SDLK_SLASH; break;
281 case SDLK_KP_MULTIPLY: sym = SDLK_ASTERISK; break;
282 case SDLK_KP_MINUS: sym = SDLK_MINUS; break;
283 case SDLK_KP_PLUS: sym = SDLK_PLUS; break;
284 case SDLK_KP_ENTER: sym = SDLK_RETURN; break;
285 case SDLK_KP_EQUALS: sym = SDLK_EQUALS; break;
286 }
287 // If we're not directly handled and still above 255
288 // just force it to 0
289 if(sym > 255) sym = 0;
290 Key_Event(sym, state);
291 break;
292
293 case SDL_MOUSEMOTION:
294 if ( (event.motion.x != (vid.width/2)) ||
295 (event.motion.y != (vid.height/2)) ) {
296 mouse_x = event.motion.xrel*10;
297 mouse_y = event.motion.yrel*10;
298 if ( (event.motion.x < ((vid.width/2)-(vid.width/4))) ||
299 (event.motion.x > ((vid.width/2)+(vid.width/4))) ||
300 (event.motion.y < ((vid.height/2)-(vid.height/4))) ||
301 (event.motion.y > ((vid.height/2)+(vid.height/4))) ) {
302 SDL_WarpMouse(vid.width/2, vid.height/2);
303 }
304 }
305 break;
306
307 case SDL_QUIT:
308 CL_Disconnect ();
309 Host_ShutdownServer(false);
310 Sys_Quit ();
311 break;
312 default:
313 break;
314 }
315 }
316}
317
318void IN_Init (void)
319{
320 if ( COM_CheckParm ("-nomouse") )
321 return;
322 mouse_x = mouse_y = 0.0;
323 mouse_avail = 1;
324}
325
326void IN_Shutdown (void)
327{
328 mouse_avail = 0;
329}
330
331void IN_Commands (void)
332{
333 int i;
334 int mouse_buttonstate;
335
336 if (!mouse_avail) return;
337
338 i = SDL_GetMouseState(NULL, NULL);
339 /* Quake swaps the second and third buttons */
340 mouse_buttonstate = (i & ~0x06) | ((i & 0x02)<<1) | ((i & 0x04)>>1);
341 for (i=0 ; i<3 ; i++) {
342 if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
343 Key_Event (K_MOUSE1 + i, true);
344
345 if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
346 Key_Event (K_MOUSE1 + i, false);
347 }
348 mouse_oldbuttonstate = mouse_buttonstate;
349}
350
351void IN_Move (usercmd_t *cmd)
352{
353 if (!mouse_avail)
354 return;
355
356 mouse_x *= sensitivity.value;
357 mouse_y *= sensitivity.value;
358
359 if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
360 cmd->sidemove += m_side.value * mouse_x;
361 else
362 cl.viewangles[YAW] -= m_yaw.value * mouse_x;
363 if (in_mlook.state & 1)
364 V_StopPitchDrift ();
365
366 if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) {
367 cl.viewangles[PITCH] += m_pitch.value * mouse_y;
368 if (cl.viewangles[PITCH] > 80)
369 cl.viewangles[PITCH] = 80;
370 if (cl.viewangles[PITCH] < -70)
371 cl.viewangles[PITCH] = -70;
372 } else {
373 if ((in_strafe.state & 1) && noclip_anglehack)
374 cmd->upmove -= m_forward.value * mouse_y;
375 else
376 cmd->forwardmove -= m_forward.value * mouse_y;
377 }
378 mouse_x = mouse_y = 0.0;
379}
380
381/*
382================
383Sys_ConsoleInput
384================
385*/
386char *Sys_ConsoleInput (void)
387{
388 return 0;
389}