1 //----------------------------------------------------------------------------
2 //  EDGE Misc: Screenshots, Menu and defaults Code
3 //----------------------------------------------------------------------------
4 //
5 //  Copyright (c) 1999-2009  The EDGE Team.
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.
11 //
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.
16 //
17 //----------------------------------------------------------------------------
18 //
19 //  Based on the DOOM source code, released by Id Software under the
20 //  following copyright:
21 //
22 //    Copyright (C) 1993-1996 by id Software, Inc.
23 //
24 //----------------------------------------------------------------------------
25 //
26 // -MH- 1998/07/02  Added key_flyup and key_flydown
27 // -MH- 1998/07/02 "shootupdown" --> "true3dgameplay"
28 // -ACB- 2000/06/02 Removed Control Defaults
29 //
30 
31 #include "i_defs.h"
32 
33 #include "epi/utility.h"
34 #include "epi/endianess.h"
35 #include "epi/file.h"
36 #include "epi/filesystem.h"
37 #include "epi/path.h"
38 #include "epi/str_format.h"
39 
40 #include "epi/image_data.h"
41 #include "epi/image_jpeg.h"
42 #include "epi/image_png.h"
43 
44 #include "con_main.h"
45 #include "dm_defs.h"
46 #include "dm_state.h"
47 #include "e_input.h"
48 #include "e_player.h"
49 #include "hu_draw.h"
50 #include "hu_stuff.h"  // only for showMessages
51 #include "m_argv.h"
52 #include "m_misc.h"
53 #include "m_option.h"
54 #include "n_network.h"
55 #include "p_spec.h"
56 #include "r_gldefs.h"
57 #include "s_music.h"  // mus_volume
58 #include "s_sound.h"
59 #include "am_map.h"
60 #include "r_colormap.h"
61 #include "r_draw.h"
62 #include "r_modes.h"
63 #include "r_image.h"
64 #include "r_wipe.h"
65 #include "version.h"
66 
67 #include "defaults.h"
68 
69 //
70 // DEFAULTS
71 //
72 int monitor_size;
73 
74 cvar_c m_diskicon;
75 
76 bool display_disk = false;
77 int  display_desync = 0;
78 
79 static const image_c *disk_image = NULL;
80 
81 bool force_directx = false;
82 bool force_waveout = false;
83 
84 unsigned short save_screenshot[160][100];
85 bool save_screenshot_valid = false;
86 
87 int var_sample_rate = 0;
88 int var_sound_bits = 0;
89 int var_sound_stereo = 0;
90 int var_mix_channels = 0;
91 int var_quiet_factor = 0;
92 int var_timid_factor = 0;
93 
94 static int edge_version;
95 static bool done_first_init = false;
96 
97 extern int joystick_device;
98 
99 
100 
101 static default_t defaults[] =
102 {
103     {CFGT_Int,		"edge_version",		 &edge_version,	  0},
104     {CFGT_Int,		"screenwidth",		 &SCREENWIDTH,	  CFGDEF_SCREENWIDTH},
105     {CFGT_Int,		"screenheight",		 &SCREENHEIGHT,	  CFGDEF_SCREENHEIGHT},
106     {CFGT_Int,		"screendepth",		 &SCREENBITS,	  CFGDEF_SCREENBITS},
107     {CFGT_Boolean,	"fullscreen",		 &FULLSCREEN,	  CFGDEF_FULLSCREEN},
108     {CFGT_Boolean,	"directx",			 &force_directx,  0},
109     {CFGT_Boolean,	"waveout",			 &force_waveout,  0},
110     {CFGT_Int,      "usegamma",          &var_gamma,  CFGDEF_CURRENT_GAMMA},
111 
112     {CFGT_Int,      "sfx_volume",        &sfx_volume,     CFGDEF_SOUND_VOLUME},
113     {CFGT_Int,      "music_volume",      &mus_volume,     CFGDEF_MUSIC_VOLUME},
114     {CFGT_Int,      "music_device",      &var_music_dev,  CFGDEF_MUSIC_DEVICE},
115     {CFGT_Int,      "sample_rate",       &var_sample_rate,  CFGDEF_SAMPLE_RATE},
116     {CFGT_Int,      "sound_bits",        &var_sound_bits,   CFGDEF_SOUND_BITS},
117     {CFGT_Int,      "sound_stereo",      &var_sound_stereo, CFGDEF_SOUND_STEREO},
118     {CFGT_Int,      "mix_channels",      &var_mix_channels, CFGDEF_MIX_CHANNELS},
119     {CFGT_Int,      "quiet_factor",      &var_quiet_factor, CFGDEF_QUIET_FACTOR},
120     {CFGT_Int,      "timidity_quiet",    &var_timid_factor, CFGDEF_QUIET_FACTOR},
121 
122     {CFGT_Int,      "show_messages",     &showMessages,   CFGDEF_SHOWMESSAGES},
123 
124     // -ES- 1998/11/28 Save fade settings
125     {CFGT_Enum,     "telept_effect",     &telept_effect,  CFGDEF_TELEPT_EFFECT},
126     {CFGT_Int,      "telept_reverse",    &telept_reverse, CFGDEF_TELEPT_REVERSE},
127     {CFGT_Int,      "telept_flash",      &telept_flash,   CFGDEF_TELEPT_FLASH},
128     {CFGT_Int,      "invuln_fx",         &var_invul_fx,   CFGDEF_INVUL_FX},
129     {CFGT_Enum,     "wipe_method",       &wipe_method,    CFGDEF_WIPE_METHOD},
130     {CFGT_Int,      "wipe_reverse",      &wipe_reverse,   CFGDEF_WIPE_REVERSE},
131     {CFGT_Boolean,  "rotatemap",         &rotatemap,      CFGDEF_ROTATEMAP},
132     {CFGT_Boolean,  "respawnsetting",    &global_flags.res_respawn, CFGDEF_RES_RESPAWN},
133     {CFGT_Boolean,  "itemrespawn",       &global_flags.itemrespawn, CFGDEF_ITEMRESPAWN},
134     {CFGT_Boolean,  "respawn",           &global_flags.respawn, CFGDEF_RESPAWN},
135     {CFGT_Boolean,  "fastparm",          &global_flags.fastparm, CFGDEF_FASTPARM},
136     {CFGT_Int,      "grav",              &global_flags.menu_grav, CFGDEF_MENU_GRAV},
137     {CFGT_Boolean,  "true3dgameplay",    &global_flags.true3dgameplay, CFGDEF_TRUE3DGAMEPLAY},
138     {CFGT_Enum,     "autoaim",           &global_flags.autoaim, CFGDEF_AUTOAIM},
139     {CFGT_Int,      "doom_fading",       &doom_fading,    CFGDEF_DOOM_FADING},
140     {CFGT_Boolean,  "shootthru_scenery", &global_flags.pass_missile, CFGDEF_PASS_MISSILE},
141 
142     // -KM- 1998/07/21 Save the blood setting
143     {CFGT_Boolean,  "blood",             &global_flags.more_blood, CFGDEF_MORE_BLOOD},
144     {CFGT_Boolean,  "extra",             &global_flags.have_extra, CFGDEF_HAVE_EXTRA},
145     {CFGT_Boolean,  "shadows",           &global_flags.shadows, CFGDEF_SHADOWS},
146     {CFGT_Boolean,  "halos",             &global_flags.halos, 0},
147     {CFGT_Boolean,  "weaponkick",        &global_flags.kicking, CFGDEF_KICKING},
148     {CFGT_Boolean,  "weaponswitch",      &global_flags.weapon_switch, CFGDEF_WEAPON_SWITCH},
149     {CFGT_Boolean,  "mlook",             &global_flags.mlook, CFGDEF_MLOOK},
150     {CFGT_Boolean,  "jumping",           &global_flags.jump, CFGDEF_JUMP},
151     {CFGT_Boolean,  "crouching",         &global_flags.crouch, CFGDEF_CROUCH},
152     {CFGT_Int,      "mipmapping",        &var_mipmapping, CFGDEF_USE_MIPMAPPING},
153     {CFGT_Int,      "smoothing",         &var_smoothing,  CFGDEF_USE_SMOOTHING},
154     {CFGT_Boolean,  "dither",            &var_dithering, 0},
155     {CFGT_Int,      "dlights",           &use_dlights,    CFGDEF_USE_DLIGHTS},
156     {CFGT_Int,      "detail_level",      &detail_level,   CFGDEF_DETAIL_LEVEL},
157 	{CFGT_Int,      "hq2x_scaling",      &hq2x_scaling,   CFGDEF_HQ2X_SCALING},
158 
159     // -KM- 1998/09/01 Useless mouse/joy stuff removed,
160     //                 analogue binding added
161     {CFGT_Int,      "mouse_axis_x",      &mouse_xaxis,  CFGDEF_MOUSE_XAXIS},
162     {CFGT_Int,      "mouse_axis_y",      &mouse_yaxis,  CFGDEF_MOUSE_YAXIS},
163     {CFGT_Int,      "mouse_sens_x",      &mouse_xsens,  CFGDEF_MOUSESENSITIVITY},
164     {CFGT_Int,      "mouse_sens_y",      &mouse_ysens,  CFGDEF_MOUSESENSITIVITY},
165 
166     // -ACB- 1998/09/06 Two-stage turning & Speed controls added
167     {CFGT_Int,      "var_turnspeed",     &var_turnspeed,    CFGDEF_TURNSPEED},
168     {CFGT_Int,      "var_mlookspeed",    &var_mlookspeed,   CFGDEF_MLOOKSPEED},
169     {CFGT_Int,      "var_forwardspeed",  &var_forwardspeed, CFGDEF_FORWARDMOVESPEED},
170     {CFGT_Int,      "var_sidespeed",     &var_sidespeed,    CFGDEF_SIDEMOVESPEED},
171     {CFGT_Int,      "var_flyspeed",      &var_flyspeed,     CFGDEF_SIDEMOVESPEED},
172 
173     {CFGT_Int,      "joystick_device",   &joystick_device, 0},
174     {CFGT_Int,      "joy_axis1",         &joy_axis[0],    CFGDEF_JOY_XAXIS},
175     {CFGT_Int,      "joy_axis2",         &joy_axis[1],    CFGDEF_JOY_YAXIS},
176     {CFGT_Int,      "joy_axis3",         &joy_axis[2],    AXIS_DISABLE},
177     {CFGT_Int,      "joy_axis4",         &joy_axis[3],    AXIS_DISABLE},
178     {CFGT_Int,      "joy_axis5",         &joy_axis[4],    AXIS_DISABLE},
179     {CFGT_Int,      "joy_axis6",         &joy_axis[5],    AXIS_DISABLE},
180 
181     {CFGT_Int,      "monitor_size",      &monitor_size,   0},
182     {CFGT_Int,      "screen_hud",        &screen_hud,     CFGDEF_SCREEN_HUD},
183     {CFGT_Int,      "save_page",         &save_page, 0},
184     {CFGT_Boolean,  "png_scrshots",      &png_scrshots,   CFGDEF_PNG_SCRSHOTS},
185 
186 	// -------------------- VARS --------------------
187 
188 	{CFGT_Boolean,  "var_obituaries",    &var_obituaries, 1},
189 
190 	// -------------------- KEYS --------------------
191 
192     {CFGT_Key,      "key_right",         &key_right,      CFGDEF_KEY_RIGHT},
193     {CFGT_Key,      "key_left",          &key_left,       CFGDEF_KEY_LEFT},
194     {CFGT_Key,      "key_up",            &key_up,         CFGDEF_KEY_UP},
195     {CFGT_Key,      "key_down",          &key_down,       CFGDEF_KEY_DOWN},
196     {CFGT_Key,      "key_lookup",        &key_lookup,     CFGDEF_KEY_LOOKUP},
197     {CFGT_Key,      "key_lookdown",      &key_lookdown,   CFGDEF_KEY_LOOKDOWN},
198     {CFGT_Key,      "key_lookcenter",    &key_lookcenter, CFGDEF_KEY_LOOKCENTER},
199 
200     // -ES- 1999/03/28 Zoom Key
201     {CFGT_Key,      "key_zoom",          &key_zoom,        CFGDEF_KEY_ZOOM},
202     {CFGT_Key,      "key_strafeleft",    &key_strafeleft,  CFGDEF_KEY_STRAFELEFT},
203     {CFGT_Key,      "key_straferight",   &key_straferight, CFGDEF_KEY_STRAFERIGHT},
204 
205     // -ACB- for -MH- 1998/07/02 Flying Keys
206     {CFGT_Key,      "key_flyup",         &key_flyup,      CFGDEF_KEY_FLYUP},
207     {CFGT_Key,      "key_flydown",       &key_flydown,    CFGDEF_KEY_FLYDOWN},
208 
209     {CFGT_Key,      "key_fire",          &key_fire,       CFGDEF_KEY_FIRE},
210     {CFGT_Key,      "key_use",           &key_use,        CFGDEF_KEY_USE},
211     {CFGT_Key,      "key_strafe",        &key_strafe,     CFGDEF_KEY_STRAFE},
212     {CFGT_Key,      "key_speed",         &key_speed,      CFGDEF_KEY_SPEED},
213     {CFGT_Key,      "key_autorun",       &key_autorun,    CFGDEF_KEY_AUTORUN},
214     {CFGT_Key,      "key_nextweapon",    &key_nextweapon, CFGDEF_KEY_NEXTWEAPON},
215     {CFGT_Key,      "key_prevweapon",    &key_prevweapon, CFGDEF_KEY_PREVWEAPON},
216 
217     {CFGT_Key,      "key_180",           &key_180,        CFGDEF_KEY_180},
218     {CFGT_Key,      "key_map",           &key_map,        CFGDEF_KEY_MAP},
219     {CFGT_Key,      "key_talk",          &key_talk,       CFGDEF_KEY_TALK},
220     {CFGT_Key,      "key_console",       &key_console,    CFGDEF_KEY_CONSOLE},  // -AJA- 2007/08/15.
221     {CFGT_Key,      "key_pause",         &key_pause,      KEYD_PAUSE},          // -AJA- 2010/06/13.
222 
223     {CFGT_Key,      "key_mlook",         &key_mlook,      CFGDEF_KEY_MLOOK},  // -AJA- 1999/07/27.
224     {CFGT_Key,      "key_secondatk",     &key_secondatk,  CFGDEF_KEY_SECONDATK},  // -AJA- 2000/02/08.
225     {CFGT_Key,      "key_reload",        &key_reload,     CFGDEF_KEY_RELOAD},  // -AJA- 2004/11/11.
226     {CFGT_Key,      "key_action1",       &key_action1,    CFGDEF_KEY_ACTION1},  // -AJA- 2009/09/07
227     {CFGT_Key,      "key_action2",       &key_action2,    CFGDEF_KEY_ACTION2},  // -AJA- 2009/09/07
228 
229 	// -AJA- 2010/06/13: weapon and automap keys
230 	{CFGT_Key,      "key_weapon1",       &key_weapons[1], '1'},
231 	{CFGT_Key,      "key_weapon2",       &key_weapons[2], '2'},
232 	{CFGT_Key,      "key_weapon3",       &key_weapons[3], '3'},
233 	{CFGT_Key,      "key_weapon4",       &key_weapons[4], '4'},
234 	{CFGT_Key,      "key_weapon5",       &key_weapons[5], '5'},
235 	{CFGT_Key,      "key_weapon6",       &key_weapons[6], '6'},
236 	{CFGT_Key,      "key_weapon7",       &key_weapons[7], '7'},
237 	{CFGT_Key,      "key_weapon8",       &key_weapons[8], '8'},
238 	{CFGT_Key,      "key_weapon9",       &key_weapons[9], '9'},
239 	{CFGT_Key,      "key_weapon0",       &key_weapons[0], '0'},
240 
241 	{CFGT_Key,      "key_am_up",         &key_am_up,      KEYD_UPARROW},
242 	{CFGT_Key,      "key_am_down",       &key_am_down,    KEYD_DOWNARROW},
243 	{CFGT_Key,      "key_am_left",       &key_am_left,    KEYD_LEFTARROW},
244 	{CFGT_Key,      "key_am_right",      &key_am_right,   KEYD_RIGHTARROW},
245 	{CFGT_Key,      "key_am_zoomin",     &key_am_zoomin,  '='},
246 	{CFGT_Key,      "key_am_zoomout",    &key_am_zoomout, '-'},
247 	{CFGT_Key,      "key_am_follow",     &key_am_follow,  'f'},
248 	{CFGT_Key,      "key_am_grid",       &key_am_grid,    'g'},
249 	{CFGT_Key,      "key_am_mark",       &key_am_mark,    'm'},
250 	{CFGT_Key,      "key_am_clear",      &key_am_clear,   'c'},
251 };
252 
253 
M_SaveDefaults(void)254 void M_SaveDefaults(void)
255 {
256 	edge_version = EDGEVER;
257 
258 	int numdefaults = sizeof(defaults) / sizeof(defaults[0]);
259 
260 	// -ACB- 1999/09/24 idiot proof checking as required by MSVC
261 	SYS_ASSERT(! cfgfile.empty());
262 
263 	FILE *f = fopen(cfgfile.c_str(), "w");
264 	if (!f)
265 	{
266 		I_Warning("Couldn't open config file %s for writing.", cfgfile.c_str());
267 		return;  // can't write the file, but don't complain
268 	}
269 
270 	// console variables
271 	for (int k = 0; all_cvars[k].name; k++)
272 	{
273 		cvar_c *var = all_cvars[k].var;
274 
275 		if (strchr(all_cvars[k].flags, 'c'))
276 			fprintf(f, "/%s\t\"%s\"\n", all_cvars[k].name, var->str);
277 	}
278 
279 	// normal variables
280 	for (int i = 0; i < numdefaults; i++)
281 	{
282 		int v;
283 
284 		switch (defaults[i].type)
285 		{
286 			case CFGT_Int:
287 				fprintf(f, "%s\t\t%i\n", defaults[i].name, *(int*)defaults[i].location);
288 				break;
289 
290 			case CFGT_Boolean:
291 				fprintf(f, "%s\t\t%i\n", defaults[i].name, *(bool*)defaults[i].location ?1:0);
292 				break;
293 
294 			case CFGT_Key:
295 				v = *(int*)defaults[i].location;
296 				fprintf(f,  "%s\t\t0x%X\n", defaults[i].name, v);
297 				break;
298 		}
299 	}
300 
301 	fclose(f);
302 }
303 
304 
SetToBaseValue(default_t * def)305 static void SetToBaseValue(default_t *def)
306 {
307 	switch (def->type)
308 	{
309 		case CFGT_Int:
310 		case CFGT_Key:
311 			*(int*)(def->location) = def->defaultvalue;
312 			break;
313 
314 		case CFGT_Boolean:
315 			*(bool*)(def->location) = def->defaultvalue?true:false;
316 			break;
317 	}
318 }
319 
M_ResetDefaults(int _dummy)320 void M_ResetDefaults(int _dummy)
321 {
322 	int numdefaults = sizeof(defaults) / sizeof(defaults[0]);
323 
324 	for (int i = 0; i < numdefaults; i++)
325 	{
326 		// don't reset the first five entries except at startup
327 		if (done_first_init && i < 5)
328 			continue;
329 
330 		SetToBaseValue(defaults + i);
331 	}
332 
333 	done_first_init = true;
334 }
335 
336 
M_LoadDefaults(void)337 void M_LoadDefaults(void)
338 {
339 	int i;
340 
341 	// set everything to base values
342 	int numdefaults = sizeof(defaults) / sizeof(defaults[0]);
343 
344 	M_ResetDefaults(0);
345 
346 	I_Printf("M_LoadDefaults from %s\n", cfgfile.c_str());
347 
348 	// read the file in, overriding any set defaults
349 	FILE *f = fopen(cfgfile.c_str(), "r");
350 
351 	if (! f)
352 	{
353 		I_Warning("Couldn't open config file %s for reading.\n", cfgfile.c_str());
354 		I_Warning("Resetting config to RECOMMENDED values...\n");
355 		return;
356 	}
357 
358 	while (!feof(f))
359 	{
360 		char def[80];
361 		char strparm[100];
362 
363 		int parm;
364 
365 		std::string newstr;
366 		bool isstring = false;
367 
368 		if (fscanf(f, "%79s %[^\n]\n", def, strparm) != 2)
369 			continue;
370 
371 		// console var?
372 		if (def[0] == '/')
373 		{
374 			std::string con_line;
375 
376 			con_line += (def+1);
377 			con_line += " ";
378 			con_line += strparm;
379 
380 			CON_TryCommand(con_line.c_str());
381 			continue;
382 		}
383 
384 		if (strparm[0] == '"')
385 		{
386 			// get a string default
387 			isstring = true;
388 			// overwrite the last "
389 			strparm[strlen(strparm) - 1] = 0;
390 			// skip the first "
391 			newstr = std::string(strparm + 1);
392 		}
393 		else if (strparm[0] == '0' && strparm[1] == 'x')
394 			sscanf(strparm + 2, "%x", &parm);
395 		else
396 			sscanf(strparm, "%i", &parm);
397 
398 		for (i = 0; i < numdefaults; i++)
399 		{
400 			if (0 == strcmp(def, defaults[i].name))
401 			{
402 				if (defaults[i].type == CFGT_Boolean)
403 				{
404 					*(bool*)defaults[i].location = parm?true:false;
405 				}
406 				else /* CFGT_Int and CFGT_Key */
407 				{
408 					*(int*)defaults[i].location = parm;
409 				}
410 				break;
411 			}
412 		}
413 	}
414 
415 	fclose(f);
416 
417 	if (edge_version == 0)
418 	{
419 		// config file is from an older version (< 1.31)
420 		// Hence fix some things up here...
421 
422 		key_console = KEYD_TILDE;
423 	}
424 
425 	return;
426 }
427 
428 
M_InitMiscConVars(void)429 void M_InitMiscConVars(void)
430 {
431 	if (M_CheckParm("-hqscale") || M_CheckParm("-hqall"))
432 		hq2x_scaling = 3;
433 	else if (M_CheckParm("-nohqscale"))
434 		hq2x_scaling = 0;
435 }
436 
437 
M_DisplayDisk(void)438 void M_DisplayDisk(void)
439 {
440 	/* displays disk icon during loading... */
441 
442 	if (!m_diskicon.d || !display_disk)
443 		return;
444 
445 	if (!disk_image)
446 		disk_image = W_ImageLookup("STDISK");
447 
448 	// reset flag
449 	display_disk = false;
450 
451 	float w = IM_WIDTH(disk_image);
452 	float h = IM_HEIGHT(disk_image);
453 
454 	HUD_StretchImage(314 - w, 164 - h, w, h, disk_image);
455 }
456 
457 
458 #define PIXEL_RED(pix)  (playpal_data[0][pix][0])
459 #define PIXEL_GRN(pix)  (playpal_data[0][pix][1])
460 #define PIXEL_BLU(pix)  (playpal_data[0][pix][2])
461 
462 
M_ScreenShot(bool show_msg)463 void M_ScreenShot(bool show_msg)
464 {
465 	const char *extension;
466 
467     if (png_scrshots)
468 		extension = "png";
469 	else
470 		extension = "jpg";
471 
472 	std::string fn;
473 
474 	// find a file name to save it to
475 	for (int i = 1; i <= 9999; i++)
476 	{
477 		std::string base(epi::STR_Format("shot%02d.%s", i, extension));
478 
479 		fn = epi::PATH_Join(shot_dir.c_str(), base.c_str());
480 
481 		if (! epi::FS_Access(fn.c_str(), epi::file_c::ACCESS_READ))
482         {
483 			break; // file doesn't exist
484         }
485 	}
486 
487 	FILE *fp = fopen(fn.c_str(), "wb");
488 	if (fp == NULL)
489 	{
490 		if (show_msg)
491 			I_Printf("Unable to create file: %s\n", fn.c_str());
492 
493 		return;
494 	}
495 
496 	epi::image_data_c *img = new epi::image_data_c(SCREENWIDTH, SCREENHEIGHT, 3);
497 
498 	RGL_ReadScreen(0, 0, SCREENWIDTH, SCREENHEIGHT, img->PixelAt(0,0));
499 
500 	bool result;
501     if (png_scrshots)
502         result = epi::PNG_Save(fp, img);
503     else
504         result = epi::JPEG_Save(fp, img);
505 
506 	if (show_msg)
507 	{
508 		if (result)
509 			I_Printf("Captured to file: %s\n", fn.c_str());
510 		else
511 			I_Printf("Error saving file: %s\n", fn.c_str());
512 	}
513 
514 	delete img;
515 
516 	fclose(fp);
517 }
518 
519 
M_MakeSaveScreenShot(void)520 void M_MakeSaveScreenShot(void)
521 {
522 #if 0 /// FIXME:
523 	// byte* buffer = new byte[SCREENWIDTH*SCREENHEIGHT*4];
524 	// glReadBuffer(GL_FRONT);
525 	// glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
526 	// glReadPixels(0, 0, SCREENWIDTH, SCREENHEIGHT, GL_RGB, GL_UNSIGNED_BYTE, buffer);
527 	// ...
528 	// delete [] buffer;
529 #endif
530 
531 #if 0  // OLD SOFTWARE VERSION
532 	int x, y;
533 	int ax, ay;
534 
535 	byte pixel;
536 	unsigned short rgb;
537 	truecol_info_t colinfo;
538 
539 	save_screenshot_valid = true;
540 
541 	I_GetTruecolInfo(&colinfo);
542 
543 	switch (main_scr->bytepp)
544 	{
545 		case 1:
546 		{
547 			byte *top = (byte *) main_scr->data;
548 
549 			top += viewwindowy * main_scr->pitch + viewwindowx;
550 
551 			for (y=0; y < 100; y++)
552 				for (x=0; x < 160; x++)
553 				{
554 					ax = x * viewwindowwidth  / 160;
555 					ay = y * viewwindowheight / 100;
556 
557 					SYS_ASSERT(0 <= ax && ax < SCREENWIDTH);
558 					SYS_ASSERT(0 <= ay && ay < SCREENHEIGHT);
559 
560 					pixel = top[ay * main_scr->pitch + ax];
561 
562 					rgb = ((PIXEL_RED(pixel) & 0xF8) << 7) |
563 						((PIXEL_GRN(pixel) & 0xF8) << 2) |
564 						((PIXEL_BLU(pixel) & 0xF8) >> 3);
565 
566 					save_screenshot[x][y] = rgb;
567 				}
568 		}
569 		break;
570 
571 		case 2:
572 		{
573 			unsigned short *top = (unsigned short *) main_scr->data;
574 
575 			top += viewwindowy * main_scr->pitch/2 + viewwindowx;
576 
577 			for (y=0; y < 100; y++)
578 				for (x=0; x < 160; x++)
579 				{
580 					ax = x * viewwindowwidth  / 160;
581 					ay = y * viewwindowheight / 100;
582 
583 					SYS_ASSERT(0 <= ax && ax < SCREENWIDTH);
584 					SYS_ASSERT(0 <= ay && ay < SCREENHEIGHT);
585 
586 					rgb = top[ay * main_scr->pitch/2 + ax];
587 
588 					// hack !
589 					if (colinfo.green_bits == 6)
590 						rgb = ((rgb & 0xFFC0) >> 1) | (rgb & 0x001F);
591 
592 					save_screenshot[x][y] = rgb;
593 				}
594 		}
595 		break;
596 	}
597 #endif
598 }
599 
600 //
601 // Creates the file name "dir/file", or
602 // just "file" in the given string if it
603 // was an absolute address.
604 //
M_ComposeFileName(const char * dir,const char * file)605 std::string M_ComposeFileName(const char *dir, const char *file)
606 {
607 	if (epi::PATH_IsAbsolute(file))
608 		return std::string(file);
609 
610 	return epi::PATH_Join(dir, file);
611 }
612 
613 
M_OpenComposedEPIFile(const char * dir,const char * file)614 epi::file_c *M_OpenComposedEPIFile(const char *dir, const char *file)
615 {
616 	std::string fullname = M_ComposeFileName(dir, file);
617 
618 	return epi::FS_Open(fullname.c_str(),
619 		epi::file_c::ACCESS_READ | epi::file_c::ACCESS_BINARY);
620 }
621 
622 //
623 // Loads file into memory. This sets a pointer to the data and
624 // the length.
625 //
626 // NOTE: The data must be freed by delete[] when not used.
627 //
628 // Returns NULL on failure.
629 //
630 // -ACB- 2000/01/08 Written
631 // -ES-  2000/06/12 Now returns the allocated pointer, or NULL on failure.
632 //
M_GetFileData(const char * filename,int * length)633 byte* M_GetFileData(const char *filename, int *length)
634 {
635 	FILE *lumpfile;
636 	byte *data;
637 
638 	// Sanity Checks..
639 	SYS_ASSERT(filename);
640 	SYS_ASSERT(length);
641 
642 	lumpfile = fopen(filename, "rb");
643 	if (!lumpfile)
644 	{
645 		I_Warning("M_GetFileData: Cannot open '%s'\n", filename);
646 		return NULL;
647 	}
648 
649 	fseek(lumpfile, 0, SEEK_END);                   // get the end of the file
650 	(*length) = ftell(lumpfile);                    // get the size
651 	fseek(lumpfile, 0, SEEK_SET);                   // reset to beginning
652 
653 	data = new byte[*length];						// malloc the size
654 	fread(data, sizeof(char), (*length), lumpfile); // read file
655 	fclose(lumpfile);                               // close the file
656 
657 	return data;
658 }
659 
660 
M_WarnError(const char * error,...)661 void M_WarnError(const char *error,...)
662 {
663 	// Either displays a warning or produces a fatal error, depending
664 	// on whether the "-strict" option is used.
665 
666 	char message_buf[4096];
667 
668 	message_buf[4095] = 0;
669 
670 	va_list argptr;
671 
672 	va_start(argptr, error);
673 	vsprintf(message_buf, error, argptr);
674 	va_end(argptr);
675 
676 	// I hope nobody is printing strings longer than 4096 chars...
677 	SYS_ASSERT(message_buf[4095] == 0);
678 
679 	if (strict_errors)
680 		I_Error("%s", message_buf);
681 	else if (! no_warnings)
682 		I_Warning("%s", message_buf);
683 }
684 
685 
686 extern FILE *debugfile; // FIXME
687 
I_Debugf(const char * message,...)688 void I_Debugf(const char *message,...)
689 {
690 	// Write into the debug file.
691 	//
692 	// -ACB- 1999/09/22: From #define to Procedure
693 	// -AJA- 2001/02/07: Moved here from platform codes.
694 	//
695 	if (!debugfile)
696 		return;
697 
698 	char message_buf[4096];
699 
700 	message_buf[4095] = 0;
701 
702 	// Print the message into a text string
703 	va_list argptr;
704 
705 	va_start(argptr, message);
706 	vsprintf(message_buf, message, argptr);
707 	va_end(argptr);
708 
709 	// I hope nobody is printing strings longer than 4096 chars...
710 	SYS_ASSERT(message_buf[4095] == 0);
711 
712 	fprintf(debugfile, "%s", message_buf);
713 	fflush(debugfile);
714 }
715 
716 
717 extern FILE *logfile; // FIXME: make file_c and unify with debugfile
718 
I_Logf(const char * message,...)719 void I_Logf(const char *message,...)
720 {
721 	if (!logfile)
722 		return;
723 
724 	char message_buf[4096];
725 
726 	message_buf[4095] = 0;
727 
728 	// Print the message into a text string
729 	va_list argptr;
730 
731 	va_start(argptr, message);
732 	vsprintf(message_buf, message, argptr);
733 	va_end(argptr);
734 
735 	// I hope nobody is printing strings longer than 4096 chars...
736 	SYS_ASSERT(message_buf[4095] == 0);
737 
738 	fprintf(logfile, "%s", message_buf);
739 	fflush(logfile);
740 }
741 
742 
743 //
744 // Just like L_CompareTimeStamps above, but give the filenames.
745 //
L_CompareFileTimes(const char * A,const char * B)746 int L_CompareFileTimes(const char *A, const char *B)
747 {
748 	epi::timestamp_c A_time;
749 	epi::timestamp_c B_time;
750 
751 	if (! FS_GetModifiedTime(A, A_time))
752 		I_Error("AddFile: I_GetModifiedTime failed on %s\n", A);
753 
754 	if (! FS_GetModifiedTime(B, B_time))
755 		I_Error("AddFile: I_GetModifiedTime failed on %s\n", B);
756 
757 	return A_time.Cmp(B_time);
758 }
759 
760 
761 //--- editor settings ---
762 // vi:ts=4:sw=4:noexpandtab
763