1 /* Emacs style mode select   -*- C++ -*-
2  *-----------------------------------------------------------------------------
3  *
4  *
5  *  PrBoom: a Doom port merged with LxDoom and LSDLDoom
6  *  based on BOOM, a modified and improved DOOM engine
7  *  Copyright (C) 1999 by
8  *  id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9  *  Copyright (C) 1999-2000 by
10  *  Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11  *  Copyright 2005, 2006 by
12  *  Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13  *
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public License
16  *  as published by the Free Software Foundation; either version 2
17  *  of the License, or (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27  *  02111-1307, USA.
28  *
29  * DESCRIPTION:
30  *
31  *-----------------------------------------------------------------------------
32  */
33 
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37 #ifdef _WIN32
38 #define WIN32_LEAN_AND_MEAN
39 #include <windows.h>
40 #include <direct.h>
41 #include <winreg.h>
42 #endif
43 #ifdef GL_DOOM
44 #include <SDL_opengl.h>
45 #endif
46 #include <string.h>
47 #include <math.h>
48 
49 #include <stdio.h>
50 #include <stdarg.h>
51 #include <stdlib.h>
52 
53 #include "SDL.h"
54 #ifdef _WIN32
55 #include <SDL_syswm.h>
56 #endif
57 
58 #include "hu_lib.h"
59 
60 #include "doomtype.h"
61 #include "doomstat.h"
62 #include "d_main.h"
63 #include "s_sound.h"
64 #include "i_system.h"
65 #include "i_main.h"
66 #include "i_sound.h"
67 #include "m_menu.h"
68 #include "lprintf.h"
69 #include "m_argv.h"
70 #include "m_misc.h"
71 #include "i_system.h"
72 #include "p_maputl.h"
73 #include "p_map.h"
74 #include "i_video.h"
75 #include "info.h"
76 #include "r_screenmultiply.h"
77 #include "r_main.h"
78 #include "r_things.h"
79 #include "am_map.h"
80 #include "hu_tracers.h"
81 #ifdef GL_DOOM
82 #include "gl_struct.h"
83 #include "gl_intern.h"
84 #endif
85 #include "g_game.h"
86 #include "r_demo.h"
87 #include "e6y.h"
88 
89 dboolean wasWiped = false;
90 
91 int secretfound;
92 int messagecenter_counter;
93 int demo_skiptics;
94 int demo_playerscount;
95 int demo_tics_count;
96 int demo_curr_tic;
97 char demo_len_st[80];
98 
99 int avi_shot_time;
100 int avi_shot_num;
101 const char *avi_shot_fname;
102 char avi_shot_curr_fname[PATH_MAX];
103 
104 dboolean doSkip;
105 dboolean demo_stoponnext;
106 dboolean demo_stoponend;
107 dboolean demo_warp;
108 
109 int key_speed_up;
110 int key_speed_down;
111 int key_speed_default;
112 int speed_step;
113 int key_level_restart;
114 int key_nextlevel;
115 int key_demo_jointogame;
116 int key_demo_endlevel;
117 int key_demo_skip;
118 int key_walkcamera;
119 int key_showalive;
120 
121 int hudadd_gamespeed;
122 int hudadd_leveltime;
123 int hudadd_demotime;
124 int hudadd_secretarea;
125 int hudadd_smarttotals;
126 int hudadd_demoprogressbar;
127 int movement_strafe50;
128 int movement_shorttics;
129 int movement_strafe50onturns;
130 int movement_mouselook;
131 int movement_mouseinvert;
132 int movement_maxviewpitch;
133 int mouse_handler;
134 int mouse_doubleclick_as_use;
135 int render_fov;
136 int render_multisampling;
137 int render_paperitems;
138 int render_wipescreen;
139 int mouse_acceleration;
140 int demo_overwriteexisting;
141 
142 int showendoom;
143 
144 int palette_ondamage;
145 int palette_onbonus;
146 int palette_onpowers;
147 
148 float mouse_accelfactor;
149 
150 camera_t walkcamera;
151 
152 hu_textline_t  w_hudadd;
153 hu_textline_t  w_centermsg;
154 hu_textline_t  w_precache;
155 char hud_add[80];
156 char hud_centermsg[80];
157 
158 fixed_t sidemove_normal[2]    = {0x18, 0x28};
159 fixed_t sidemove_strafe50[2]    = {0x19, 0x32};
160 
161 int mouseSensitivity_mlook;
162 angle_t viewpitch;
163 float skyscale;
164 float screen_skybox_zplane;
165 float tan_pitch;
166 float skyUpAngle;
167 float skyUpShift;
168 float skyXShift;
169 float skyYShift;
170 dboolean mlook_or_fov;
171 
172 int maxViewPitch;
173 int minViewPitch;
174 
175 #ifdef _WIN32
WINError(void)176 const char* WINError(void)
177 {
178   static char *WinEBuff = NULL;
179   DWORD err = GetLastError();
180   char *ch;
181 
182   if (WinEBuff)
183   {
184     LocalFree(WinEBuff);
185   }
186 
187   if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
188     NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
189     (LPTSTR) &WinEBuff, 0, NULL) == 0)
190   {
191     return "Unknown error";
192   }
193 
194   if ((ch = strchr(WinEBuff, '\n')) != 0)
195     *ch = 0;
196   if ((ch = strchr(WinEBuff, '\r')) != 0)
197     *ch = 0;
198 
199   return WinEBuff;
200 }
201 #endif
202 
203 //--------------------------------------------------
204 #ifdef _WIN32
205 HWND WIN32_GetHWND(void);
206 #endif
207 //--------------------------------------------------
208 
e6y_assert(const char * format,...)209 void e6y_assert(const char *format, ...)
210 {
211   static FILE *f = NULL;
212   va_list argptr;
213   va_start(argptr,format);
214   //if (!f)
215     f = fopen("d:\\a.txt", "ab+");
216   vfprintf(f, format, argptr);
217   fclose(f);
218   va_end(argptr);
219 }
220 
221 /* ParamsMatchingCheck
222  * Conflicting command-line parameters could cause the engine to be confused
223  * in some cases. Added checks to prevent this.
224  * Example: glboom.exe -record mydemo -playdemo demoname
225  */
ParamsMatchingCheck()226 void ParamsMatchingCheck()
227 {
228   dboolean recording_attempt =
229     M_CheckParm("-record") ||
230     M_CheckParm("-recordfrom") ||
231     M_CheckParm("-recordfromto");
232 
233   dboolean playbacking_attempt =
234     M_CheckParm("-playdemo") ||
235     M_CheckParm("-timedemo") ||
236     M_CheckParm("-fastdemo");
237 
238   if (recording_attempt && playbacking_attempt)
239     I_Error("Params are not matching: Can not being played back and recorded at the same time.");
240 }
241 
242 prboom_comp_t prboom_comp[PC_MAX] = {
243   {0xffffffff, 0x02020615, 0, "-force_monster_avoid_hazards"},
244   {0x00000000, 0x02040601, 0, "-force_remove_slime_trails"},
245   {0x02020200, 0x02040801, 0, "-force_no_dropoff"},
246   {0x00000000, 0x02040801, 0, "-force_truncated_sector_specials"},
247   {0x00000000, 0x02040802, 0, "-force_boom_brainawake"},
248   {0x00000000, 0x02040802, 0, "-force_prboom_friction"},
249   {0x02020500, 0x02040000, 0, "-reject_pad_with_ff"},
250   {0xffffffff, 0x02040802, 0, "-force_lxdoom_demo_compatibility"},
251   {0x00000000, 0x0202061b, 0, "-allow_ssg_direct"},
252   {0x00000000, 0x02040601, 0, "-treat_no_clipping_things_as_not_blocking"},
253   {0x00000000, 0x02040803, 0, "-force_incorrect_processing_of_respawn_frame_entry"},
254   {0x00000000, 0x02040601, 0, "-force_correct_code_for_3_keys_doors_in_mbf"},
255   {0x00000000, 0x02040601, 0, "-uninitialize_crush_field_for_stairs"},
256   {0x00000000, 0x02040802, 0, "-force_boom_findnexthighestfloor"},
257   {0x00000000, 0x02040802, 0, "-allow_sky_transfer_in_boom"},
258   {0x00000000, 0x02040803, 0, "-apply_green_armor_class_to_armor_bonuses"},
259   {0x00000000, 0x02040803, 0, "-apply_blue_armor_class_to_megasphere"},
260   {0x02050001, 0x02050003, 0, "-wrong_fixeddiv"},
261   {0x02020200, 0x02050003, 0, "-force_incorrect_bobbing_in_boom"},
262   {0xffffffff, 0x00000000, 0, "-boom_deh_parser"},
263   {0x00000000, 0x02050007, 0, "-mbf_remove_thinker_in_killmobj"},
264   {0x00000000, 0x02050007, 0, "-do_not_inherit_friendlyness_flag_on_spawn"},
265   {0x00000000, 0x02050007, 0, "-do_not_use_misc12_frame_parameters_in_a_mushroom"},
266   {0x00000000, 0x02050102, 0, "-apply_mbf_codepointers_to_any_complevel"},
267 };
268 
269 dboolean *use_wrong_fixeddiv;
e6y_InitCommandLine(void)270 void e6y_InitCommandLine(void)
271 {
272   int p;
273 
274   if ((p = M_CheckParm("-skipsec")) && (p < myargc-1))
275     demo_skiptics = (int)(atof(myargv[p + 1]) * 35);
276   if ((IsDemoPlayback() || IsDemoContinue()) && (startmap > 1 || demo_skiptics))
277     G_SkipDemoStart();
278   if ((p = M_CheckParm("-avidemo")) && (p < myargc-1))
279     avi_shot_fname = myargv[p + 1];
280   stats_level = M_CheckParm("-levelstat");
281 
282   // TAS-tracers
283   InitTracers();
284 
285   shorttics = movement_shorttics || M_CheckParm("-shorttics");
286 
287   // What hacked exe are we emulating?
288   game_exe = EXE_NONE;
289   if ((p = M_CheckParm("-exe")) && (p < myargc-1))
290   {
291     if (!strcasecmp(myargv[p + 1], "chex") || !strcasecmp(myargv[p + 1], "chex.exe"))
292     {
293       game_exe = EXE_CHEX;
294     }
295   }
296 }
297 
298 static dboolean saved_fastdemo;
299 static dboolean saved_nodrawers;
300 static dboolean saved_nosfxparm;
301 static dboolean saved_nomusicparm;
302 static int saved_render_precise;
303 
G_SkipDemoStart(void)304 void G_SkipDemoStart(void)
305 {
306   saved_fastdemo = fastdemo;
307   saved_nodrawers = nodrawers;
308   saved_nosfxparm = nosfxparm;
309   saved_nomusicparm = nomusicparm;
310   saved_render_precise = render_precise;
311 
312   paused = false;
313 
314   doSkip = true;
315 
316   S_StopMusic();
317   fastdemo = true;
318   nodrawers = true;
319   nosfxparm = true;
320   nomusicparm = true;
321 
322   render_precise = false;
323   M_ChangeRenderPrecise();
324 
325   I_Init2();
326 }
327 
328 dboolean sound_inited_once = false;
329 
G_SkipDemoStop(void)330 void G_SkipDemoStop(void)
331 {
332   fastdemo = saved_fastdemo;
333   nodrawers = saved_nodrawers;
334   nosfxparm = saved_nosfxparm;
335   nomusicparm = saved_nomusicparm;
336 
337   render_precise = saved_render_precise;
338   M_ChangeRenderPrecise();
339 
340   demo_stoponnext = false;
341   demo_stoponend = false;
342   demo_warp = false;
343   doSkip = false;
344   demo_skiptics = 0;
345   startmap = 0;
346 
347   I_Init2();
348   if (!sound_inited_once && !(nomusicparm && nosfxparm))
349   {
350     I_InitSound();
351   }
352   S_Init(snd_SfxVolume, snd_MusicVolume);
353   S_Stop();
354   S_RestartMusic();
355 
356 #ifdef GL_DOOM
357   if (V_GetMode() == VID_MODEGL) {
358     gld_PreprocessLevel();
359   }
360 #endif
361 }
362 
G_SkipDemoCheck(void)363 void G_SkipDemoCheck(void)
364 {
365   if (doSkip && gametic > 0)
366   {
367     if (((startmap <= 1) &&
368          (gametic > demo_skiptics + (demo_skiptics > 0 ? 0 : demo_tics_count))) ||
369         (demo_warp && gametic - levelstarttic > demo_skiptics))
370      {
371        G_SkipDemoStop();
372      }
373   }
374 }
375 
G_ReloadLevel(void)376 int G_ReloadLevel(void)
377 {
378   int result = false;
379 
380   if ((gamestate == GS_LEVEL) &&
381       !deathmatch && !netgame &&
382       !demorecording && !demoplayback &&
383       !menuactive)
384   {
385     G_DeferedInitNew(gameskill, gameepisode, gamemap);
386     result = true;
387   }
388 
389   return result;
390 }
391 
G_GotoNextLevel(void)392 int G_GotoNextLevel(void)
393 {
394   static byte doom2_next[32] = {
395     2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
396     12, 13, 14, 15, 31, 17, 18, 19, 20, 21,
397     22, 23, 24, 25, 26, 27, 28, 29, 30, 1,
398     32, 16
399   };
400   static byte doom_next[4][9] = {
401     {12, 13, 19, 15, 16, 17, 18, 21, 14},
402     {22, 23, 24, 25, 29, 27, 28, 31, 26},
403     {32, 33, 34, 35, 36, 39, 38, 41, 37},
404     {42, 49, 44, 45, 46, 47, 48, 11, 43}
405   };
406 
407   int changed = false;
408 
409   // secret level
410   doom2_next[14] = (haswolflevels ? 31 : 16);
411 
412   // shareware doom has only episode 1
413   doom_next[0][7] = (gamemode == shareware ? 11 : 21);
414 
415   doom_next[2][7] = ((gamemode == registered) ||
416     // the fourth episode for pre-ultimate complevels is not allowed.
417     (compatibility_level < ultdoom_compatibility) ?
418     11 : 41);
419 
420   if ((gamestate == GS_LEVEL) &&
421       !deathmatch && !netgame &&
422       !demorecording && !demoplayback &&
423       !menuactive)
424   {
425     //doom2_next and doom_next are 0 biased, unlike gameepisode and gamemap
426     int epsd = gameepisode - 1;
427     int map = gamemap - 1;
428 
429     if (gamemode == commercial)
430     {
431       epsd = 1;
432       map = doom2_next[BETWEEN(0, 31, map)];
433     }
434     else
435     {
436       int next = doom_next[BETWEEN(0, 3, epsd)][BETWEEN(0, 9, map)];
437       epsd = next / 10;
438       map = next % 10;
439     }
440 
441     G_DeferedInitNew(gameskill, epsd, map);
442     changed = true;
443   }
444 
445   return changed;
446 }
447 
M_ChangeSpeed(void)448 void M_ChangeSpeed(void)
449 {
450   extern int sidemove[2];
451 
452   if(movement_strafe50)
453   {
454     sidemove[0] = sidemove_strafe50[0];
455     sidemove[1] = sidemove_strafe50[1];
456   }
457   else
458   {
459     movement_strafe50onturns = false;
460     sidemove[0] = sidemove_normal[0];
461     sidemove[1] = sidemove_normal[1];
462   }
463 }
464 
465 #ifdef GL_DOOM
M_ChangeMouseLook(void)466 void M_ChangeMouseLook(void)
467 {
468   viewpitch = 0;
469 
470   if (gl_skymode == skytype_auto)
471     gl_drawskys = (movement_mouselook ? skytype_skydome : skytype_standard);
472   else
473     gl_drawskys = gl_skymode;
474 }
475 
M_ChangeMouseInvert(void)476 void M_ChangeMouseInvert(void)
477 {
478 }
479 
M_ChangeMaxViewPitch(void)480 void M_ChangeMaxViewPitch(void)
481 {
482   int angle = (int)((float)movement_maxviewpitch / 45.0f * ANG45);
483   maxViewPitch = (angle - (1<<ANGLETOFINESHIFT));
484   minViewPitch = (-angle + (1<<ANGLETOFINESHIFT));
485 
486   viewpitch = 0;
487 }
488 #endif // GL_DOOM
489 
M_ChangeRenderPrecise(void)490 void M_ChangeRenderPrecise(void)
491 {
492 #ifdef GL_DOOM
493   if (V_GetMode() != VID_MODEGL)
494   {
495     gl_seamless = false;
496     return;
497   }
498   else
499   {
500     if (render_precise)
501     {
502       gl_seamless = true;
503       gld_InitVertexData();
504     }
505     else
506     {
507       gl_seamless = false;
508       gld_CleanVertexData();
509     }
510   }
511 #endif // GL_DOOM
512 
513   AM_SetRenderPrecise();
514 }
515 
M_ChangeScreenMultipleFactor(void)516 void M_ChangeScreenMultipleFactor(void)
517 {
518   V_ChangeScreenResolution();
519 }
520 
M_ChangeInterlacedScanning(void)521 void M_ChangeInterlacedScanning(void)
522 {
523   if (render_interlaced_scanning)
524     interlaced_scanning_requires_clearing = 1;
525 }
526 
527 #ifdef GL_DOOM
GetMouseLook(void)528 dboolean GetMouseLook(void)
529 {
530   return movement_mouselook;
531 }
HaveMouseLook(void)532 dboolean HaveMouseLook(void)
533 {
534   return (viewpitch != 0);
535 }
536 #endif
537 
CheckPitch(signed int * pitch)538 void CheckPitch(signed int *pitch)
539 {
540   if (V_GetMode() == VID_MODEGL)
541   {
542     if(*pitch > maxViewPitch)
543       *pitch = maxViewPitch;
544     if(*pitch < minViewPitch)
545       *pitch = minViewPitch;
546 
547     (*pitch) >>= 16;
548     (*pitch) <<= 16;
549   }
550 }
551 
552 int render_aspect;
553 float render_ratio;
554 float render_fovratio;
555 float render_fovy = FOV90;
556 float render_multiplier;
557 
M_ChangeAspectRatio(void)558 void M_ChangeAspectRatio(void)
559 {
560   extern int screenblocks;
561 
562 #ifdef GL_DOOM
563   M_ChangeFOV();
564 #endif
565 
566   R_SetViewSize(screenblocks);
567 }
568 
M_ChangeStretch(void)569 void M_ChangeStretch(void)
570 {
571   extern int screenblocks;
572 
573   render_stretch_hud = render_stretch_hud_default;
574 
575   R_SetViewSize(screenblocks);
576 }
577 
578 #ifdef GL_DOOM
M_ChangeMultiSample(void)579 void M_ChangeMultiSample(void)
580 {
581 }
582 
M_ChangeFOV(void)583 void M_ChangeFOV(void)
584 {
585   float f1, f2;
586   int p;
587   int render_aspect_width, render_aspect_height;
588 
589   if ((p = M_CheckParm("-aspect")) && (p+1 < myargc) && (strlen(myargv[p+1]) <= 21) &&
590      (2 == sscanf(myargv[p+1], "%dx%d", &render_aspect_width, &render_aspect_height)))
591   {
592     CheckRatio(SCREENWIDTH, SCREENHEIGHT);
593     render_fovratio = (float)render_aspect_width / (float)render_aspect_height;
594     render_ratio = RMUL * render_fovratio;
595     render_multiplier = 64.0f / render_fovratio / RMUL;
596   }
597   else
598   {
599     CheckRatio(SCREENWIDTH, SCREENHEIGHT);
600     render_ratio = BaseRatioSizes[wide_ratio].gl_ratio;
601     render_multiplier = (float)BaseRatioSizes[wide_ratio].multiplier;
602     if (!(wide_ratio & 4))
603     {
604       render_fovratio = 1.6f;
605     }
606     else
607     {
608       render_fovratio = render_ratio;
609     }
610   }
611 
612   render_fovy = (float)(2 * RAD2DEG(atan(tan(DEG2RAD(render_fov) / 2) / render_fovratio)));
613 
614   screen_skybox_zplane = 320.0f/2.0f/(float)tan(DEG2RAD(render_fov/2));
615 
616   f1 = (float)(320.0f / 200.0f * (float)render_fov / (float)FOV90 - 0.2f);
617   f2 = (float)tan(DEG2RAD(render_fovy)/2.0f);
618   if (f1-f2<1)
619     skyUpAngle = (float)-RAD2DEG(asin(f1-f2));
620   else
621     skyUpAngle = -90.0f;
622 
623   skyUpShift = (float)tan(DEG2RAD(render_fovy)/2.0f);
624 
625   skyscale = 1.0f / (float)tan(DEG2RAD(render_fov / 2));
626 }
627 
M_ChangeSpriteClip(void)628 void M_ChangeSpriteClip(void)
629 {
630   gl_sprite_offset = (gl_spriteclip != spriteclip_const ? 0 : (.01f * (float)gl_sprite_offset_default));
631   gl_spriteclip_threshold_f = (float)gl_spriteclip_threshold / MAP_COEFF;
632 }
633 
ResolveColormapsHiresConflict(dboolean prefer_colormap)634 void ResolveColormapsHiresConflict(dboolean prefer_colormap)
635 {
636   gl_boom_colormaps = !r_have_internal_hires && !gl_texture_external_hires;
637 #if 0
638   if (prefer_colormap)
639   {
640     if (gl_boom_colormaps_default)
641     {
642       gl_texture_external_hires = false;
643     }
644     else if (gl_texture_external_hires)
645     {
646       gl_boom_colormaps = false;
647       gl_boom_colormaps_default = false;
648     }
649   }
650   else
651   {
652     if (gl_texture_external_hires)
653     {
654       gl_boom_colormaps = false;
655       gl_boom_colormaps_default = false;
656     }
657     else if (gl_boom_colormaps_default)
658     {
659       gl_texture_external_hires = false;
660     }
661   }
662 #endif
663 }
664 
M_ChangeAllowBoomColormaps(void)665 void M_ChangeAllowBoomColormaps(void)
666 {
667   if (gl_boom_colormaps == -1)
668   {
669     gl_boom_colormaps = gl_boom_colormaps_default;
670     ResolveColormapsHiresConflict(true);
671   }
672   else
673   {
674     gl_boom_colormaps = gl_boom_colormaps_default;
675     ResolveColormapsHiresConflict(true);
676     gld_FlushTextures();
677     gld_Precache();
678   }
679 }
680 
M_ChangeTextureUseHires(void)681 void M_ChangeTextureUseHires(void)
682 {
683   ResolveColormapsHiresConflict(false);
684 
685   gld_FlushTextures();
686   gld_Precache();
687 }
688 
M_ChangeTextureHQResize(void)689 void M_ChangeTextureHQResize(void)
690 {
691   gld_FlushTextures();
692 }
693 #endif //GL_DOOM
694 
695 void M_Mouse(int choice, int *sens);
M_MouseMLook(int choice)696 void M_MouseMLook(int choice)
697 {
698   M_Mouse(choice, &mouseSensitivity_mlook);
699 }
700 
M_MouseAccel(int choice)701 void M_MouseAccel(int choice)
702 {
703   M_Mouse(choice, &mouse_acceleration);
704   MouseAccelChanging();
705 }
706 
MouseAccelChanging(void)707 void MouseAccelChanging(void)
708 {
709   mouse_accelfactor = (float)mouse_acceleration/100.0f+1.0f;
710 }
711 
M_DemosBrowse(void)712 void M_DemosBrowse(void)
713 {
714 }
715 
716 float viewPitch;
717 dboolean transparentpresent;
718 
StepwiseSum(int value,int direction,int step,int minval,int maxval,int defval)719 int StepwiseSum(int value, int direction, int step, int minval, int maxval, int defval)
720 {
721   static int prev_value = 0;
722   static int prev_direction = 0;
723 
724   int newvalue;
725   int val = (direction > 0 ? value : value - 1);
726 
727   if (direction == 0)
728     return defval;
729 
730   direction = (direction > 0 ? 1 : -1);
731 
732   if (step != 0)
733     newvalue = (prev_direction * direction < 0 ? prev_value : value + direction * step);
734   else
735   {
736     int exp = 1;
737     while (exp * 10 <= val)
738       exp *= 10;
739     newvalue = direction * (val < exp * 5 && exp > 1 ? exp / 2 : exp);
740     newvalue = (value + newvalue) / newvalue * newvalue;
741   }
742 
743   if (newvalue > maxval) newvalue = maxval;
744   if (newvalue < minval) newvalue = minval;
745 
746   if ((value < defval && newvalue > defval) || (value > defval && newvalue < defval))
747     newvalue = defval;
748 
749   if (newvalue != value)
750   {
751     prev_value = value;
752     prev_direction = direction;
753   }
754 
755   return newvalue;
756 }
757 
I_vWarning(const char * message,va_list argList)758 void I_vWarning(const char *message, va_list argList)
759 {
760   char msg[1024];
761 #ifdef HAVE_VSNPRINTF
762   vsnprintf(msg,sizeof(msg),message,argList);
763 #else
764   vsprintf(msg,message,argList);
765 #endif
766   lprintf(LO_ERROR, "%s\n", msg);
767 #ifdef _MSC_VER
768   I_MessageBox(msg, PRB_MB_OK);
769 #endif
770 }
771 
I_Warning(const char * message,...)772 void I_Warning(const char *message, ...)
773 {
774   va_list argptr;
775   va_start(argptr,message);
776   I_vWarning(message, argptr);
777   va_end(argptr);
778 }
779 
I_MessageBox(const char * text,unsigned int type)780 int I_MessageBox(const char* text, unsigned int type)
781 {
782   int result = PRB_IDCANCEL;
783 
784 #ifdef _WIN32
785   {
786     HWND current_hwnd = GetForegroundWindow();
787     result = MessageBox(GetDesktopWindow(), text, PACKAGE_NAME, type|MB_TASKMODAL|MB_TOPMOST);
788     I_SwitchToWindow(current_hwnd);
789     return result;
790   }
791 #endif
792 
793 #if 0
794   {
795     typedef struct mb_hotkeys_s
796     {
797       int type;
798       char *hotkeys_str;
799     } mb_hotkeys_t;
800 
801     mb_hotkeys_t mb_hotkeys[] = {
802       {PRB_MB_OK               , "(press <enter> to continue)"},
803       {PRB_MB_OKCANCEL         , "(press <enter> to continue or <esc> to cancel)"},
804       {PRB_MB_ABORTRETRYIGNORE , "(a - abort, r - retry, i - ignore)"},
805       {PRB_MB_YESNOCANCEL      , "(y - yes, n - no, esc - cancel"},
806       {PRB_MB_YESNO            , "(y - yes, n - no)"},
807       {PRB_MB_RETRYCANCEL      , "(r - retry, <esc> - cancel)"},
808       {0, NULL}
809     };
810 
811     int i, c;
812     char* hotkeys_str = NULL;
813 
814     type &= 0x000000ff;
815 
816     i = 0;
817     while (mb_hotkeys[i].hotkeys_str)
818     {
819       if (mb_hotkeys[i].type == type)
820       {
821         hotkeys_str = mb_hotkeys[i].hotkeys_str;
822         break;
823       }
824       i++;
825     }
826 
827     if (hotkeys_str)
828     {
829       lprintf(LO_CONFIRM, "%s\n%s\n", text, hotkeys_str);
830 
831       result = -1;
832       do
833       {
834         I_uSleep(1000);
835 
836         c = tolower(getchar());
837 
838         if (c == 'y') result = PRB_IDYES;
839         else if (c == 'n') result = PRB_IDNO;
840         else if (c == 'a') result = PRB_IDABORT;
841         else if (c == 'r') result = PRB_IDRETRY;
842         else if (c == 'i') result = PRB_IDIGNORE;
843         else if (c == 'o' || c == 13) result = PRB_IDOK;
844         else if (c == 'c' || c == 27) result = PRB_IDCANCEL;
845       }
846       while (result == EOF);
847 
848       return result;
849     }
850 
851     return result;
852   }
853 #else
854   return PRB_IDCANCEL;
855 #endif
856 }
857 
858 int stats_level;
859 int numlevels = 0;
860 int levels_max = 0;
861 timetable_t *stats = NULL;
862 
e6y_G_DoCompleted(void)863 void e6y_G_DoCompleted(void)
864 {
865   int i;
866 
867   if (doSkip && (demo_stoponend || demo_warp))
868     G_SkipDemoStop();
869 
870   if(!stats_level)
871     return;
872 
873   if (numlevels >= levels_max)
874   {
875     levels_max = levels_max ? levels_max*2 : 32;
876     stats = realloc(stats,sizeof(*stats)*levels_max);
877   }
878 
879   memset(&stats[numlevels], 0, sizeof(timetable_t));
880 
881   if (gamemode==commercial)
882     sprintf(stats[numlevels].map,"MAP%02i",gamemap);
883   else
884     sprintf(stats[numlevels].map,"E%iM%i",gameepisode,gamemap);
885 
886   stats[numlevels].stat[TT_TIME]        = leveltime;
887   stats[numlevels].stat[TT_TOTALTIME]   = totalleveltimes;
888   stats[numlevels].stat[TT_TOTALKILL]   = totalkills;
889   stats[numlevels].stat[TT_TOTALITEM]   = totalitems;
890   stats[numlevels].stat[TT_TOTALSECRET] = totalsecret;
891 
892   for (i=0 ; i<MAXPLAYERS ; i++)
893   {
894     if (playeringame[i])
895     {
896       stats[numlevels].kill[i]   = players[i].killcount - players[i].resurectedkillcount;
897       stats[numlevels].item[i]   = players[i].itemcount;
898       stats[numlevels].secret[i] = players[i].secretcount;
899 
900       stats[numlevels].stat[TT_ALLKILL]   += stats[numlevels].kill[i];
901       stats[numlevels].stat[TT_ALLITEM]   += stats[numlevels].item[i];
902       stats[numlevels].stat[TT_ALLSECRET] += stats[numlevels].secret[i];
903     }
904   }
905 
906   numlevels++;
907 
908   e6y_WriteStats();
909 }
910 
911 typedef struct tmpdata_s
912 {
913   char kill[200];
914   char item[200];
915   char secret[200];
916 } tmpdata_t;
917 
e6y_WriteStats(void)918 void e6y_WriteStats(void)
919 {
920   FILE *f;
921   char str[200];
922   int i, level, playerscount;
923   timetable_t max;
924   tmpdata_t tmp;
925   tmpdata_t all[32];
926   size_t allkills_len=0, allitems_len=0, allsecrets_len=0;
927 
928   f = fopen("levelstat.txt", "wb");
929 
930   memset(&max, 0, sizeof(timetable_t));
931 
932   playerscount = 0;
933   for (i=0; i<MAXPLAYERS; i++)
934     if (playeringame[i])
935       playerscount++;
936 
937   for (level=0;level<numlevels;level++)
938   {
939     memset(&tmp, 0, sizeof(tmpdata_t));
940     for (i=0 ; i<MAXPLAYERS ; i++)
941     {
942       if (playeringame[i])
943       {
944         strcpy(str, strlen(tmp.kill)==0?"%s%d":"%s+%d");
945 
946         sprintf(tmp.kill,   str, tmp.kill,   stats[level].kill[i]  );
947         sprintf(tmp.item,   str, tmp.item,   stats[level].item[i]  );
948         sprintf(tmp.secret, str, tmp.secret, stats[level].secret[i]);
949       }
950     }
951     if (playerscount<2)
952       memset(&all[level], 0, sizeof(tmpdata_t));
953     else
954     {
955       sprintf(all[level].kill,   " (%s)", tmp.kill  );
956       sprintf(all[level].item,   " (%s)", tmp.item  );
957       sprintf(all[level].secret, " (%s)", tmp.secret);
958     }
959 
960     if (strlen(all[level].kill) > allkills_len)
961       allkills_len = strlen(all[level].kill);
962     if (strlen(all[level].item) > allitems_len)
963       allitems_len = strlen(all[level].item);
964     if (strlen(all[level].secret) > allsecrets_len)
965       allsecrets_len = strlen(all[level].secret);
966 
967     for(i=0; i<TT_MAX; i++)
968       if (stats[level].stat[i] > max.stat[i])
969         max.stat[i] = stats[level].stat[i];
970   }
971   max.stat[TT_TIME] = max.stat[TT_TIME]/TICRATE/60;
972   max.stat[TT_TOTALTIME] = max.stat[TT_TOTALTIME]/TICRATE/60;
973 
974   for(i=0; i<TT_MAX; i++) {
975     SNPRINTF(str, 200, "%d", max.stat[i]);
976     max.stat[i] = strlen(str);
977   }
978 
979   for (level=0;level<numlevels;level++)
980   {
981     sprintf(str,
982       "%%s - %%%dd:%%05.2f (%%%dd:%%02d)  K: %%%dd/%%-%dd%%%ds  I: %%%dd/%%-%dd%%%ds  S: %%%dd/%%-%dd %%%ds\r\n",
983       max.stat[TT_TIME],      max.stat[TT_TOTALTIME],
984       max.stat[TT_ALLKILL],   max.stat[TT_TOTALKILL],   allkills_len,
985       max.stat[TT_ALLITEM],   max.stat[TT_TOTALITEM],   allitems_len,
986       max.stat[TT_ALLSECRET], max.stat[TT_TOTALSECRET], allsecrets_len);
987 
988     fprintf(f, str, stats[level].map,
989       stats[level].stat[TT_TIME]/TICRATE/60,
990       (float)(stats[level].stat[TT_TIME]%(60*TICRATE))/TICRATE,
991       (stats[level].stat[TT_TOTALTIME])/TICRATE/60,
992       (stats[level].stat[TT_TOTALTIME]%(60*TICRATE))/TICRATE,
993       stats[level].stat[TT_ALLKILL],  stats[level].stat[TT_TOTALKILL],   all[level].kill,
994       stats[level].stat[TT_ALLITEM],  stats[level].stat[TT_TOTALITEM],   all[level].item,
995       stats[level].stat[TT_ALLSECRET],stats[level].stat[TT_TOTALSECRET], all[level].secret
996       );
997 
998   }
999 
1000   fclose(f);
1001 }
1002 
e6y_G_DoWorldDone(void)1003 void e6y_G_DoWorldDone(void)
1004 {
1005   if (doSkip)
1006   {
1007     static int firstmap = 1;
1008     int episode = 0;
1009     int map = 0;
1010     int p;
1011 
1012     if ((p = M_CheckParm ("-warp")))
1013     {
1014       if (gamemode == commercial)
1015       {
1016         if (p < myargc - 1)
1017           map = atoi(myargv[p + 1]);
1018       }
1019       else
1020       {
1021         if (p < myargc - 2)
1022         {
1023           episode = atoi(myargv[++p]);
1024           map = atoi(myargv[p + 1]);
1025         }
1026       }
1027     }
1028 
1029     demo_warp = demo_stoponnext ||
1030       (gamemode == commercial ? (map == gamemap) : (episode == gameepisode && map == gamemap));
1031 
1032     if (demo_warp && demo_skiptics == 0 && !firstmap)
1033       G_SkipDemoStop();
1034 
1035     firstmap = 0;
1036   }
1037 }
1038 
1039 //--------------------------------------------------
1040 
1041 #ifdef _WIN32
WIN32_GetHWND(void)1042 HWND WIN32_GetHWND(void)
1043 {
1044   static HWND Window = NULL;
1045   if(!Window)
1046   {
1047     SDL_SysWMinfo wminfo;
1048     SDL_VERSION(&wminfo.version);
1049     SDL_GetWMInfo(&wminfo);
1050 #if SDL_VERSION_ATLEAST(1, 3, 0)
1051     Window = wminfo.info.win.window;
1052 #else
1053     Window = wminfo.window;
1054 #endif
1055   }
1056   return Window;
1057 }
1058 #endif
1059 
AccelerateMouse(int val)1060 int AccelerateMouse(int val)
1061 {
1062   if (!mouse_acceleration)
1063     return val;
1064 
1065   if (val < 0)
1066     return -AccelerateMouse(-val);
1067 
1068   return M_DoubleToInt(pow((double)val, (double)mouse_accelfactor));
1069 }
1070 
1071 int mlooky = 0;
1072 
1073 dboolean IsDehMaxHealth = false;
1074 dboolean IsDehMaxSoul = false;
1075 dboolean IsDehMegaHealth = false;
1076 dboolean DEH_mobjinfo_bits[NUMMOBJTYPES] = {0};
1077 
1078 int deh_maxhealth;
1079 int deh_max_soul;
1080 int deh_mega_health;
1081 
1082 int maxhealthbonus;
1083 
M_ChangeCompTranslucency(void)1084 void M_ChangeCompTranslucency(void)
1085 {
1086   int i;
1087   int predefined_translucency[] = {
1088     MT_FIRE, MT_SMOKE, MT_FATSHOT, MT_BRUISERSHOT, MT_SPAWNFIRE,
1089     MT_TROOPSHOT, MT_HEADSHOT, MT_PLASMA, MT_BFG, MT_ARACHPLAZ, MT_PUFF,
1090     MT_TFOG, MT_IFOG, MT_MISC12, MT_INV, MT_INS, MT_MEGA
1091   };
1092 
1093   for(i = 0; (size_t)i < sizeof(predefined_translucency)/sizeof(predefined_translucency[0]); i++)
1094   {
1095     if (!DEH_mobjinfo_bits[predefined_translucency[i]])
1096     {
1097       // Transparent sprites are not visible behind transparent walls in OpenGL.
1098       // It needs much work.
1099 #ifdef GL_DOOM
1100       if (V_GetMode() == VID_MODEGL)
1101       {
1102         // Disabling transparency in OpenGL for original sprites
1103         // which are not changed by dehacked, because it's buggy for now.
1104         // Global sorting of transparent sprites and walls is needed
1105         mobjinfo[predefined_translucency[i]].flags &= ~MF_TRANSLUCENT;
1106       }
1107       else
1108 #endif
1109       if (comp[comp_translucency])
1110         mobjinfo[predefined_translucency[i]].flags &= ~MF_TRANSLUCENT;
1111       else
1112         mobjinfo[predefined_translucency[i]].flags |= MF_TRANSLUCENT;
1113     }
1114   }
1115 }
1116 
e6y_G_Compatibility(void)1117 void e6y_G_Compatibility(void)
1118 {
1119   extern int maxhealth;
1120   extern int max_soul;
1121   extern int mega_health;
1122 
1123   int comp_max = (compatibility_level == doom_12_compatibility ? 199 : 200);
1124 
1125   max_soul = (IsDehMaxSoul ? deh_max_soul : comp_max);
1126   mega_health = (IsDehMegaHealth ? deh_mega_health : comp_max);
1127 
1128   if (comp[comp_maxhealth])
1129   {
1130     maxhealth = 100;
1131     maxhealthbonus = (IsDehMaxHealth ? deh_maxhealth : comp_max);
1132   }
1133   else
1134   {
1135     maxhealth = (IsDehMaxHealth ? deh_maxhealth : 100);
1136     maxhealthbonus = maxhealth * 2;
1137   }
1138 
1139   if (!DEH_mobjinfo_bits[MT_SKULL])
1140   {
1141     if (compatibility_level == doom_12_compatibility)
1142       mobjinfo[MT_SKULL].flags |= (MF_COUNTKILL);
1143     else
1144       mobjinfo[MT_SKULL].flags &= ~(MF_COUNTKILL);
1145   }
1146 
1147   M_ChangeCompTranslucency();
1148 
1149   if (IsDemoPlayback())
1150   {
1151     int i, p;
1152 
1153     //"2.4.8.2" -> 0x02040802
1154     if ((p = M_CheckParm("-emulate")) && (p < myargc - 1))
1155     {
1156       unsigned int emulated_version = 0;
1157       int b[4], k = 1;
1158       memset(b, 0, sizeof(b));
1159       sscanf(myargv[p + 1], "%d.%d.%d.%d", &b[0], &b[1], &b[2], &b[3]);
1160       for (i = 3; i >= 0; i--, k *= 256)
1161       {
1162 #ifdef RANGECHECK
1163         if (b[i] >= 256)
1164           I_Error("Wrong version number of package: %s", VERSION);
1165 #endif
1166         emulated_version += b[i] * k;
1167       }
1168 
1169       for (i = 0; i < PC_MAX; i++)
1170       {
1171         prboom_comp[i].state =
1172           (emulated_version >= prboom_comp[i].minver &&
1173            emulated_version <  prboom_comp[i].maxver);
1174       }
1175     }
1176 
1177     for (i = 0; i < PC_MAX; i++)
1178     {
1179       if (M_CheckParm(prboom_comp[i].cmd))
1180         prboom_comp[i].state = true;
1181     }
1182   }
1183   use_wrong_fixeddiv = &(prboom_comp[PC_WRONG_FIXEDDIV].state);
1184 
1185   P_CrossSubsector = P_CrossSubsector_PrBoom;
1186   if (!prboom_comp[PC_FORCE_LXDOOM_DEMO_COMPATIBILITY].state)
1187   {
1188     if (demo_compatibility)
1189       P_CrossSubsector = P_CrossSubsector_Doom;
1190 
1191     switch (compatibility_level)
1192     {
1193     case boom_compatibility_compatibility:
1194     case boom_201_compatibility:
1195     case boom_202_compatibility:
1196     case mbf_compatibility:
1197       P_CrossSubsector = P_CrossSubsector_Boom;
1198     break;
1199     }
1200   }
1201 }
1202 
1203 dboolean zerotag_manual;
1204 int comperr_zerotag;
1205 int comperr_passuse;
1206 int comperr_hangsolid;
1207 
ProcessNoTagLines(line_t * line,sector_t ** sec,int * secnum)1208 dboolean ProcessNoTagLines(line_t* line, sector_t **sec, int *secnum)
1209 {
1210   zerotag_manual = false;
1211   if (line->tag == 0 && COMPBAD(comperr_zerotag))
1212   {
1213     if (!(*sec=line->backsector))
1214       return true;
1215     *secnum = (*sec)->iSectorID;
1216     zerotag_manual = true;
1217     return true;
1218   }
1219   return false;
1220 }
1221 
PathFindFileName(const char * pPath)1222 char* PathFindFileName(const char* pPath)
1223 {
1224   const char* pT = pPath;
1225 
1226   if (pPath)
1227   {
1228     for ( ; *pPath; pPath++)
1229     {
1230       if ((pPath[0] == '\\' || pPath[0] == ':' || pPath[0] == '/')
1231         && pPath[1] &&  pPath[1] != '\\'  &&   pPath[1] != '/')
1232         pT = pPath + 1;
1233     }
1234   }
1235 
1236   return (char*)pT;
1237 }
1238 
NormalizeSlashes2(char * str)1239 void NormalizeSlashes2(char *str)
1240 {
1241   size_t l;
1242 
1243   if (!str || !(l = strlen(str)))
1244     return;
1245   if (str[--l]=='\\' || str[l]=='/')
1246     str[l]=0;
1247   while (l--)
1248     if (str[l]=='/')
1249       str[l]='\\';
1250 }
1251 
AfxGetFileName(const char * lpszPathName,char * lpszTitle,unsigned int nMax)1252 unsigned int AfxGetFileName(const char* lpszPathName, char* lpszTitle, unsigned int nMax)
1253 {
1254   char* lpszTemp = PathFindFileName(lpszPathName);
1255 
1256   if (lpszTitle == NULL)
1257     return strlen(lpszTemp)+1;
1258 
1259   strncpy(lpszTitle, lpszTemp, nMax-1);
1260   return 0;
1261 }
1262 
AbbreviateName(char * lpszCanon,int cchMax,int bAtLeastName)1263 void AbbreviateName(char* lpszCanon, int cchMax, int bAtLeastName)
1264 {
1265   int cchFullPath, cchFileName, cchVolName;
1266   const char* lpszCur;
1267   const char* lpszBase;
1268   const char* lpszFileName;
1269 
1270   lpszBase = lpszCanon;
1271   cchFullPath = strlen(lpszCanon);
1272 
1273   cchFileName = AfxGetFileName(lpszCanon, NULL, 0) - 1;
1274   lpszFileName = lpszBase + (cchFullPath-cchFileName);
1275 
1276   if (cchMax >= cchFullPath)
1277     return;
1278 
1279   if (cchMax < cchFileName)
1280   {
1281     strcpy(lpszCanon, (bAtLeastName) ? lpszFileName : "");
1282     return;
1283   }
1284 
1285   lpszCur = lpszBase + 2;
1286 
1287   if (lpszBase[0] == '\\' && lpszBase[1] == '\\')
1288   {
1289     while (*lpszCur != '\\')
1290       lpszCur++;
1291   }
1292 
1293   if (cchFullPath - cchFileName > 3)
1294   {
1295     lpszCur++;
1296     while (*lpszCur != '\\')
1297       lpszCur++;
1298   }
1299 
1300   cchVolName = (int)(lpszCur - lpszBase);
1301   if (cchMax < cchVolName + 5 + cchFileName)
1302   {
1303     strcpy(lpszCanon, lpszFileName);
1304     return;
1305   }
1306 
1307   while (cchVolName + 4 + (int)strlen(lpszCur) > cchMax)
1308   {
1309     do
1310     {
1311       lpszCur++;
1312     }
1313     while (*lpszCur != '\\');
1314   }
1315 
1316   lpszCanon[cchVolName] = '\0';
1317   strcat(lpszCanon, "\\...");
1318   strcat(lpszCanon, lpszCur);
1319 }
1320 
1321 int levelstarttic;
1322 
1323 int force_singletics_to = 0;
1324 
HU_DrawDemoProgress(int force)1325 int HU_DrawDemoProgress(int force)
1326 {
1327   static unsigned int last_update = 0;
1328   static int prev_len = -1;
1329 
1330   int len, tics_count, diff;
1331   unsigned int tick, max_period;
1332 
1333   if (gamestate == GS_DEMOSCREEN || (!demoplayback && !democontinue) || !hudadd_demoprogressbar)
1334     return false;
1335 
1336   tics_count = ((doSkip && demo_skiptics > 0) ? MIN(demo_skiptics, demo_tics_count) : demo_tics_count) * demo_playerscount;
1337   len = MIN(SCREENWIDTH, (int)((int_64_t)SCREENWIDTH * demo_curr_tic / tics_count));
1338 
1339   if (!force)
1340   {
1341     max_period = ((tics_count - demo_curr_tic > 35 * demo_playerscount) ? 500 : 15);
1342 
1343     // Unnecessary updates of progress bar
1344     // can slow down demo skipping and playback
1345     tick = SDL_GetTicks();
1346     if (tick - last_update < max_period)
1347       return false;
1348     last_update = tick;
1349 
1350     // Do not update progress bar if difference is small
1351     diff = len - prev_len;
1352     if (diff == 0 || diff == 1) // because of static prev_len
1353       return false;
1354   }
1355 
1356   prev_len = len;
1357 
1358   V_FillRect(0, 0, SCREENHEIGHT - 4, len - 0, 4, 4);
1359   if (len > 4)
1360     V_FillRect(0, 2, SCREENHEIGHT - 3, len - 4, 2, 0);
1361 
1362   return true;
1363 }
1364 
1365 #ifdef ALL_IN_ONE
GetAllInOneLumpHandle(void)1366 unsigned char* GetAllInOneLumpHandle(void)
1367 {
1368   static unsigned char* AllInOneLumpHandle = NULL;
1369 
1370   if (!AllInOneLumpHandle)
1371   {
1372     HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(IDR_ALL_IN_ONE_LUMP), RT_RCDATA);
1373     if (hrsrc)
1374     {
1375       HGLOBAL hglobal = LoadResource(NULL, hrsrc);
1376       if (hglobal)
1377       {
1378         AllInOneLumpHandle = LockResource(hglobal);
1379       }
1380     }
1381   }
1382 
1383   if (!AllInOneLumpHandle)
1384     I_Error("Can't load internal data.");
1385 
1386   return AllInOneLumpHandle;
1387 }
1388 #endif
1389 
1390 #ifdef _MSC_VER
GetFullPath(const char * FileName,const char * ext,char * Buffer,size_t BufferLength)1391 int GetFullPath(const char* FileName, const char* ext, char *Buffer, size_t BufferLength)
1392 {
1393   int i, Result;
1394   char *p;
1395   char dir[PATH_MAX];
1396 
1397   for (i=0; i<3; i++)
1398   {
1399     switch(i)
1400     {
1401     case 0:
1402       getcwd(dir, sizeof(dir));
1403       break;
1404     case 1:
1405       if (!getenv("DOOMWADDIR"))
1406         continue;
1407       strcpy(dir, getenv("DOOMWADDIR"));
1408       break;
1409     case 2:
1410       strcpy(dir, I_DoomExeDir());
1411       break;
1412     }
1413 
1414     Result = SearchPath(dir,FileName,ext,BufferLength,Buffer,&p);
1415     if (Result)
1416       return Result;
1417   }
1418 
1419   return false;
1420 }
1421 #endif
1422 
1423 #ifdef _WIN32
1424 #include <Mmsystem.h>
1425 #pragma comment( lib, "winmm.lib" )
1426 int mus_extend_volume;
I_midiOutSetVolumes(int volume)1427 void I_midiOutSetVolumes(int volume)
1428 {
1429   // NSM changed to work on the 0-15 volume scale,
1430   // and to check mus_extend_volume itself.
1431 
1432   MMRESULT result;
1433   int calcVolume;
1434   MIDIOUTCAPS capabilities;
1435   unsigned int i;
1436 
1437   if (volume > 15)
1438     volume = 15;
1439   if (volume < 0)
1440     volume = 0;
1441   calcVolume = (65535 * volume / 15);
1442 
1443   //SDL_LockAudio(); // this function doesn't touch anything the audio callback touches
1444 
1445   //Device loop
1446   for (i = 0; i < midiOutGetNumDevs(); i++)
1447   {
1448     //Get device capabilities
1449     result = midiOutGetDevCaps(i, &capabilities, sizeof(capabilities));
1450     if (result == MMSYSERR_NOERROR)
1451     {
1452       //Adjust volume on this candidate
1453       if ((capabilities.dwSupport & MIDICAPS_VOLUME))
1454       {
1455         midiOutSetVolume((HMIDIOUT)i, MAKELONG(calcVolume, calcVolume));
1456       }
1457     }
1458   }
1459 
1460   //SDL_UnlockAudio();
1461 }
1462 #endif
1463 
1464 //Begin of GZDoom code
1465 /*
1466 **---------------------------------------------------------------------------
1467 ** Copyright 2004-2005 Christoph Oelckers
1468 ** All rights reserved.
1469 **
1470 ** Redistribution and use in source and binary forms, with or without
1471 ** modification, are permitted provided that the following conditions
1472 ** are met:
1473 **
1474 ** 1. Redistributions of source code must retain the above copyright
1475 **    notice, this list of conditions and the following disclaimer.
1476 ** 2. Redistributions in binary form must reproduce the above copyright
1477 **    notice, this list of conditions and the following disclaimer in the
1478 **    documentation and/or other materials provided with the distribution.
1479 ** 3. The name of the author may not be used to endorse or promote products
1480 **    derived from this software without specific prior written permission.
1481 ** 4. When not used as part of GZDoom or a GZDoom derivative, this code will be
1482 **    covered by the terms of the GNU Lesser General Public License as published
1483 **    by the Free Software Foundation; either version 2.1 of the License, or (at
1484 **    your option) any later version.
1485 */
1486 
1487 //===========================================================================
1488 //
1489 // smooth the edges of transparent fields in the texture
1490 // returns false when nothing is manipulated to save the work on further
1491 // levels
1492 
1493 // 28/10/2003: major optimization: This function was far too pedantic.
1494 // taking the value of one of the neighboring pixels is fully sufficient
1495 //
1496 //===========================================================================
1497 
1498 #ifdef WORDS_BIGENDIAN
1499 #define MSB 0
1500 #define SOME_MASK 0xffffff00
1501 #else
1502 #define MSB 3
1503 #define SOME_MASK 0x00ffffff
1504 #endif
1505 
1506 #define CHKPIX(ofs) (l1[(ofs)*4+MSB]==255 ? (( ((unsigned int*)l1)[0] = ((unsigned int*)l1)[ofs]&SOME_MASK), trans=true ) : false)
1507 
SmoothEdges(unsigned char * buffer,int w,int h)1508 dboolean SmoothEdges(unsigned char * buffer,int w, int h)
1509 {
1510   int x,y;
1511   dboolean trans=buffer[MSB]==0; // If I set this to false here the code won't detect textures
1512                                 // that only contain transparent pixels.
1513   unsigned char * l1;
1514 
1515   // makes (a) no sense and (b) doesn't work with this code!
1516   // if (h<=1 || w<=1)
1517   // e6y: Do not smooth small patches.
1518   // Makes sense for HUD small digits
1519   // 2 and 7 still look ugly
1520   if (h<=8 || w<=8)
1521     return false;
1522 
1523   l1=buffer;
1524 
1525   if (l1[MSB]==0 && !CHKPIX(1)) CHKPIX(w);
1526   l1+=4;
1527   for(x=1;x<w-1;x++, l1+=4)
1528   {
1529     if (l1[MSB]==0 &&  !CHKPIX(-1) && !CHKPIX(1)) CHKPIX(w);
1530   }
1531   if (l1[MSB]==0 && !CHKPIX(-1)) CHKPIX(w);
1532   l1+=4;
1533 
1534   for(y=1;y<h-1;y++)
1535   {
1536     if (l1[MSB]==0 && !CHKPIX(-w) && !CHKPIX(1)) CHKPIX(w);
1537     l1+=4;
1538     for(x=1;x<w-1;x++, l1+=4)
1539     {
1540       if (l1[MSB]==0 &&  !CHKPIX(-w) && !CHKPIX(-1) && !CHKPIX(1)) CHKPIX(w);
1541     }
1542     if (l1[MSB]==0 && !CHKPIX(-w) && !CHKPIX(-1)) CHKPIX(w);
1543     l1+=4;
1544   }
1545 
1546   if (l1[MSB]==0 && !CHKPIX(-w)) CHKPIX(1);
1547   l1+=4;
1548   for(x=1;x<w-1;x++, l1+=4)
1549   {
1550     if (l1[MSB]==0 &&  !CHKPIX(-w) && !CHKPIX(-1)) CHKPIX(1);
1551   }
1552   if (l1[MSB]==0 && !CHKPIX(-w)) CHKPIX(-1);
1553 
1554   return trans;
1555 }
1556 
1557 #undef MSB
1558 #undef SOME_MASK
1559 //End of GZDoom code
1560