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