diff options
author | Franklin Wei <git@fwei.tk> | 2018-02-11 15:34:30 -0500 |
---|---|---|
committer | Franklin Wei <git@fwei.tk> | 2019-07-19 22:37:40 -0400 |
commit | 5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4 (patch) | |
tree | 84406e21639529a185556a33e5de7f43cffc277b /apps/plugins/sdl/progs/quake/vid_sdl.c | |
parent | b70fecf21ddc21877ec1ae7888d9c18a979e37ad (diff) | |
download | rockbox-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.c | 389 |
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 | |||
7 | viddef_t vid; // global video state | ||
8 | unsigned 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 | |||
17 | int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes = 0; | ||
18 | byte *VGA_pagebase; | ||
19 | |||
20 | static SDL_Surface *screen = NULL; | ||
21 | |||
22 | static qboolean mouse_avail; | ||
23 | static float mouse_x, mouse_y; | ||
24 | static int mouse_oldbuttonstate = 0; | ||
25 | |||
26 | // No support for option menus | ||
27 | void (*vid_menudrawfn)(void) = NULL; | ||
28 | void (*vid_menukeyfn)(int key) = NULL; | ||
29 | |||
30 | void 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 | |||
44 | void VID_ShiftPalette (unsigned char *palette) | ||
45 | { | ||
46 | VID_SetPalette(palette); | ||
47 | } | ||
48 | |||
49 | void 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 | |||
117 | void VID_Shutdown (void) | ||
118 | { | ||
119 | SDL_Quit(); | ||
120 | } | ||
121 | |||
122 | void 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 | ================ | ||
152 | D_BeginDirectRect | ||
153 | ================ | ||
154 | */ | ||
155 | void 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 | ================ | ||
174 | D_EndDirectRect | ||
175 | ================ | ||
176 | */ | ||
177 | void 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 | ================ | ||
187 | Sys_SendKeyEvents | ||
188 | ================ | ||
189 | */ | ||
190 | |||
191 | void 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 | |||
318 | void IN_Init (void) | ||
319 | { | ||
320 | if ( COM_CheckParm ("-nomouse") ) | ||
321 | return; | ||
322 | mouse_x = mouse_y = 0.0; | ||
323 | mouse_avail = 1; | ||
324 | } | ||
325 | |||
326 | void IN_Shutdown (void) | ||
327 | { | ||
328 | mouse_avail = 0; | ||
329 | } | ||
330 | |||
331 | void 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 | |||
351 | void 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 | ================ | ||
383 | Sys_ConsoleInput | ||
384 | ================ | ||
385 | */ | ||
386 | char *Sys_ConsoleInput (void) | ||
387 | { | ||
388 | return 0; | ||
389 | } | ||