Add weapon cycling bindings for mouse and joystick buttons. Add weapon cycling bindi...
[chocolate-doom.git] / src / i_system.c
blobf37b5becd16565d1cb4a839f7f9496d06a6c5aad
1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // Copyright(C) 1993-1996 Id Software, Inc.
5 // Copyright(C) 2005 Simon Howard
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 // 02111-1307, USA.
22 // DESCRIPTION:
24 //-----------------------------------------------------------------------------
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
32 #include <stdarg.h>
34 #ifdef _WIN32
35 #define WIN32_LEAN_AND_MEAN
36 #include <windows.h>
37 #else
38 #include <unistd.h>
39 #endif
41 #include "deh_main.h"
42 #include "doomdef.h"
43 #include "doomstat.h"
44 #include "m_argv.h"
45 #include "m_config.h"
46 #include "m_misc.h"
47 #include "i_joystick.h"
48 #include "i_timer.h"
49 #include "i_video.h"
50 #include "s_sound.h"
52 #include "d_net.h"
53 #include "g_game.h"
55 #include "i_system.h"
56 #include "txt_main.h"
59 #include "w_wad.h"
60 #include "z_zone.h"
62 #define DEFAULT_RAM 16 /* MiB */
63 #define MIN_RAM 4 /* MiB */
65 int show_endoom = 1;
67 // Tactile feedback function, probably used for the Logitech Cyberman
69 void I_Tactile(int on, int off, int total)
73 #ifdef _WIN32_WCE
75 // Windows CE-specific auto-allocation function that allocates the zone
76 // size based on the amount of memory reported free by the OS.
78 static byte *AutoAllocMemory(int *size, int default_ram, int min_ram)
80 MEMORYSTATUS memory_status;
81 byte *zonemem;
82 size_t available;
84 // Get available physical RAM. We leave one megabyte extra free
85 // for the OS to keep running (my PDA becomes unstable if too
86 // much RAM is allocated)
88 GlobalMemoryStatus(&memory_status);
89 available = memory_status.dwAvailPhys - 2 * 1024 * 1024;
91 // Limit to default_ram if we have more than that available:
93 if (available > default_ram * 1024 * 1024)
95 available = default_ram * 1024 * 1024;
98 if (available < min_ram * 1024 * 1024)
100 I_Error("Unable to allocate %i MiB of RAM for zone", min_ram);
103 // Allocate zone:
105 *size = available;
106 zonemem = malloc(*size);
108 if (zonemem == NULL)
110 I_Error("Failed when allocating %i bytes", *size);
113 return zonemem;
116 #else
118 // Zone memory auto-allocation function that allocates the zone size
119 // by trying progressively smaller zone sizes until one is found that
120 // works.
122 static byte *AutoAllocMemory(int *size, int default_ram, int min_ram)
124 byte *zonemem;
126 // Allocate the zone memory. This loop tries progressively smaller
127 // zone sizes until a size is found that can be allocated.
128 // If we used the -mb command line parameter, only the parameter
129 // provided is accepted.
131 zonemem = NULL;
133 while (zonemem == NULL)
135 // We need a reasonable minimum amount of RAM to start.
137 if (default_ram < min_ram)
139 I_Error("Unable to allocate %i MiB of RAM for zone", default_ram);
142 // Try to allocate the zone memory.
144 *size = default_ram * 1024 * 1024;
146 zonemem = malloc(*size);
148 // Failed to allocate? Reduce zone size until we reach a size
149 // that is acceptable.
151 if (zonemem == NULL)
153 default_ram -= 1;
157 return zonemem;
160 #endif
162 byte *I_ZoneBase (int *size)
164 byte *zonemem;
165 int min_ram, default_ram;
166 int p;
169 // @arg <mb>
171 // Specify the heap size, in MiB (default 16).
174 p = M_CheckParm("-mb");
176 if (p > 0)
178 default_ram = atoi(myargv[p+1]);
179 min_ram = default_ram;
181 else
183 default_ram = DEFAULT_RAM;
184 min_ram = MIN_RAM;
187 zonemem = AutoAllocMemory(size, default_ram, min_ram);
189 printf("zone memory: %p, %x allocated for zone\n",
190 zonemem, *size);
192 return zonemem;
196 // I_ConsoleStdout
198 // Returns true if stdout is a real console, false if it is a file
201 boolean I_ConsoleStdout(void)
203 #ifdef _WIN32
204 // SDL "helpfully" always redirects stdout to a file.
205 return 0;
206 #else
207 return isatty(fileno(stdout));
208 #endif
212 // I_Init
214 void I_Init (void)
216 I_CheckIsScreensaver();
217 I_InitTimer();
218 I_InitJoystick();
221 #define ENDOOM_W 80
222 #define ENDOOM_H 25
225 // Displays the text mode ending screen after the game quits
228 void I_Endoom(void)
230 unsigned char *endoom_data;
231 unsigned char *screendata;
232 int y;
233 int indent;
235 endoom_data = W_CacheLumpName(DEH_String("ENDOOM"), PU_STATIC);
237 // Set up text mode screen
239 TXT_Init();
241 // Make sure the new window has the right title and icon
243 I_SetWindowCaption();
244 I_SetWindowIcon();
246 // Write the data to the screen memory
248 screendata = TXT_GetScreenData();
250 indent = (ENDOOM_W - TXT_SCREEN_W) / 2;
252 for (y=0; y<TXT_SCREEN_H; ++y)
254 memcpy(screendata + (y * TXT_SCREEN_W * 2),
255 endoom_data + (y * ENDOOM_W + indent) * 2,
256 TXT_SCREEN_W * 2);
259 // Wait for a keypress
261 while (true)
263 TXT_UpdateScreen();
265 if (TXT_GetChar() >= 0)
267 break;
270 TXT_Sleep(0);
273 // Shut down text mode screen
275 TXT_Shutdown();
279 // I_Quit
282 void I_Quit (void)
284 D_QuitNetGame ();
285 G_CheckDemoStatus();
286 S_Shutdown();
288 if (!screensaver_mode)
290 M_SaveDefaults ();
293 I_ShutdownGraphics();
295 if (show_endoom && !testcontrols && !screensaver_mode)
297 I_Endoom();
300 exit(0);
303 void I_WaitVBL(int count)
305 I_Sleep((count * 1000) / 70);
309 // I_Error
311 extern boolean demorecording;
313 static boolean already_quitting = false;
315 void I_Error (char *error, ...)
317 va_list argptr;
319 if (already_quitting)
321 fprintf(stderr, "Warning: recursive call to I_Error detected.\n");
322 exit(-1);
324 else
326 already_quitting = true;
329 // Message first.
330 va_start(argptr, error);
331 fprintf(stderr, "\nError: ");
332 vfprintf(stderr, error, argptr);
333 fprintf(stderr, "\n");
334 va_end(argptr);
335 fflush(stderr);
337 // Shutdown. Here might be other errors.
339 if (demorecording)
341 G_CheckDemoStatus();
344 D_QuitNetGame ();
345 I_ShutdownGraphics();
346 S_Shutdown();
348 #ifdef _WIN32
349 // On Windows, pop up a dialog box with the error message.
351 char msgbuf[512];
352 wchar_t wmsgbuf[512];
354 va_start(argptr, error);
355 memset(msgbuf, 0, sizeof(msgbuf));
356 vsnprintf(msgbuf, sizeof(msgbuf) - 1, error, argptr);
357 va_end(argptr);
359 MultiByteToWideChar(CP_ACP, 0,
360 msgbuf, strlen(msgbuf) + 1,
361 wmsgbuf, sizeof(wmsgbuf));
363 MessageBoxW(NULL, wmsgbuf, L"Error", MB_OK);
365 #endif
367 // abort();
369 exit(-1);