1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2016 EDuke32 developers and contributors
4 
5 This file is part of EDuke32.
6 
7 EDuke32 is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License version 2
9 as published by the Free Software Foundation.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 
15 See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 */
21 //-------------------------------------------------------------------------
22 
23 #pragma once
24 
25 #ifndef game_h_
26 #define game_h_
27 
28 #ifndef ONLY_USERDEFS
29 #include "premap.h" // XXX
30 #endif
31 
32 #include "fix16.h"
33 #include "gamedefs.h"
34 #include "gamedef.h"
35 #include "net.h"
36 #include "mmulti.h"
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 #ifndef ONLY_USERDEFS
43 
44 // Compile game-side legacy Room over Room code?
45 #define LEGACY_ROR 1
46 
47 #define USERQUOTE_LEFTOFFSET    5
48 #define USERQUOTE_RIGHTOFFSET   14
49 
50 #if defined(GEKKO) || defined(__OPENDINGUX__)
51 # define VIEWSCREENFACTOR 0
52 #elif defined(__ANDROID__)
53 # define VIEWSCREENFACTOR 1
54 #else
55 # define VIEWSCREENFACTOR 2
56 #endif
57 
58 enum GametypeFlags_t {
59     GAMETYPE_COOP                   = 0x00000001,
60     GAMETYPE_WEAPSTAY               = 0x00000002,
61     GAMETYPE_FRAGBAR                = 0x00000004,
62     GAMETYPE_SCORESHEET             = 0x00000008,
63     GAMETYPE_DMSWITCHES             = 0x00000010,
64     GAMETYPE_COOPSPAWN              = 0x00000020,
65     GAMETYPE_ACCESSCARDSPRITES      = 0x00000040,
66     GAMETYPE_COOPVIEW               = 0x00000080,
67     GAMETYPE_COOPSOUND              = 0x00000100,
68     GAMETYPE_OTHERPLAYERSINMAP      = 0x00000200,
69     GAMETYPE_ITEMRESPAWN            = 0x00000400,
70     GAMETYPE_MARKEROPTION           = 0x00000800,
71     GAMETYPE_PLAYERSFRIENDLY        = 0x00001000,
72     GAMETYPE_FIXEDRESPAWN           = 0x00002000,
73     GAMETYPE_ACCESSATSTART          = 0x00004000,
74     GAMETYPE_PRESERVEINVENTORYDEATH = 0x00008000,
75     GAMETYPE_TDM                    = 0x00010000,
76     GAMETYPE_TDMSPAWN               = 0x00020000
77 };
78 
79 // logo control
80 enum LogoFlags_t {
81     LOGO_ENABLED           = 0x00000001,
82     LOGO_PLAYANIM          = 0x00000002,
83     LOGO_PLAYMUSIC         = 0x00000004,
84     LOGO_3DRSCREEN         = 0x00000008,
85     LOGO_TITLESCREEN       = 0x00000010,
86     LOGO_DUKENUKEM         = 0x00000020,
87     LOGO_THREEDEE          = 0x00000040,
88     LOGO_PLUTOPAKSPRITE    = 0x00000080,
89     LOGO_SHAREWARESCREENS  = 0x00000100,
90     LOGO_TENSCREEN         = 0x00000200,
91     LOGO_STOPANIMSOUNDS    = 0x00000400,
92     LOGO_NOE4CUTSCENE      = 0x00000800,
93     LOGO_NOE1BONUSSCENE    = 0x00001000,
94     LOGO_NOE2BONUSSCENE    = 0x00002000,
95     LOGO_NOE3BONUSSCENE    = 0x00004000,
96     LOGO_NOE4BONUSSCENE    = 0x00008000,
97     LOGO_NOE1ENDSCREEN     = 0x00010000,
98     LOGO_NOE2ENDSCREEN     = 0x00020000,
99     LOGO_NOE3RADLOGO       = 0x00040000,
100     LOGO_NODUKETEAMTEXT    = 0x00080000,
101     LOGO_NODUKETEAMPIC     = 0x00100000,
102     LOGO_STOPMISCSOUNDS    = 0x00200000,
103     LOGO_NOGAMETITLE       = 0x00400000,
104     LOGO_NOTITLEBAR        = 0x00800000,
105     LOGO_HIDEEPISODE       = 0x01000000,
106     LOGO_NOHELP            = 0x02000000,
107     LOGO_NOCREDITS         = 0x04000000,
108 };
109 
110 enum {
111     STATUSBAR_NONONE    = 0x00000001,
112     STATUSBAR_NOMINI    = 0x00000002,
113     STATUSBAR_NOFULL    = 0x00000004,
114     STATUSBAR_NOSHRINK  = 0x00000008,
115     STATUSBAR_NOFRAGBAR = 0x00000010,
116     STATUSBAR_NOOVERLAY = 0x00000020,
117     STATUSBAR_NOMODERN  = 0x00000040,
118 };
119 
120 void A_DeleteSprite(int spriteNum);
121 
122 //static inline int32_t G_GetLogoFlags(void)
123 //{
124 //    return 255;
125 //}
126 
127 # define CAMERA(Membname) (ud.camera ## Membname)
128 # define CAMERADIST g_cameraDistance
129 # define CAMERACLOCK g_cameraClock
130 
131 #endif
132 
133 #define MAXRIDECULE 10
134 #define MAXRIDECULELENGTH 40
135 #define MAXSAVEGAMENAMESTRUCT 32
136 #define MAXSAVEGAMENAME (MAXSAVEGAMENAMESTRUCT-1)
137 #define MAXPWLOCKOUT 128
138 #define MAXRTSNAME 128
139 
140 #define MAX_RETURN_VALUES 6
141 
142 // KEEPINSYNC lunatic/_defs_game.lua
143 
144 typedef struct {
145     int32_t usejoystick;
146     int32_t usemouse;
147     int32_t fullscreen;
148     int32_t xdim;
149     int32_t ydim;
150     int32_t bpp;
151     int32_t forcesetup;
152     int32_t noautoload;
153 } ud_setup_t;
154 
155 typedef struct {
156     vec3_t camerapos;
157     int32_t const_visibility,uw_framerate;
158     int32_t camera_time,folfvel,folavel,folx,foly,fola;
159     int32_t reccnt,crosshairscale;
160 
161     int32_t runkey_mode,statusbarscale,mouseaiming,weaponswitch,drawweapon;   // JBF 20031125
162     int32_t democams,color,msgdisptime,statusbarmode;
163     int32_t m_noexits,noexits,autovote,automsg,idplayers;
164     int32_t team, viewbob, weaponsway, althud, weaponscale, textscale;
165     int32_t statusbarflags, statusbarrange, statusbarcustom;
166     int32_t hudontop;
167     int32_t menu_slidebarz, menu_slidebarmargin, menu_slidecursorz;
168     int32_t menu_scrollbartilenum, menu_scrollbarz, menu_scrollcursorz;
169 
170     int32_t entered_name,screen_tilting,shadows,fta_on,executions,auto_run;
171     int32_t coords,showfps,levelstats,m_coop,coop,screen_size,lockout,crosshair;
172     int32_t playerai,angleinterpolation,obituaries;
173 
174     int32_t respawn_monsters,respawn_items,respawn_inventory,recstat,monsters_off,brightness;
175     int32_t m_respawn_items,m_respawn_monsters,m_respawn_inventory,m_recstat,m_monsters_off,detail;
176     int32_t m_ffire,ffire,m_player_skill,m_level_number,m_volume_number,multimode;
177     int32_t player_skill,level_number,volume_number,m_marker,marker,mouseflip;
178     int32_t music_episode, music_level;
179 
180     int32_t playerbest;
181 
182     int32_t configversion, bgstretch, frameperiod;
183 
184     int32_t default_volume, default_skill;
185 
186     int32_t autosave;
187     int32_t autosavedeletion, maxautosaves;
188 
189     //int32_t returnvar[MAX_RETURN_VALUES-1];
190 
191     uint32_t userbytever;
192 
193     int32_t fov;
194 
195     fix16_t cameraq16ang, cameraq16horiz;
196     int16_t camerasect;
197     int16_t pause_on,from_bonus;
198     int16_t camerasprite,last_camsprite;
199     int16_t last_level,secretlevel;
200 
201     int8_t menutitle_pal, slidebar_palselected, slidebar_paldisabled;
202 
203     struct {
204         int32_t AutoAim;
205         int32_t ShowOpponentWeapons;
206         int32_t MouseDeadZone,MouseBias;
207 
208         // JBF 20031211: Store the input settings because
209         // (currently) mact can't regurgitate them
210         int32_t MouseFunctions[MAXMOUSEBUTTONS][2];
211         int32_t MouseAnalogueAxes[MAXMOUSEAXES];
212         int32_t JoystickFunctions[MAXJOYBUTTONSANDHATS][2];
213         int32_t JoystickDigitalFunctions[MAXJOYAXES][2];
214         int32_t JoystickAnalogueAxes[MAXJOYAXES];
215         int32_t JoystickAnalogueScale[MAXJOYAXES];
216         int32_t JoystickAnalogueDead[MAXJOYAXES];
217         int32_t JoystickAnalogueSaturate[MAXJOYAXES];
218         uint8_t KeyboardKeys[NUMGAMEFUNCTIONS][2];
219 
220         //
221         // Sound variables
222         //
223         int32_t FXVolume;
224         int32_t MusicDevice;
225         int32_t MusicVolume;
226         int32_t SoundToggle;
227         int32_t MusicToggle;
228         int32_t VoiceToggle;
229         int32_t AmbienceToggle;
230 
231         int32_t NumVoices;
232         int32_t NumChannels;
233         int32_t NumBits;
234         int32_t MixRate;
235 
236 #ifdef ASS_REVERSESTEREO
237         int32_t ReverseStereo;
238 #endif
239 
240         int32_t scripthandle;
241         int32_t setupread;
242 
243         int32_t CheckForUpdates;
244         int32_t LastUpdateCheck;
245         int32_t useprecache;
246     } config;
247 
248     ud_setup_t setup;
249 
250     char overhead_on,last_overhead,showweapons;
251     char god,warp_on,cashman,eog,showallmap;
252     char show_help,scrollmode,noclip;
253     char ridecule[MAXRIDECULE][MAXRIDECULELENGTH];
254     char pwlockout[MAXPWLOCKOUT],rtsname[MAXRTSNAME];
255     char display_bonus_screen;
256     char show_level_text;
257     char wchoice[MAX_WEAPONS];
258 
259     uint8_t user_map;
260     uint8_t screenfade, menubackground;
261     uint8_t shadow_pal;
262 } user_defs;
263 
264 extern user_defs ud;
265 
266 #ifndef ONLY_USERDEFS
267 
268 // this is checked against http://eduke32.com/VERSION
269 extern const char *s_buildDate;
270 
271 extern char boardfilename[BMAX_PATH], currentboardfilename[BMAX_PATH];
272 
G_HaveUserMap(void)273 static inline int G_HaveUserMap(void)
274 {
275     return (boardfilename[0] != 0 && ud.level_number == 7 && ud.volume_number == 0);
276 }
277 
Menu_HaveUserMap(void)278 static inline int Menu_HaveUserMap(void)
279 {
280     return (boardfilename[0] != 0 && ud.m_level_number == 7 && ud.m_volume_number == 0);
281 }
282 
283 extern const char *defaultrtsfilename[GAMECOUNT];
284 extern const char *G_DefaultRtsFile(void);
285 
286 #ifdef LEGACY_ROR
287 extern char ror_protectedsectors[MAXSECTORS];
288 #endif
289 
290 extern float r_ambientlight;
291 
292 extern int32_t g_Debug;
293 extern int32_t g_Shareware;
294 extern int32_t g_cameraClock;
295 extern int32_t g_cameraDistance;
296 extern int32_t g_crosshairSum;
297 extern int32_t g_doQuickSave;
298 extern int32_t g_levelTextTime;
299 extern int32_t g_quitDeadline;
300 extern int32_t g_restorePalette;
301 extern int32_t hud_glowingquotes;
302 extern int32_t hud_showmapname;
303 extern int32_t tempwallptr;
304 extern int32_t ticrandomseed;
305 extern int32_t vote_map;
306 extern int32_t voting;
307 
308 extern int32_t MAXCACHE1DSIZE;
309 //extern int8_t cheatbuf[MAXCHEATLEN],cheatbuflen;
310 
311 #define CROSSHAIR_PAL (MAXPALOOKUPS-RESERVEDPALS-1)
312 
313 extern palette_t CrosshairColors;
314 extern palette_t DefaultCrosshairColors;
315 
316 int32_t A_CheckInventorySprite(spritetype *s);
317 int32_t A_InsertSprite(int16_t whatsect, int32_t s_x, int32_t s_y, int32_t s_z, int16_t s_pn, int8_t s_s, uint8_t s_xr,
318                        uint8_t s_yr, int16_t s_a, int16_t s_ve, int16_t s_zv, int16_t s_ow, int16_t s_ss);
319 int A_Spawn(int spriteNum,int tileNum);
320 int G_DoMoveThings(void);
321 //int32_t G_EndOfLevel(void);
322 
323 #ifdef YAX_ENABLE
324 void Yax_SetBunchZs(int32_t sectnum, int32_t cf, int32_t daz);
325 #else
326 #define Yax_SetBunchZs(sectnum, cf, daz)
327 #endif
328 
329 void G_PostCreateGameState(void);
330 
331 void A_SpawnCeilingGlass(int spriteNum,int sectNum,int glassCnt);
332 void A_SpawnGlass(int spriteNum,int glassCnt);
333 void A_SpawnRandomGlass(int spriteNum,int wallNum,int glassCnt);
334 void A_SpawnWallGlass(int spriteNum,int wallnum,int glassCnt);
335 void A_SpawnWallPopcorn(int spriteNum,int wallnum,int glassCnt);
336 void G_AddUserQuote(const char *daquote);
337 void G_BackToMenu(void);
338 void G_DumpDebugInfo(void);
339 
340 const char* G_PrintYourTime(void);
341 const char* G_PrintParTime(void);
342 const char* G_PrintDesignerTime(void);
343 const char* G_PrintBestTime(void);
344 void G_BonusScreen(int32_t bonusonly);
345 void G_BonusScreenRRRA(int32_t bonusonly);
346 //void G_CheatGetInv(void);
347 void G_DisplayRest(int32_t smoothratio);
348 void G_DoSpriteAnimations(int32_t ourx, int32_t oury, int32_t ourz, int32_t oura, int32_t smoothratio);
349 void G_DrawBackground(void);
350 void G_DrawFrags(void);
351 void G_HandleMirror(int32_t x, int32_t y, int32_t z, fix16_t a, fix16_t horiz, int32_t smoothratio);
352 void G_DrawRooms(int32_t playerNum,int32_t smoothratio);
353 void G_DrawTXDigiNumZ(int32_t starttile,int32_t x,int32_t y,int32_t n,int32_t s,int32_t pal,int32_t cs,int32_t x1,int32_t y1,int32_t x2,int32_t y2,int32_t z);
354 void G_GameExit(const char *msg) ATTRIBUTE((noreturn));
355 void G_GameQuit(void);
356 void G_GetCrosshairColor(void);
357 void G_HandleLocalKeys(void);
358 void G_HandleSpecialKeys(void);
359 void G_UpdateAppTitle(void);
360 void G_PrintGameQuotes(int32_t snum);
361 //void G_SE40(int32_t smoothratio);
362 void G_SetCrosshairColor(int32_t r,int32_t g,int32_t b);
363 void G_Shutdown(void);
364 void G_UpdatePlayerFromMenu(void);
365 void M32RunScript(const char *s);
366 void P_DoQuote(int32_t q,DukePlayer_t *p);
367 void P_SetGamePalette(DukePlayer_t *player, uint32_t palid, int32_t set);
368 void G_OnMotorcycle(DukePlayer_t *pPlayer, int spriteNum);
369 void G_OffMotorcycle(DukePlayer_t *pPlayer);
370 void G_OnBoat(DukePlayer_t *pPlayer, int spriteNum);
371 void G_OffBoat(DukePlayer_t *pPlayer);
372 
373 // Cstat protection mask for (currently) spawned MASKWALL* sprites.
374 // TODO: look at more cases of cstat=(cstat&PROTECTED)|ADDED in A_Spawn()?
375 // 2048+(32+16)+8+4
376 #define SPAWN_PROTECT_CSTAT_MASK (CSTAT_SPRITE_NOSHADE|CSTAT_SPRITE_ALIGNMENT_SLAB|CSTAT_SPRITE_XFLIP|CSTAT_SPRITE_YFLIP);
377 
378 void fadepal(int32_t r,int32_t g,int32_t b,int32_t start,int32_t end,int32_t step);
379 //void fadepaltile(int32_t r,int32_t g,int32_t b,int32_t start,int32_t end,int32_t step,int32_t tile);
380 void G_InitTimer(int32_t ticspersec);
381 
G_GetTeamPalette(int32_t team)382 static inline int32_t G_GetTeamPalette(int32_t team)
383 {
384     int8_t pal[] = { 3, 10, 11, 12 };
385 
386     if ((unsigned)team >= ARRAY_SIZE(pal))
387         return 0;
388 
389     return pal[team];
390 }
391 
392 #define A_CheckSpriteFlags(spriteNum, iType) (((g_tile[sprite[spriteNum].picnum].flags^actor[spriteNum].flags) & iType) != 0)
393 // (unsigned)iPicnum check: AMC TC Rusty Nails, bayonet MG alt. fire, iPicnum == -1 (via aplWeaponShoots)
394 #define A_CheckSpriteTileFlags(iPicnum, iType) (((unsigned)iPicnum < MAXTILES) && (g_tile[iPicnum].flags & iType) != 0)
395 #define S_StopSound(num) S_StopEnvSound(num, -1)
396 
397 extern int G_StartRTS(int lumpNum, int localPlayer);
398 
399 extern void G_MaybeAllocPlayer(int32_t pnum);
400 
G_HandleAsync(void)401 static inline void G_HandleAsync(void)
402 {
403     handleevents();
404     Net_GetPackets();
405 }
406 
calc_smoothratio_demo(ClockTicks totalclk,ClockTicks ototalclk)407 static inline int32_t calc_smoothratio_demo(ClockTicks totalclk, ClockTicks ototalclk)
408 {
409     int32_t rfreq = (refreshfreq != -1 ? refreshfreq : 60);
410     uint64_t elapsedFrames = tabledivide64(((uint64_t) (totalclk - ototalclk).toScale16()) * rfreq, 65536*TICRATE);
411 #if 0
412     //POGO: additional debug info for testing purposes
413     OSD_Printf("Elapsed frames: %" PRIu64 ", smoothratio: %" PRIu64 "\n", elapsedFrames, tabledivide64(65536*elapsedFrames*REALGAMETICSPERSEC, rfreq));
414 #endif
415     return clamp(tabledivide64(65536*elapsedFrames*REALGAMETICSPERSEC, rfreq), 0, 65536);
416 }
417 
calc_smoothratio(ClockTicks totalclk,ClockTicks ototalclk)418 static inline int32_t calc_smoothratio(ClockTicks totalclk, ClockTicks ototalclk)
419 {
420     if (!((ud.show_help == 0 && (!g_netServer && ud.multimode < 2) && ((g_player[myconnectindex].ps->gm & MODE_MENU) == 0)) ||
421           (g_netServer || ud.multimode > 1) ||
422           ud.recstat == 2) ||
423         ud.pause_on)
424     {
425         return 65536;
426     }
427 
428     return calc_smoothratio_demo(totalclk, ototalclk);
429 }
430 
431 // sector effector lotags
432 enum
433 {
434     SE_0_ROTATING_SECTOR              = 0,
435     SE_1_PIVOT                        = 1,
436     SE_2_EARTHQUAKE                   = 2,
437     SE_3_RANDOM_LIGHTS_AFTER_SHOT_OUT = 3,
438     SE_4_RANDOM_LIGHTS                = 4,
439     SE_5                              = 5,
440     SE_6_SUBWAY                       = 6,
441     // ^^ potentially incomplete substitution in code
442     // vv almost surely complete substitution
443     SE_7_TELEPORT                      = 7,
444     SE_8_UP_OPEN_DOOR_LIGHTS           = 8,
445     SE_9_DOWN_OPEN_DOOR_LIGHTS         = 9,
446     SE_10_DOOR_AUTO_CLOSE              = 10,
447     SE_11_SWINGING_DOOR                = 11,
448     SE_12_LIGHT_SWITCH                 = 12,
449     SE_13_EXPLOSIVE                    = 13,
450     SE_14_SUBWAY_CAR                   = 14,
451     SE_15_SLIDING_DOOR                 = 15,
452     SE_16_REACTOR                      = 16,
453     SE_17_WARP_ELEVATOR                = 17,
454     SE_18_INCREMENTAL_SECTOR_RISE_FALL = 18,
455     SE_19_EXPLOSION_LOWERS_CEILING     = 19,
456     SE_20_STRETCH_BRIDGE               = 20,
457     SE_21_DROP_FLOOR                   = 21,
458     SE_22_TEETH_DOOR                   = 22,
459     SE_23_ONE_WAY_TELEPORT             = 23,
460     SE_24_CONVEYOR                     = 24,
461     SE_25_PISTON                       = 25,
462     SE_26                              = 26,
463     SE_27_DEMO_CAM                     = 27,
464     SE_28_LIGHTNING                    = 28,
465     SE_29_WAVES                        = 29,
466     SE_30_TWO_WAY_TRAIN                = 30,
467     SE_31_FLOOR_RISE_FALL              = 31,
468     SE_32_CEILING_RISE_FALL            = 32,
469     SE_33_QUAKE_DEBRIS                 = 33,
470     SE_34                              = 34,  // XXX
471     SE_35                              = 35,  // XXX
472     SE_36_PROJ_SHOOTER                 = 36,
473     SE_49_POINT_LIGHT                  = 49,
474     SE_50_SPOT_LIGHT                   = 50,
475     SE_77                              = 77,
476     SE_130                             = 130,
477     SE_131                             = 131,
478 };
479 
480 // sector lotags
481 enum
482 {
483     ST_0_NO_EFFECT   = 0,
484     ST_1_ABOVE_WATER = 1,
485     ST_2_UNDERWATER  = 2,
486     ST_3             = 3,
487     // ^^^ maybe not complete substitution in code
488     ST_9_SLIDING_ST_DOOR     = 9,
489     ST_15_WARP_ELEVATOR      = 15,
490     ST_16_PLATFORM_DOWN      = 16,
491     ST_17_PLATFORM_UP        = 17,
492     ST_18_ELEVATOR_DOWN      = 18,
493     ST_19_ELEVATOR_UP        = 19,
494     ST_20_CEILING_DOOR       = 20,
495     ST_21_FLOOR_DOOR         = 21,
496     ST_22_SPLITTING_DOOR     = 22,
497     ST_23_SWINGING_DOOR      = 23,
498     ST_25_SLIDING_DOOR       = 25,
499     ST_26_SPLITTING_ST_DOOR  = 26,
500     ST_27_STRETCH_BRIDGE     = 27,
501     ST_28_DROP_FLOOR         = 28,
502     ST_29_TEETH_DOOR         = 29,
503     ST_30_ROTATE_RISE_BRIDGE = 30,
504     ST_31_TWO_WAY_TRAIN      = 31,
505     // left: ST 32767, 65534, 65535
506 };
507 
508 
509 #define G_ModDirSnprintf(buf, size, basename, ...)                                                                          \
510     \
511 (((g_modDir[0] != '/') ? Bsnprintf(buf, size, "%s/" basename, g_modDir, ##__VA_ARGS__)                                      \
512                        : Bsnprintf(buf, size, basename, ##__VA_ARGS__)) >= ((int32_t)size) - 1\
513 )
514 #define G_ModDirSnprintfLite(buf, size, basename)                                                                          \
515     \
516 ((g_modDir[0] != '/') ? Bsnprintf(buf, size, "%s/%s", g_modDir, basename)                                      \
517                       : Bsnprintf(buf, size, basename))
518 
G_NewGame_EnterLevel(void)519 static inline void G_NewGame_EnterLevel(void)
520 {
521     G_NewGame(ud.m_volume_number, ud.m_level_number, ud.m_player_skill);
522 
523     if (G_EnterLevel(MODE_GAME))
524         G_BackToMenu();
525 }
526 
G_GetMusicIdx(const char * str)527 static inline int G_GetMusicIdx(const char *str)
528 {
529     int32_t lev, ep;
530     signed char b1, b2;
531 
532     int numMatches = sscanf(str, "%c%d%c%d", &b1,&ep, &b2,&lev);
533 
534     if (numMatches != 4 || Btoupper(b1) != 'E' || Btoupper(b2) != 'L')
535         return -1;
536 
537     if ((unsigned)--lev >= MAXLEVELS || (unsigned)--ep >= MAXVOLUMES)
538         return -2;
539 
540     return (ep * MAXLEVELS) + lev;
541 }
542 
543 extern void G_PrintCurrentMusic(void);
544 
545 EXTERN_INLINE_HEADER void G_SetStatusBarScale(int32_t sc);
546 
547 EXTERN_INLINE_HEADER void SetIfGreater(int32_t *variable, int32_t potentialValue);
548 
549 #endif
550 
551 #ifdef __cplusplus
552 }
553 #endif
554 
555 #ifndef ONLY_USERDEFS
556 
557 template <typename T>
G_GetViewscreenSizeShift(T const * tspr)558 static inline int G_GetViewscreenSizeShift(T const *tspr)
559 {
560 #if VIEWSCREENFACTOR == 0
561     UNREFERENCED_PARAMETER(tspr);
562     return VIEWSCREENFACTOR;
563 #else
564     static const int mask = (1<<VIEWSCREENFACTOR)-1;
565     const int rem = (tspr->xrepeat & mask) | (tspr->yrepeat & mask);
566 
567     for (bssize_t i=0; i < VIEWSCREENFACTOR; i++)
568         if (rem & (1<<i))
569             return i;
570 
571     return VIEWSCREENFACTOR;
572 #endif
573 }
574 
575 #if defined game_c_ || !defined DISABLE_INLINING
576 
G_SetStatusBarScale(int32_t sc)577 EXTERN_INLINE void G_SetStatusBarScale(int32_t sc)
578 {
579     ud.statusbarscale = clamp(sc, 36, 100);
580     G_UpdateScreenArea();
581 }
582 
583 // the point of this is to prevent re-running a function or calculation passed to potentialValue
584 // without making a new variable under each individual circumstance
SetIfGreater(int32_t * variable,int32_t potentialValue)585 EXTERN_INLINE void SetIfGreater(int32_t *variable, int32_t potentialValue)
586 {
587     if (potentialValue > *variable)
588         *variable = potentialValue;
589 }
590 
591 #endif
592 
593 #endif
594 
595 #endif
596