From d0936017ccb8a078d1b03f55478af284bb015bbc Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Tue, 15 Jun 2021 18:44:26 +0300 Subject: [PATCH] cleanup: remove g_main.pas --- src/game/Doom2DF.lpr | 597 +++++++++++++++-- src/game/g_console.pas | 2 +- src/game/g_game.pas | 350 +++++++++- src/game/g_holmes.pas | 2 +- src/game/g_items.pas | 4 +- src/game/g_main.pas | 1010 ----------------------------- src/game/g_map.pas | 2 +- src/game/g_menu.pas | 2 +- src/game/g_monsters.pas | 2 +- src/game/g_net.pas | 4 +- src/game/g_netmsg.pas | 2 +- src/game/g_options.pas | 24 +- src/game/g_player.pas | 2 +- src/game/g_playermodel.pas | 2 +- src/game/g_res_downloader.pas | 4 +- src/game/g_saveload.pas | 4 +- src/game/g_triggers.pas | 2 +- src/game/g_weapons.pas | 2 +- src/game/g_window.pas | 77 ++- src/game/opengl/r_console.pas | 4 +- src/game/opengl/r_playermodel.pas | 4 +- src/game/sdl/g_system.pas | 10 +- src/game/sdl2/g_system.pas | 10 +- src/game/sdl2/g_touch.pas | 2 +- src/game/stub/g_system.pas | 3 + 25 files changed, 1039 insertions(+), 1088 deletions(-) delete mode 100644 src/game/g_main.pas diff --git a/src/game/Doom2DF.lpr b/src/game/Doom2DF.lpr index f42c4b5..bbbcdd3 100644 --- a/src/game/Doom2DF.lpr +++ b/src/game/Doom2DF.lpr @@ -27,7 +27,10 @@ uses ctypes, {$ENDIF} {$IFDEF UNIX} - cthreads, + cthreads, BaseUnix, +{$ENDIF} +{$IFDEF DARWIN} + MacOSAll, CocoaAll, {$ENDIF} mempool in '../shared/mempool.pas', conbuf in '../shared/conbuf.pas', @@ -123,7 +126,6 @@ uses g_gfx in 'g_gfx.pas', g_gui in 'g_gui.pas', g_items in 'g_items.pas', - g_main in 'g_main.pas', g_map in 'g_map.pas', g_menu in 'g_menu.pas', g_monsters in 'g_monsters.pas', @@ -204,20 +206,527 @@ uses {$R *.res} {$ENDIF} -{$IFDEF ANDROID} -function SDL_main(argc: CInt; argv: PPChar): CInt; cdecl; -{$ENDIF ANDROID} + var + noct: Boolean = False; + binPath: AnsiString = ''; + forceBinDir: Boolean = False; -var - f: Integer; - noct: Boolean = false; -{$IFDEF ANDROID} - storage: String; +function GetBinaryPath (): AnsiString; + {$IFDEF LINUX} + var sl: AnsiString; + {$ENDIF} +begin + result := ExtractFilePath(ParamStr(0)); + {$IFDEF LINUX} + // it may be a symlink; do some guesswork here + sl := fpReadLink(ExtractFileName(ParamStr(0))); + if (sl = ParamStr(0)) then + begin + // use current directory, as we don't have anything better + //result := '.'; + GetDir(0, result); + end; + {$ENDIF} + result := fixSlashes(result); + if (length(result) > 0) and (result[length(result)] <> '/') then + result := result + '/'; +end; + +procedure PrintDirs (msg: AnsiString; dirs: SSArray); + var dir: AnsiString; +begin + e_LogWriteln(msg + ':'); + for dir in dirs do + e_LogWriteln(' ' + dir); +end; + +{$IFDEF DARWIN} + function NSStringToAnsiString (s: NSString): AnsiString; + var i: Integer; + begin + result := ''; + for i := 0 to s.length - 1 do + result := result + AnsiChar(s.characterAtIndex(i)); + end; + + function GetBundlePath (): AnsiString; + var pathRef: CFURLRef; pathCFStr: CFStringRef; pathStr: ShortString; + begin + pathRef := CFBundleCopyBundleURL(CFBundleGetMainBundle()); + pathCFStr := CFURLCopyFileSystemPath(pathRef, kCFURLPOSIXPathStyle); + CFStringGetPascalString(pathCFStr, @pathStr, 255, CFStringGetSystemEncoding()); + CFRelease(pathRef); + CFRelease(pathCFStr); + Result := pathStr; + end; {$ENDIF} - //tfo: Text; + +procedure InitPath; + var i: Integer; rwdir, rodir: AnsiString; rwdirs, rodirs: SSArray; + + procedure AddDir (var dirs: SSArray; append: AnsiString); + begin + SetLength(dirs, Length(dirs) + 1); + dirs[High(dirs)] := ExpandFileName(append) + end; + + function IsSep (ch: Char): Boolean; + begin + {$IFDEF WINDOWS} + result := (ch = '/') or (ch = '\'); + {$ELSE} + result := (ch = '/'); + {$ENDIF} + end; + + function OptimizePath (dir: AnsiString): AnsiString; + var i, len: Integer; s: AnsiString; + begin + i := 1; len := Length(dir); s := ''; + while i <= len do + begin + if IsSep(dir[i]) then + begin + s := s + DirectorySeparator; + Inc(i); + while (i <= len) and IsSep(dir[i]) do Inc(i); + if (i <= len) and (dir[i] = '.') then + begin + if (i = len) or IsSep(dir[i + 1]) then + begin + Inc(i) + end + else if (i + 1 <= len) and (dir[i + 1] = '.') then + begin + if (i + 1 = len) or IsSep(dir[i + 2]) then + begin + s := e_UpperDir(s); + Inc(i, 2) + end + end + end + end + else + begin + s := s + dir[i]; + Inc(i) + end + end; + result := s + end; + + procedure OptimizeDirs (var dirs: SSArray); + var i, j, k: Integer; + begin + for i := 0 to High(dirs) do + dirs[i] := OptimizePath(dirs[i]); + // deduplicate + i := High(dirs); + while i >= 0 do + begin + j := 0; + while j < i do + begin + if dirs[j] = dirs[i] then + begin + for k := j + 1 to High(dirs) do + dirs[k - 1] := dirs[k]; + Dec(i); + SetLength(dirs, High(dirs)) + end + else + begin + Inc(j) + end + end; + Dec(i) + end + end; + + procedure AddDef (var dirs: SSArray; base: SSArray; append: AnsiString); + var s: AnsiString; + begin + if Length(dirs) = 0 then + for s in base do + AddDir(dirs, e_CatPath(s, append)); + OptimizeDirs(dirs) + end; + + function GetDefaultRODirs (): SSArray; + {$IF DEFINED(UNIX) AND NOT DEFINED(DARWIN) AND NOT DEFINED(ANDROID)} + var home: AnsiString; + {$ENDIF} + {$IFDEF WINDOWS} + var appdata: AnsiString; + {$ENDIF} + {$IFDEF DARWIN} + var bundle, s: AnsiString; dirArr: NSArray; i: Integer; + {$ENDIF} + begin + result := nil; + {$IFDEF DARWIN} + bundle := GetBundlePath(); + if ExtractFileExt(bundle) <> '.app' then + AddDir(result, binpath); + {$ELSE} + AddDir(result, binPath); + {$ENDIF} + if forceBinDir = false then + begin + {$IFDEF USE_SDL2} + AddDir(result, SDL_GetBasePath()); + AddDir(result, SDL_GetPrefPath('', 'doom2df')); + {$ENDIF} + {$IFDEF WINDOWS} + appdata := GetEnvironmentVariable('APPDATA') + '\doom2df'; + if appdata <> '' then + AddDir(result, appdata); + {$ENDIF} + {$IF DEFINED(UNIX) AND NOT DEFINED(DARWIN) AND NOT DEFINED(ANDROID)} + AddDir(result, '/usr/share/doom2df'); + AddDir(result, '/usr/local/share/doom2df'); + home := GetEnvironmentVariable('HOME'); + if home <> '' then + AddDir(result, e_CatPath(home, '.doom2df')); + {$ENDIF} + {$IFDEF DARWIN} + bundle := GetBundlePath(); + if bundle <> '' then + AddDir(result, e_CatPath(bundle, 'Contents/Resources')); + dirArr := NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, true); + for i := 0 to dirArr.count - 1 do + begin + s := NSStringToAnsiString(dirArr.objectAtIndex(i)); + AddDir(result, e_CatPath(s, 'Doom 2D Forever')) + end; + {$ENDIF} + {$IF DEFINED(ANDROID) AND DEFINED(USE_SDL2)} + AddDir(result, SDL_AndroidGetInternalStoragePath()); + if SDL_AndroidGetExternalStorageState() <> 0 then + AddDir(result, SDL_AndroidGetExternalStoragePath()); + {$ENDIF} + end + end; + + function GetDefaultRWDirs (): SSArray; + {$IF DEFINED(UNIX) AND NOT DEFINED(DARWIN) AND NOT DEFINED(ANDROID)} + var home: AnsiString; + {$ENDIF} + {$IFDEF WINDOWS} + var appdata: AnsiString; + {$ENDIF} + {$IFDEF DARWIN} + var bundle, s: AnsiString; dirArr: NSArray; i: Integer; + {$ENDIF} + begin + result := nil; + {$IFDEF DARWIN} + bundle := GetBundlePath(); + if ExtractFileExt(bundle) <> '.app' then + AddDir(result, binPath); + {$ELSE} + AddDir(result, binPath); + {$ENDIF} + if forceBinDir = false then + begin + {$IFDEF USE_SDL2} + AddDir(result, SDL_GetPrefPath('', 'doom2df')); + {$ENDIF} + {$IFDEF WINDOWS} + appdata := GetEnvironmentVariable('APPDATA') + '\doom2df'; + if appdata <> '' then + AddDir(result, appdata); + {$ENDIF} + {$IF DEFINED(UNIX) AND NOT DEFINED(DARWIN) AND NOT DEFINED(ANDROID)} + home := GetEnvironmentVariable('HOME'); + if home <> '' then + AddDir(result, e_CatPath(home, '.doom2df')); + {$ENDIF} + {$IFDEF DARWIN} + dirArr := NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, true); + for i := 0 to dirArr.count - 1 do + begin + s := NSStringToAnsiString(dirArr.objectAtIndex(i)); + AddDir(result, e_CatPath(s, 'Doom 2D Forever')) + end; + {$ENDIF} + {$IF DEFINED(ANDROID) AND DEFINED(USE_SDL2)} + if SDL_AndroidGetExternalStorageState() <> 0 then + AddDir(result, SDL_AndroidGetExternalStoragePath()); + {$ENDIF} + end + end; + begin - SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]); //k8: fuck off, that's why + forceBinDir := false; + binPath := GetBinaryPath(); + + i := 1; + while i < ParamCount do + begin + case ParamStr(i) of + '--like-windoze': forceBinDir := true; + '--rw-dir': + begin + Inc(i); + rwdir := ParamStr(i); + (* RW *) + AddDir(LogDirs, e_CatPath(rwdir, '')); + AddDir(SaveDirs, e_CatPath(rwdir, 'data')); + AddDir(CacheDirs, e_CatPath(rwdir, 'data/cache')); + AddDir(ConfigDirs, e_CatPath(rwdir, '')); + AddDir(MapDownloadDirs, e_CatPath(rwdir, 'maps/downloads')); + AddDir(WadDownloadDirs, e_CatPath(rwdir, 'wads/downloads')); + AddDir(ScreenshotDirs, e_CatPath(rwdir, 'screenshots')); + AddDir(StatsDirs, e_CatPath(rwdir, 'stats')); + (* RO *) + AddDir(DataDirs, e_CatPath(rwdir, 'data')); + AddDir(ModelDirs, e_CatPath(rwdir, 'data/models')); + AddDir(MegawadDirs, e_CatPath(rwdir, 'maps/megawads')); + AddDir(MapDirs, e_CatPath(rwdir, 'maps')); + AddDir(WadDirs, e_CatPath(rwdir, 'wads')); + end; + '--ro-dir': + begin + Inc(i); + rodir := ParamStr(i); + (* RO *) + AddDir(DataDirs, e_CatPath(rodir, 'data')); + AddDir(ModelDirs, e_CatPath(rodir, 'data/models')); + AddDir(MegawadDirs, e_CatPath(rodir, 'maps/megawads')); + AddDir(MapDirs, e_CatPath(rodir, 'maps')); + AddDir(WadDirs, e_CatPath(rodir, 'wads')); + end; + '--game-wad': + begin + Inc(i); + GameWADName := ParamStr(i); + end; + '--config': + begin + Inc(i); + gConfigScript := ParamStr(i); + end; + end; + Inc(i) + end; + + // prefer bin dir if it writable and contains game.wad + if forceBinDir = false then + begin + if findDiskWad(binPath + 'data' + '/' + GameWADName) <> '' then + if e_CanCreateFilesAt(binPath) then + forceBinDir := true + end; + + (* RO *) + rodirs := GetDefaultRODirs(); + AddDef(DataDirs, rodirs, 'data'); + AddDef(ModelDirs, rodirs, 'data/models'); + AddDef(MegawadDirs, rodirs, 'maps/megawads'); + AddDef(MapDirs, rodirs, 'maps'); + AddDef(WadDirs, rodirs, 'wads'); + + (* RW *) + rwdirs := GetDefaultRWDirs(); + AddDef(LogDirs, rwdirs, ''); + AddDef(SaveDirs, rwdirs, 'data'); + AddDef(CacheDirs, rwdirs, 'data/cache'); + AddDef(ConfigDirs, rwdirs, ''); + AddDef(MapDownloadDirs, rwdirs, 'maps/downloads'); + AddDef(WadDownloadDirs, rwdirs, 'wads/downloads'); + AddDef(ScreenshotDirs, rwdirs, 'screenshots'); + AddDef(StatsDirs, rwdirs, 'stats'); + + for i := 0 to High(MapDirs) do + AddDir(AllMapDirs, MapDirs[i]); + for i := 0 to High(MegawadDirs) do + AddDir(AllMapDirs, MegawadDirs[i]); + OptimizeDirs(AllMapDirs); + + if LogFileName = '' then + begin + rwdir := e_GetWriteableDir(LogDirs, false); + if rwdir <> '' then + begin + {$IFDEF HEADLESS} + LogFileName := e_CatPath(rwdir, 'Doom2DF_H.log'); + {$ELSE} + LogFileName := e_CatPath(rwdir, 'Doom2DF.log'); + {$ENDIF} + end + end; + + // HACK: ensure the screenshots folder also has a stats subfolder in it + rwdir := e_GetWriteableDir(ScreenshotDirs, false); + if rwdir <> '' then CreateDir(rwdir + '/stats'); +end; + +procedure InitPrep; + {$IF DEFINED(ANDROID) AND DEFINED(USE_SDLMIXER)} + var timiditycfg: AnsiString; + {$ENDIF} + var i: Integer; +begin + {$IFDEF HEADLESS} + conbufDumpToStdOut := true; + {$ENDIF} + for i := 1 to ParamCount do + begin + case ParamStr(i) of + '--con-stdout': conbufDumpToStdOut := true; + '--no-fbo': glRenderToFBO := false; + end + end; + + if LogFileName <> '' then + e_InitLog(LogFileName, TWriteMode.WM_NEWFILE); + e_InitWritelnDriver(); + e_WriteLog('Doom 2D: Forever version ' + GAME_VERSION + ' proto ' + IntToStr(NET_PROTOCOL_VER), TMsgType.Notify); + e_WriteLog('Build date: ' + GAME_BUILDDATE + ' ' + GAME_BUILDTIME, TMsgType.Notify); + e_WriteLog('Build hash: ' + g_GetBuildHash(), TMsgType.Notify); + e_WriteLog('Build by: ' + g_GetBuilderName(), TMsgType.Notify); + + e_LogWritefln('Force bin dir: %s', [forceBinDir], TMsgType.Notify); + e_LogWritefln('BINARY PATH: [%s]', [binPath], TMsgType.Notify); + + PrintDirs('DataDirs', DataDirs); + PrintDirs('ModelDirs', ModelDirs); + PrintDirs('MegawadDirs', MegawadDirs); + PrintDirs('MapDirs', MapDirs); + PrintDirs('WadDirs', WadDirs); + + PrintDirs('LogDirs', LogDirs); + PrintDirs('SaveDirs', SaveDirs); + PrintDirs('CacheDirs', CacheDirs); + PrintDirs('ConfigDirs', ConfigDirs); + PrintDirs('ScreenshotDirs', ScreenshotDirs); + PrintDirs('StatsDirs', StatsDirs); + PrintDirs('MapDownloadDirs', MapDownloadDirs); + PrintDirs('WadDownloadDirs', WadDownloadDirs); + + GameWAD := e_FindWad(DataDirs, GameWADName); + if GameWad = '' then + begin + e_WriteLog('WAD ' + GameWADName + ' not found in data directories.', TMsgType.Fatal); + {$IF DEFINED(USE_SDL2) AND NOT DEFINED(HEADLESS)} + if forceBinDir = false then + SDL_ShowSimpleMessageBox( + SDL_MESSAGEBOX_ERROR, + 'Doom 2D Forever', + PChar('WAD ' + GameWADName + ' not found in data directories.'), + nil + ); + {$ENDIF} + e_DeinitLog; + Halt(1); + end; + + {$IF DEFINED(ANDROID) AND DEFINED(USE_SDLMIXER)} + timiditycfg := 'timidity.cfg'; + if e_FindResource(ConfigDirs, timiditycfg) = true then + begin + timiditycfg := ExpandFileName(timiditycfg); + SetEnvVar('TIMIDITY_CFG', timiditycfg); + e_LogWritefln('Set TIMIDITY_CFG = "%s"', [timiditycfg]); + end; + {$ENDIF} +end; + +procedure Main; +{$IFDEF ENABLE_HOLMES} + var flexloaded: Boolean; +{$ENDIF} +begin + InitPath; + InitPrep; + e_InitInput; + sys_Init; + + sys_CharPress := @CharPress; + + g_Options_SetDefault; + g_Options_SetDefaultVideo; + g_Console_SysInit; + if sys_SetDisplayMode(gRC_Width, gRC_Height, gBPP, gRC_FullScreen, gRC_Maximized) = False then + raise Exception.Create('Failed to set videomode on startup.'); + + e_WriteLog(gLanguage, TMsgType.Notify); + g_Language_Set(gLanguage); + +{$IF not DEFINED(HEADLESS) and DEFINED(ENABLE_HOLMES)} + flexloaded := true; + if not fuiAddWad('flexui.wad') then + begin + if not fuiAddWad('./data/flexui.wad') then fuiAddWad('./flexui.wad'); + end; + try + fuiGfxLoadFont('win8', 'flexui/fonts/win8.fuifont'); + fuiGfxLoadFont('win14', 'flexui/fonts/win14.fuifont'); + fuiGfxLoadFont('win16', 'flexui/fonts/win16.fuifont'); + fuiGfxLoadFont('dos8', 'flexui/fonts/dos8.fuifont'); + fuiGfxLoadFont('msx6', 'flexui/fonts/msx6.fuifont'); + except on e: Exception do + begin + writeln('ERROR loading FlexUI fonts'); + flexloaded := false; + //raise; + end; + else + begin + flexloaded := false; + //raise; + end; + end; + if (flexloaded) then + begin + try + e_LogWriteln('FlexUI: loading stylesheet...'); + uiLoadStyles('flexui/widgets.wgs'); + except on e: TParserException do + begin + writeln('ERROR at (', e.tokLine, ',', e.tokCol, '): ', e.message); + //raise; + flexloaded := false; + end; + else + begin + //raise; + flexloaded := false; + end; + end; + end; + g_holmes_imfunctional := not flexloaded; + + if (not g_holmes_imfunctional) then + begin + uiInitialize(); + uiContext.font := 'win14'; + end; + + if assigned(oglInitCB) then oglInitCB; +{$ENDIF} + + //g_Res_CreateDatabases(true); // it will be done before connecting to the server for the first time + + e_WriteLog('Entering SDLMain', TMsgType.Notify); + + {$WARNINGS OFF} + SDLMain(); + {$WARNINGS ON} + {$IFDEF ENABLE_HOLMES} + if assigned(oglDeinitCB) then oglDeinitCB; + {$ENDIF} + + g_Console_WriteGameConfig; + sys_Final; +end; + + +procedure EntryParams; + var f: Integer; +begin f := 1; while f <= ParamCount do begin @@ -230,45 +739,43 @@ begin begin Inc(f); LogFileName := ParamStr(f) - end; + end end; Inc(f) - end; + end +end; +procedure EntryPoint; +begin + SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]); //k8: fuck off, that's why + EntryParams; if noct then - begin - Main() - end + Main else - begin - try - Main(); - e_WriteLog('Shutdown with no errors.', TMsgType.Notify); - except - on e: Exception do - begin - e_WriteStackTrace(e.message); - //e_WriteLog(Format(_lc[I_SYSTEM_ERROR_MSG], [E.Message]), MSG_FATALERROR); - (* - AssignFile(tfo, GameDir+'/trace.log'); - {$I-} - Append(tfo); - if (IOResult <> 0) then Rewrite(tfo); - if (IOResult = 0) then begin writeln(tfo, '====================='); DumpExceptionBackTrace(tfo); CloseFile(tfo); end; - *) - end - else - begin - //e_WriteLog(Format(_lc[I_SYSTEM_ERROR_UNKNOWN], [NativeUInt(ExceptAddr())]), MSG_FATALERROR); - e_WriteStackTrace('FATAL ERROR'); - end; - end; + try + Main; + e_WriteLog('Shutdown with no errors.', TMsgType.Notify) + except on e: Exception do + e_WriteStackTrace(e.message) + else + e_WriteStackTrace('FATAL ERROR') end; - e_DeinitLog(); + + e_DeinitLog; +end; {$IFDEF ANDROID} - result := 0; -end; // SDL_main -exports SDL_main; -{$ENDIF ANDROID} + function SDL_main (argc: CInt; argv: PPChar): CInt; cdecl; + begin + // TODO pass argc+argv to rtl + EntryPoint; + result := 0 + end; + + exports SDL_main; +{$ELSE} +begin + EntryPoint +{$ENDIF} + end. diff --git a/src/game/g_console.pas b/src/game/g_console.pas index 9db9e79..02beb87 100644 --- a/src/game/g_console.pas +++ b/src/game/g_console.pas @@ -99,7 +99,7 @@ var implementation uses - g_textures, g_main, e_input, g_game, g_gfx, g_player, g_items, + g_textures, e_input, g_game, g_gfx, g_player, g_items, SysUtils, g_basic, g_options, Math, g_touch, e_res, g_menu, g_gui, g_language, g_net, g_netmsg, e_log, conbuf; diff --git a/src/game/g_game.pas b/src/game/g_game.pas index 6fc6035..9095b1d 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -148,6 +148,9 @@ function IsActivePlayer(p: TPlayer): Boolean; function GetActivePlayerID_Next(Skip: Integer = -1): Integer; procedure SortGameStat(var stat: TPlayerStatArray); +procedure KeyPress (K: Word); +procedure CharPress (C: AnsiChar); + { procedure SetWinPause(Enable: Boolean); } const @@ -440,10 +443,355 @@ uses e_input, e_log, g_console, r_console, g_items, g_map, g_panel, g_playermodel, g_gfx, g_options, Math, g_triggers, g_monsters, e_sound, CONFIG, - g_language, g_net, g_main, g_phys, + g_language, g_net, g_phys, ENet, e_msg, g_netmsg, g_netmaster, sfs, wadreader, g_system, r_playermodel; + var + charbuff: packed array [0..15] of AnsiChar = ( + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' + ); + +function Translit (const S: AnsiString): AnsiString; +var + i: Integer; +begin + Result := S; + for i := 1 to Length(Result) do + begin + case Result[i] of + #$C9: Result[i] := 'Q'; + #$D6: Result[i] := 'W'; + #$D3: Result[i] := 'E'; + #$CA: Result[i] := 'R'; + #$C5: Result[i] := 'T'; + #$CD: Result[i] := 'Y'; + #$C3: Result[i] := 'U'; + #$D8: Result[i] := 'I'; + #$D9: Result[i] := 'O'; + #$C7: Result[i] := 'P'; + #$D5: Result[i] := '['; //Chr(219); + #$DA: Result[i] := ']'; //Chr(221); + #$D4: Result[i] := 'A'; + #$DB: Result[i] := 'S'; + #$C2: Result[i] := 'D'; + #$C0: Result[i] := 'F'; + #$CF: Result[i] := 'G'; + #$D0: Result[i] := 'H'; + #$CE: Result[i] := 'J'; + #$CB: Result[i] := 'K'; + #$C4: Result[i] := 'L'; + #$C6: Result[i] := ';'; //Chr(186); + #$DD: Result[i] := #39; //Chr(222); + #$DF: Result[i] := 'Z'; + #$D7: Result[i] := 'X'; + #$D1: Result[i] := 'C'; + #$CC: Result[i] := 'V'; + #$C8: Result[i] := 'B'; + #$D2: Result[i] := 'N'; + #$DC: Result[i] := 'M'; + #$C1: Result[i] := ','; //Chr(188); + #$DE: Result[i] := '.'; //Chr(190); + end; + end; +end; + + +function CheckCheat (ct: TStrings_Locale; eofs: Integer=0): Boolean; +var + ls1, ls2: string; +begin + ls1 := CheatEng[ct]; + ls2 := Translit(CheatRus[ct]); + if length(ls1) = 0 then ls1 := '~'; + if length(ls2) = 0 then ls2 := '~'; + result := + (Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1)) = ls1) or + (Translit(Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1))) = ls1) or + (Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2)) = ls2) or + (Translit(Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2))) = ls2); + { + if ct = I_GAME_CHEAT_JETPACK then + begin + e_WriteLog('ls1: ['+ls1+']', MSG_NOTIFY); + e_WriteLog('ls2: ['+ls2+']', MSG_NOTIFY); + e_WriteLog('bf0: ['+Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1))+']', MSG_NOTIFY); + e_WriteLog('bf1: ['+Translit(Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1)))+']', MSG_NOTIFY); + e_WriteLog('bf2: ['+Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2))+']', MSG_NOTIFY); + e_WriteLog('bf3: ['+Translit(Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2)))+']', MSG_NOTIFY); + end; + } +end; + +procedure Cheat (); +const + CHEAT_DAMAGE = 500; +label + Cheated; +var + s, s2: string; + c: ShortString; + a: Integer; +begin + { + if (not gGameOn) or (not gCheats) or ((gGameSettings.GameType <> GT_SINGLE) and + (gGameSettings.GameMode <> GM_COOP) and (not gDebugMode)) + or g_Game_IsNet then Exit; + } + if not gGameOn then exit; + if not conIsCheatsEnabled then exit; + + s := 'SOUND_GAME_RADIO'; + + // + if CheckCheat(I_GAME_CHEAT_GODMODE) then + begin + if gPlayer1 <> nil then gPlayer1.GodMode := not gPlayer1.GodMode; + if gPlayer2 <> nil then gPlayer2.GodMode := not gPlayer2.GodMode; + goto Cheated; + end; + // RAMBO + if CheckCheat(I_GAME_CHEAT_WEAPONS) then + begin + if gPlayer1 <> nil then gPlayer1.AllRulez(False); + if gPlayer2 <> nil then gPlayer2.AllRulez(False); + goto Cheated; + end; + // TANK + if CheckCheat(I_GAME_CHEAT_HEALTH) then + begin + if gPlayer1 <> nil then gPlayer1.AllRulez(True); + if gPlayer2 <> nil then gPlayer2.AllRulez(True); + goto Cheated; + end; + // IDDQD + if CheckCheat(I_GAME_CHEAT_DEATH) then + begin + if gPlayer1 <> nil then gPlayer1.Damage(CHEAT_DAMAGE, 0, 0, 0, HIT_TRAP); + if gPlayer2 <> nil then gPlayer2.Damage(CHEAT_DAMAGE, 0, 0, 0, HIT_TRAP); + s := 'SOUND_MONSTER_HAHA'; + goto Cheated; + end; + // + if CheckCheat(I_GAME_CHEAT_DOORS) then + begin + g_Triggers_OpenAll(); + goto Cheated; + end; + // GOODBYE + if CheckCheat(I_GAME_CHEAT_NEXTMAP) then + begin + if gTriggers <> nil then + for a := 0 to High(gTriggers) do + if gTriggers[a].TriggerType = TRIGGER_EXIT then + begin + gExitByTrigger := True; + //g_Game_ExitLevel(gTriggers[a].Data.MapName); + g_Game_ExitLevel(gTriggers[a].tgcMap); + Break; + end; + goto Cheated; + end; + // + s2 := Copy(charbuff, 15, 2); + if CheckCheat(I_GAME_CHEAT_CHANGEMAP, 2) and (s2[1] >= '0') and (s2[1] <= '9') and (s2[2] >= '0') and (s2[2] <= '9') then + begin + if g_Map_Exist(gGameSettings.WAD + ':\MAP' + s2) then + begin + c := 'MAP' + s2; + g_Game_ExitLevel(c); + end; + goto Cheated; + end; + // + if CheckCheat(I_GAME_CHEAT_FLY) then + begin + gFly := not gFly; + goto Cheated; + end; + // BULLFROG + if CheckCheat(I_GAME_CHEAT_JUMPS) then + begin + VEL_JUMP := 30-VEL_JUMP; + goto Cheated; + end; + // FORMULA1 + if CheckCheat(I_GAME_CHEAT_SPEED) then + begin + MAX_RUNVEL := 32-MAX_RUNVEL; + goto Cheated; + end; + // CONDOM + if CheckCheat(I_GAME_CHEAT_SUIT) then + begin + if gPlayer1 <> nil then gPlayer1.GiveItem(ITEM_SUIT); + if gPlayer2 <> nil then gPlayer2.GiveItem(ITEM_SUIT); + goto Cheated; + end; + // + if CheckCheat(I_GAME_CHEAT_AIR) then + begin + if gPlayer1 <> nil then gPlayer1.GiveItem(ITEM_OXYGEN); + if gPlayer2 <> nil then gPlayer2.GiveItem(ITEM_OXYGEN); + goto Cheated; + end; + // PURELOVE + if CheckCheat(I_GAME_CHEAT_BERSERK) then + begin + if gPlayer1 <> nil then gPlayer1.GiveItem(ITEM_MEDKIT_BLACK); + if gPlayer2 <> nil then gPlayer2.GiveItem(ITEM_MEDKIT_BLACK); + goto Cheated; + end; + // + if CheckCheat(I_GAME_CHEAT_JETPACK) then + begin + if gPlayer1 <> nil then gPlayer1.GiveItem(ITEM_JETPACK); + if gPlayer2 <> nil then gPlayer2.GiveItem(ITEM_JETPACK); + goto Cheated; + end; + // CASPER + if CheckCheat(I_GAME_CHEAT_NOCLIP) then + begin + if gPlayer1 <> nil then gPlayer1.SwitchNoClip; + if gPlayer2 <> nil then gPlayer2.SwitchNoClip; + goto Cheated; + end; + // + if CheckCheat(I_GAME_CHEAT_NOTARGET) then + begin + if gPlayer1 <> nil then gPlayer1.NoTarget := not gPlayer1.NoTarget; + if gPlayer2 <> nil then gPlayer2.NoTarget := not gPlayer2.NoTarget; + goto Cheated; + end; + // INFERNO + if CheckCheat(I_GAME_CHEAT_NORELOAD) then + begin + if gPlayer1 <> nil then gPlayer1.NoReload := not gPlayer1.NoReload; + if gPlayer2 <> nil then gPlayer2.NoReload := not gPlayer2.NoReload; + goto Cheated; + end; + if CheckCheat(I_GAME_CHEAT_AIMLINE) then + begin + gAimLine := not gAimLine; + goto Cheated; + end; + if CheckCheat(I_GAME_CHEAT_AUTOMAP) then + begin + gShowMap := not gShowMap; + goto Cheated; + end; + Exit; + +Cheated: + g_Sound_PlayEx(s); +end; + + +procedure KeyPress (K: Word); +{$IFNDEF HEADLESS} +var + Msg: g_gui.TMessage; +{$ENDIF} +begin +{$IFNDEF HEADLESS} + case K of + VK_ESCAPE: // : + begin + if (g_ActiveWindow <> nil) then + begin + Msg.Msg := WM_KEYDOWN; + Msg.WParam := VK_ESCAPE; + g_ActiveWindow.OnMessage(Msg); + if (not g_Game_IsNet) and (g_ActiveWindow = nil) then g_Game_Pause(false); //Fn loves to do this + end + else if (gState <> STATE_FOLD) then + begin + if gGameOn or (gState = STATE_INTERSINGLE) or (gState = STATE_INTERCUSTOM) then + begin + g_Game_InGameMenu(True); + end + else if (gExit = 0) and (gState <> STATE_SLIST) then + begin + if (gState <> STATE_MENU) then + begin + if (NetMode <> NET_NONE) then + begin + g_Game_StopAllSounds(True); + g_Game_Free; + gState := STATE_MENU; + Exit; + end; + end; + g_GUI_ShowWindow('MainMenu'); + g_Sound_PlayEx('MENU_OPEN'); + end; + end; + end; + + IK_F2, IK_F3, IK_F4, IK_F5, IK_F6, IK_F7, IK_F10: + begin // .. � + if gGameOn and (not gConsoleShow) and (not gChatShow) then + begin + while (g_ActiveWindow <> nil) do g_GUI_HideWindow(False); + if (not g_Game_IsNet) then g_Game_Pause(True); + case K of + IK_F2: g_Menu_Show_SaveMenu(); + IK_F3: g_Menu_Show_LoadMenu(); + IK_F4: g_Menu_Show_GameSetGame(); + IK_F5: g_Menu_Show_OptionsVideo(); + IK_F6: g_Menu_Show_OptionsSound(); + IK_F7: g_Menu_Show_EndGameMenu(); + IK_F10: g_Menu_Show_QuitGameMenu(); + end; + end; + end; + + else + begin + gJustChatted := False; + if gConsoleShow or gChatShow then + begin + g_Console_Control(K); + end + else if (g_ActiveWindow <> nil) then + begin + Msg.Msg := WM_KEYDOWN; + Msg.WParam := K; + g_ActiveWindow.OnMessage(Msg); + end + else if (gState = STATE_MENU) then + begin + g_GUI_ShowWindow('MainMenu'); + g_Sound_PlayEx('MENU_OPEN'); + end; + end; + end; +{$ENDIF} +end; + +procedure CharPress (C: AnsiChar); +var + Msg: g_gui.TMessage; + a: Integer; +begin + if gConsoleShow or gChatShow then + begin + g_Console_Char(C) + end + else if (g_ActiveWindow <> nil) then + begin + Msg.Msg := WM_CHAR; + Msg.WParam := Ord(C); + g_ActiveWindow.OnMessage(Msg); + end + else + begin + for a := 0 to 14 do charbuff[a] := charbuff[a+1]; + charbuff[15] := upcase1251(C); + Cheat(); + end; +end; + // ////////////////////////////////////////////////////////////////////////// // function gPause (): Boolean; inline; begin result := gPauseMain or gPauseHolmes; end; diff --git a/src/game/g_holmes.pas b/src/game/g_holmes.pas index b31ead3..7f74dc1 100644 --- a/src/game/g_holmes.pas +++ b/src/game/g_holmes.pas @@ -50,7 +50,7 @@ uses {$INCLUDE ../nogl/noGLuses.inc} {rttiobj,} typinfo, e_res, SysUtils, Classes, SDL2, - MAPDEF, g_main, g_options, + MAPDEF, g_options, utils, hashtable, xparser; diff --git a/src/game/g_items.pas b/src/game/g_items.pas index 02c8b5f..6c8041d 100644 --- a/src/game/g_items.pas +++ b/src/game/g_items.pas @@ -91,9 +91,9 @@ implementation uses Math, - g_basic, g_sound, g_main, g_gfx, g_map, + g_basic, g_sound, g_gfx, g_map, g_game, g_triggers, g_console, g_player, g_net, g_netmsg, - e_log, + e_log, g_options, g_grid, binheap, idpool, utils, xstreams; // ////////////////////////////////////////////////////////////////////////// // diff --git a/src/game/g_main.pas b/src/game/g_main.pas deleted file mode 100644 index 3da02c2..0000000 --- a/src/game/g_main.pas +++ /dev/null @@ -1,1010 +0,0 @@ -(* Copyright (C) Doom 2D: Forever Developers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License ONLY. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *) -{$INCLUDE ../shared/a_modes.inc} -unit g_main; - -interface - - uses Utils; - -procedure Main (); -procedure Init (); -procedure Release (); -procedure Update (); -procedure Draw (); -procedure KeyPress (K: Word); -procedure CharPress (C: AnsiChar); - -var - {--- Read-only dirs ---} - GameWAD: string; - DataDirs: SSArray; - ModelDirs: SSArray; - MegawadDirs: SSArray; - MapDirs: SSArray; - WadDirs: SSArray; - AllMapDirs: SSArray; // Maps + Megawads - - {--- Read-Write dirs ---} - LogFileName: string; - LogDirs: SSArray; - SaveDirs: SSArray; - CacheDirs: SSArray; - ConfigDirs: SSArray; - ScreenshotDirs: SSArray; - StatsDirs: SSArray; - MapDownloadDirs: SSArray; - WadDownloadDirs: SSArray; - - GameWADName: string = 'GAME'; - -implementation - -uses -{$IFDEF ENABLE_HOLMES} - g_holmes, sdlcarcass, fui_ctls, fui_wadread, fui_style, fui_gfx_gl, -{$ENDIF} -{$IFDEF LINUX} - BaseUnix, -{$ENDIF} -{$IFDEF DARWIN} - MacOSAll, CocoaAll, -{$ENDIF} -{$IFDEF USE_SDL2} - SDL2, -{$ENDIF} - wadreader, e_log, g_window, - r_graphics, e_input, g_game, g_console, g_gui, - e_sound, g_options, g_sound, g_player, g_basic, - g_weapons, SysUtils, g_triggers, MAPDEF, g_map, e_res, - g_menu, g_language, g_net, g_touch, g_system, g_res_downloader, - conbuf, envvars, r_game, - xparser; - - -var - charbuff: packed array [0..15] of AnsiChar; - binPath: AnsiString = ''; - forceBinDir: Boolean; - -function GetBinaryPath (): AnsiString; -{$IFDEF LINUX} -var - //cd: AnsiString; - sl: AnsiString; -{$ENDIF} -begin - result := ExtractFilePath(ParamStr(0)); - {$IFDEF LINUX} - // it may be a symlink; do some guesswork here - sl := fpReadLink(ExtractFileName(ParamStr(0))); - if (sl = ParamStr(0)) then - begin - // use current directory, as we don't have anything better - //result := '.'; - GetDir(0, result); - end; - {$ENDIF} - result := fixSlashes(result); - if (length(result) > 0) and (result[length(result)] <> '/') then result := result+'/'; -end; - -procedure PrintDirs (msg: AnsiString; dirs: SSArray); - var dir: AnsiString; -begin - e_LogWriteln(msg + ':'); - for dir in dirs do - e_LogWriteln(' ' + dir); -end; - -{$IFDEF DARWIN} - function NSStringToAnsiString (s: NSString): AnsiString; - var i: Integer; - begin - result := ''; - for i := 0 to s.length - 1 do - result := result + AnsiChar(s.characterAtIndex(i)); - end; - - function GetBundlePath (): AnsiString; - var pathRef: CFURLRef; pathCFStr: CFStringRef; pathStr: ShortString; - begin - pathRef := CFBundleCopyBundleURL(CFBundleGetMainBundle()); - pathCFStr := CFURLCopyFileSystemPath(pathRef, kCFURLPOSIXPathStyle); - CFStringGetPascalString(pathCFStr, @pathStr, 255, CFStringGetSystemEncoding()); - CFRelease(pathRef); - CFRelease(pathCFStr); - Result := pathStr; - end; -{$ENDIF} - -procedure InitPath; - var i: Integer; rwdir, rodir: AnsiString; rwdirs, rodirs: SSArray; - - procedure AddDir (var dirs: SSArray; append: AnsiString); - begin - SetLength(dirs, Length(dirs) + 1); - dirs[High(dirs)] := ExpandFileName(append) - end; - - function IsSep (ch: Char): Boolean; - begin - {$IFDEF WINDOWS} - result := (ch = '/') or (ch = '\'); - {$ELSE} - result := (ch = '/'); - {$ENDIF} - end; - - function OptimizePath (dir: AnsiString): AnsiString; - var i, len: Integer; s: AnsiString; - begin - i := 1; len := Length(dir); s := ''; - while i <= len do - begin - if IsSep(dir[i]) then - begin - s := s + DirectorySeparator; - Inc(i); - while (i <= len) and IsSep(dir[i]) do Inc(i); - if (i <= len) and (dir[i] = '.') then - begin - if (i = len) or IsSep(dir[i + 1]) then - begin - Inc(i) - end - else if (i + 1 <= len) and (dir[i + 1] = '.') then - begin - if (i + 1 = len) or IsSep(dir[i + 2]) then - begin - s := e_UpperDir(s); - Inc(i, 2) - end - end - end - end - else - begin - s := s + dir[i]; - Inc(i) - end - end; - result := s - end; - - procedure OptimizeDirs (var dirs: SSArray); - var i, j, k: Integer; - begin - for i := 0 to High(dirs) do - dirs[i] := OptimizePath(dirs[i]); - // deduplicate - i := High(dirs); - while i >= 0 do - begin - j := 0; - while j < i do - begin - if dirs[j] = dirs[i] then - begin - for k := j + 1 to High(dirs) do - dirs[k - 1] := dirs[k]; - Dec(i); - SetLength(dirs, High(dirs)) - end - else - begin - Inc(j) - end - end; - Dec(i) - end - end; - - procedure AddDef (var dirs: SSArray; base: SSArray; append: AnsiString); - var s: AnsiString; - begin - if Length(dirs) = 0 then - for s in base do - AddDir(dirs, e_CatPath(s, append)); - OptimizeDirs(dirs) - end; - - function GetDefaultRODirs (): SSArray; - {$IF DEFINED(UNIX) AND NOT DEFINED(DARWIN) AND NOT DEFINED(ANDROID)} - var home: AnsiString; - {$ENDIF} - {$IFDEF WINDOWS} - var appdata: AnsiString; - {$ENDIF} - {$IFDEF DARWIN} - var bundle, s: AnsiString; dirArr: NSArray; i: Integer; - {$ENDIF} - begin - result := nil; - {$IFDEF DARWIN} - bundle := GetBundlePath(); - if ExtractFileExt(bundle) <> '.app' then - AddDir(result, binpath); - {$ELSE} - AddDir(result, binPath); - {$ENDIF} - if forceBinDir = false then - begin - {$IFDEF USE_SDL2} - AddDir(result, SDL_GetBasePath()); - AddDir(result, SDL_GetPrefPath('', 'doom2df')); - {$ENDIF} - {$IFDEF WINDOWS} - appdata := GetEnvironmentVariable('APPDATA') + '\doom2df'; - if appdata <> '' then - AddDir(result, appdata); - {$ENDIF} - {$IF DEFINED(UNIX) AND NOT DEFINED(DARWIN) AND NOT DEFINED(ANDROID)} - AddDir(result, '/usr/share/doom2df'); - AddDir(result, '/usr/local/share/doom2df'); - home := GetEnvironmentVariable('HOME'); - if home <> '' then - AddDir(result, e_CatPath(home, '.doom2df')); - {$ENDIF} - {$IFDEF DARWIN} - bundle := GetBundlePath(); - if bundle <> '' then - AddDir(result, e_CatPath(bundle, 'Contents/Resources')); - dirArr := NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, true); - for i := 0 to dirArr.count - 1 do - begin - s := NSStringToAnsiString(dirArr.objectAtIndex(i)); - AddDir(result, e_CatPath(s, 'Doom 2D Forever')) - end; - {$ENDIF} - {$IF DEFINED(ANDROID) AND DEFINED(USE_SDL2)} - AddDir(result, SDL_AndroidGetInternalStoragePath()); - if SDL_AndroidGetExternalStorageState() <> 0 then - AddDir(result, SDL_AndroidGetExternalStoragePath()); - {$ENDIF} - end - end; - - function GetDefaultRWDirs (): SSArray; - {$IF DEFINED(UNIX) AND NOT DEFINED(DARWIN) AND NOT DEFINED(ANDROID)} - var home: AnsiString; - {$ENDIF} - {$IFDEF WINDOWS} - var appdata: AnsiString; - {$ENDIF} - {$IFDEF DARWIN} - var bundle, s: AnsiString; dirArr: NSArray; i: Integer; - {$ENDIF} - begin - result := nil; - {$IFDEF DARWIN} - bundle := GetBundlePath(); - if ExtractFileExt(bundle) <> '.app' then - AddDir(result, binPath); - {$ELSE} - AddDir(result, binPath); - {$ENDIF} - if forceBinDir = false then - begin - {$IFDEF USE_SDL2} - AddDir(result, SDL_GetPrefPath('', 'doom2df')); - {$ENDIF} - {$IFDEF WINDOWS} - appdata := GetEnvironmentVariable('APPDATA') + '\doom2df'; - if appdata <> '' then - AddDir(result, appdata); - {$ENDIF} - {$IF DEFINED(UNIX) AND NOT DEFINED(DARWIN) AND NOT DEFINED(ANDROID)} - home := GetEnvironmentVariable('HOME'); - if home <> '' then - AddDir(result, e_CatPath(home, '.doom2df')); - {$ENDIF} - {$IFDEF DARWIN} - dirArr := NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, true); - for i := 0 to dirArr.count - 1 do - begin - s := NSStringToAnsiString(dirArr.objectAtIndex(i)); - AddDir(result, e_CatPath(s, 'Doom 2D Forever')) - end; - {$ENDIF} - {$IF DEFINED(ANDROID) AND DEFINED(USE_SDL2)} - if SDL_AndroidGetExternalStorageState() <> 0 then - AddDir(result, SDL_AndroidGetExternalStoragePath()); - {$ENDIF} - end - end; - -begin - forceBinDir := false; - binPath := GetBinaryPath(); - - i := 1; - while i < ParamCount do - begin - case ParamStr(i) of - '--like-windoze': forceBinDir := true; - '--rw-dir': - begin - Inc(i); - rwdir := ParamStr(i); - (* RW *) - AddDir(LogDirs, e_CatPath(rwdir, '')); - AddDir(SaveDirs, e_CatPath(rwdir, 'data')); - AddDir(CacheDirs, e_CatPath(rwdir, 'data/cache')); - AddDir(ConfigDirs, e_CatPath(rwdir, '')); - AddDir(MapDownloadDirs, e_CatPath(rwdir, 'maps/downloads')); - AddDir(WadDownloadDirs, e_CatPath(rwdir, 'wads/downloads')); - AddDir(ScreenshotDirs, e_CatPath(rwdir, 'screenshots')); - AddDir(StatsDirs, e_CatPath(rwdir, 'stats')); - (* RO *) - AddDir(DataDirs, e_CatPath(rwdir, 'data')); - AddDir(ModelDirs, e_CatPath(rwdir, 'data/models')); - AddDir(MegawadDirs, e_CatPath(rwdir, 'maps/megawads')); - AddDir(MapDirs, e_CatPath(rwdir, 'maps')); - AddDir(WadDirs, e_CatPath(rwdir, 'wads')); - end; - '--ro-dir': - begin - Inc(i); - rodir := ParamStr(i); - (* RO *) - AddDir(DataDirs, e_CatPath(rodir, 'data')); - AddDir(ModelDirs, e_CatPath(rodir, 'data/models')); - AddDir(MegawadDirs, e_CatPath(rodir, 'maps/megawads')); - AddDir(MapDirs, e_CatPath(rodir, 'maps')); - AddDir(WadDirs, e_CatPath(rodir, 'wads')); - end; - '--game-wad': - begin - Inc(i); - GameWADName := ParamStr(i); - end; - '--config': - begin - Inc(i); - gConfigScript := ParamStr(i); - end; - end; - Inc(i) - end; - - // prefer bin dir if it writable and contains game.wad - if forceBinDir = false then - begin - if findDiskWad(binPath + 'data' + '/' + GameWADName) <> '' then - if e_CanCreateFilesAt(binPath) then - forceBinDir := true - end; - - (* RO *) - rodirs := GetDefaultRODirs(); - AddDef(DataDirs, rodirs, 'data'); - AddDef(ModelDirs, rodirs, 'data/models'); - AddDef(MegawadDirs, rodirs, 'maps/megawads'); - AddDef(MapDirs, rodirs, 'maps'); - AddDef(WadDirs, rodirs, 'wads'); - - (* RW *) - rwdirs := GetDefaultRWDirs(); - AddDef(LogDirs, rwdirs, ''); - AddDef(SaveDirs, rwdirs, 'data'); - AddDef(CacheDirs, rwdirs, 'data/cache'); - AddDef(ConfigDirs, rwdirs, ''); - AddDef(MapDownloadDirs, rwdirs, 'maps/downloads'); - AddDef(WadDownloadDirs, rwdirs, 'wads/downloads'); - AddDef(ScreenshotDirs, rwdirs, 'screenshots'); - AddDef(StatsDirs, rwdirs, 'stats'); - - for i := 0 to High(MapDirs) do - AddDir(AllMapDirs, MapDirs[i]); - for i := 0 to High(MegawadDirs) do - AddDir(AllMapDirs, MegawadDirs[i]); - OptimizeDirs(AllMapDirs); - - if LogFileName = '' then - begin - rwdir := e_GetWriteableDir(LogDirs, false); - if rwdir <> '' then - begin - {$IFDEF HEADLESS} - LogFileName := e_CatPath(rwdir, 'Doom2DF_H.log'); - {$ELSE} - LogFileName := e_CatPath(rwdir, 'Doom2DF.log'); - {$ENDIF} - end - end; - - // HACK: ensure the screenshots folder also has a stats subfolder in it - rwdir := e_GetWriteableDir(ScreenshotDirs, false); - if rwdir <> '' then CreateDir(rwdir + '/stats'); -end; - -procedure InitPrep; - {$IF DEFINED(ANDROID) AND DEFINED(USE_SDLMIXER)} - var timiditycfg: AnsiString; - {$ENDIF} - var i: Integer; -begin - {$IFDEF HEADLESS} - conbufDumpToStdOut := true; - {$ENDIF} - for i := 1 to ParamCount do - begin - case ParamStr(i) of - '--con-stdout': conbufDumpToStdOut := true; - '--no-fbo': glRenderToFBO := false; - end - end; - - if LogFileName <> '' then - e_InitLog(LogFileName, TWriteMode.WM_NEWFILE); - e_InitWritelnDriver(); - e_WriteLog('Doom 2D: Forever version ' + GAME_VERSION + ' proto ' + IntToStr(NET_PROTOCOL_VER), TMsgType.Notify); - e_WriteLog('Build date: ' + GAME_BUILDDATE + ' ' + GAME_BUILDTIME, TMsgType.Notify); - e_WriteLog('Build hash: ' + g_GetBuildHash(), TMsgType.Notify); - e_WriteLog('Build by: ' + g_GetBuilderName(), TMsgType.Notify); - - e_LogWritefln('Force bin dir: %s', [forceBinDir], TMsgType.Notify); - e_LogWritefln('BINARY PATH: [%s]', [binPath], TMsgType.Notify); - - PrintDirs('DataDirs', DataDirs); - PrintDirs('ModelDirs', ModelDirs); - PrintDirs('MegawadDirs', MegawadDirs); - PrintDirs('MapDirs', MapDirs); - PrintDirs('WadDirs', WadDirs); - - PrintDirs('LogDirs', LogDirs); - PrintDirs('SaveDirs', SaveDirs); - PrintDirs('CacheDirs', CacheDirs); - PrintDirs('ConfigDirs', ConfigDirs); - PrintDirs('ScreenshotDirs', ScreenshotDirs); - PrintDirs('StatsDirs', StatsDirs); - PrintDirs('MapDownloadDirs', MapDownloadDirs); - PrintDirs('WadDownloadDirs', WadDownloadDirs); - - GameWAD := e_FindWad(DataDirs, GameWADName); - if GameWad = '' then - begin - e_WriteLog('WAD ' + GameWADName + ' not found in data directories.', TMsgType.Fatal); - {$IF DEFINED(USE_SDL2) AND NOT DEFINED(HEADLESS)} - if forceBinDir = false then - SDL_ShowSimpleMessageBox( - SDL_MESSAGEBOX_ERROR, - 'Doom 2D Forever', - PChar('WAD ' + GameWADName + ' not found in data directories.'), - nil - ); - {$ENDIF} - e_DeinitLog; - Halt(1); - end; - - {$IF DEFINED(ANDROID) AND DEFINED(USE_SDLMIXER)} - timiditycfg := 'timidity.cfg'; - if e_FindResource(ConfigDirs, timiditycfg) = true then - begin - timiditycfg := ExpandFileName(timiditycfg); - SetEnvVar('TIMIDITY_CFG', timiditycfg); - e_LogWritefln('Set TIMIDITY_CFG = "%s"', [timiditycfg]); - end; - {$ENDIF} -end; - -procedure Main(); -{$IFDEF ENABLE_HOLMES} - var flexloaded: Boolean; -{$ENDIF} -begin - InitPath; - InitPrep; - e_InitInput; - sys_Init; - - g_Options_SetDefault; - g_Options_SetDefaultVideo; - g_Console_SysInit; - if sys_SetDisplayMode(gRC_Width, gRC_Height, gBPP, gRC_FullScreen, gRC_Maximized) = False then - raise Exception.Create('Failed to set videomode on startup.'); - - e_WriteLog(gLanguage, TMsgType.Notify); - g_Language_Set(gLanguage); - -{$IF not DEFINED(HEADLESS) and DEFINED(ENABLE_HOLMES)} - flexloaded := true; - if not fuiAddWad('flexui.wad') then - begin - if not fuiAddWad('./data/flexui.wad') then fuiAddWad('./flexui.wad'); - end; - try - fuiGfxLoadFont('win8', 'flexui/fonts/win8.fuifont'); - fuiGfxLoadFont('win14', 'flexui/fonts/win14.fuifont'); - fuiGfxLoadFont('win16', 'flexui/fonts/win16.fuifont'); - fuiGfxLoadFont('dos8', 'flexui/fonts/dos8.fuifont'); - fuiGfxLoadFont('msx6', 'flexui/fonts/msx6.fuifont'); - except on e: Exception do - begin - writeln('ERROR loading FlexUI fonts'); - flexloaded := false; - //raise; - end; - else - begin - flexloaded := false; - //raise; - end; - end; - if (flexloaded) then - begin - try - e_LogWriteln('FlexUI: loading stylesheet...'); - uiLoadStyles('flexui/widgets.wgs'); - except on e: TParserException do - begin - writeln('ERROR at (', e.tokLine, ',', e.tokCol, '): ', e.message); - //raise; - flexloaded := false; - end; - else - begin - //raise; - flexloaded := false; - end; - end; - end; - g_holmes_imfunctional := not flexloaded; - - if (not g_holmes_imfunctional) then - begin - uiInitialize(); - uiContext.font := 'win14'; - end; - - if assigned(oglInitCB) then oglInitCB; -{$ENDIF} - - //g_Res_CreateDatabases(true); // it will be done before connecting to the server for the first time - - e_WriteLog('Entering SDLMain', TMsgType.Notify); - - {$WARNINGS OFF} - SDLMain(); - {$WARNINGS ON} - - {$IFDEF ENABLE_HOLMES} - if assigned(oglDeinitCB) then oglDeinitCB; - {$ENDIF} - - g_Console_WriteGameConfig; - sys_Final; -end; - -procedure Init(); -var - NoSound: Boolean; -begin - Randomize; - -{$IFDEF HEADLESS} - {$IFDEF USE_SDLMIXER} - NoSound := False; // hope env has set SDL_AUDIODRIVER to dummy - {$ELSE} - NoSound := True; // FMOD backend will sort it out - {$ENDIF} -{$ELSE} - NoSound := False; -{$ENDIF} - - g_Touch_Init; - -(* - if (e_JoysticksAvailable > 0) then - e_WriteLog('Input: Joysticks available.', TMsgType.Notify) - else - e_WriteLog('Input: No Joysticks.', TMsgType.Notify); -*) - - if (not gNoSound) then - begin - e_WriteLog('Initializing sound system', TMsgType.Notify); - e_InitSoundSystem(NoSound); - end; - - e_WriteLog('Init game', TMsgType.Notify); - g_Game_Init(); - - FillChar(charbuff, sizeof(charbuff), ' '); -end; - - -procedure Release(); -begin - e_WriteLog('Releasing engine', TMsgType.Notify); - e_ReleaseEngine(); - - e_WriteLog('Releasing input', TMsgType.Notify); - e_ReleaseInput(); - - if not gNoSound then - begin - e_WriteLog('Releasing sound', TMsgType.Notify); - e_ReleaseSoundSystem(); - end; -end; - - -procedure Update (); -begin - // remember old mobj positions, prepare for update - g_Game_PreUpdate(); - // server: receive client commands for new frame - // client: receive game state changes from server - if (NetMode = NET_SERVER) then g_Net_Host_Update() - else if (NetMode = NET_CLIENT) then g_Net_Client_Update(); - // think - g_Game_Update(); - // server: send any accumulated outgoing data to clients - if NetMode = NET_SERVER then g_Net_Flush(); -end; - - -procedure Draw (); -begin - r_Game_Draw(); -end; - - -function Translit (const S: AnsiString): AnsiString; -var - i: Integer; -begin - Result := S; - for i := 1 to Length(Result) do - begin - case Result[i] of - 'É': Result[i] := 'Q'; - 'Ö': Result[i] := 'W'; - 'Ó': Result[i] := 'E'; - 'Ê': Result[i] := 'R'; - 'Å': Result[i] := 'T'; - 'Í': Result[i] := 'Y'; - 'Ã': Result[i] := 'U'; - 'Ø': Result[i] := 'I'; - 'Ù': Result[i] := 'O'; - 'Ç': Result[i] := 'P'; - 'Õ': Result[i] := '['; //Chr(219); - 'Ú': Result[i] := ']'; //Chr(221); - 'Ô': Result[i] := 'A'; - 'Û': Result[i] := 'S'; - 'Â': Result[i] := 'D'; - 'À': Result[i] := 'F'; - 'Ï': Result[i] := 'G'; - 'Ð': Result[i] := 'H'; - 'Î': Result[i] := 'J'; - 'Ë': Result[i] := 'K'; - 'Ä': Result[i] := 'L'; - 'Æ': Result[i] := ';'; //Chr(186); - 'Ý': Result[i] := #39; //Chr(222); - 'ß': Result[i] := 'Z'; - '×': Result[i] := 'X'; - 'Ñ': Result[i] := 'C'; - 'Ì': Result[i] := 'V'; - 'È': Result[i] := 'B'; - 'Ò': Result[i] := 'N'; - 'Ü': Result[i] := 'M'; - 'Á': Result[i] := ','; //Chr(188); - 'Þ': Result[i] := '.'; //Chr(190); - end; - end; -end; - - -function CheckCheat (ct: TStrings_Locale; eofs: Integer=0): Boolean; -var - ls1, ls2: string; -begin - ls1 := CheatEng[ct]; - ls2 := Translit(CheatRus[ct]); - if length(ls1) = 0 then ls1 := '~'; - if length(ls2) = 0 then ls2 := '~'; - result := - (Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1)) = ls1) or - (Translit(Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1))) = ls1) or - (Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2)) = ls2) or - (Translit(Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2))) = ls2); - { - if ct = I_GAME_CHEAT_JETPACK then - begin - e_WriteLog('ls1: ['+ls1+']', MSG_NOTIFY); - e_WriteLog('ls2: ['+ls2+']', MSG_NOTIFY); - e_WriteLog('bf0: ['+Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1))+']', MSG_NOTIFY); - e_WriteLog('bf1: ['+Translit(Copy(charbuff, 17-Length(ls1)-eofs, Length(ls1)))+']', MSG_NOTIFY); - e_WriteLog('bf2: ['+Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2))+']', MSG_NOTIFY); - e_WriteLog('bf3: ['+Translit(Copy(charbuff, 17-Length(ls2)-eofs, Length(ls2)))+']', MSG_NOTIFY); - end; - } -end; - - -procedure Cheat (); -const - CHEAT_DAMAGE = 500; -label - Cheated; -var - s, s2: string; - c: ShortString; - a: Integer; -begin - { - if (not gGameOn) or (not gCheats) or ((gGameSettings.GameType <> GT_SINGLE) and - (gGameSettings.GameMode <> GM_COOP) and (not gDebugMode)) - or g_Game_IsNet then Exit; - } - if not gGameOn then exit; - if not conIsCheatsEnabled then exit; - - s := 'SOUND_GAME_RADIO'; - - // - if CheckCheat(I_GAME_CHEAT_GODMODE) then - begin - if gPlayer1 <> nil then gPlayer1.GodMode := not gPlayer1.GodMode; - if gPlayer2 <> nil then gPlayer2.GodMode := not gPlayer2.GodMode; - goto Cheated; - end; - // RAMBO - if CheckCheat(I_GAME_CHEAT_WEAPONS) then - begin - if gPlayer1 <> nil then gPlayer1.AllRulez(False); - if gPlayer2 <> nil then gPlayer2.AllRulez(False); - goto Cheated; - end; - // TANK - if CheckCheat(I_GAME_CHEAT_HEALTH) then - begin - if gPlayer1 <> nil then gPlayer1.AllRulez(True); - if gPlayer2 <> nil then gPlayer2.AllRulez(True); - goto Cheated; - end; - // IDDQD - if CheckCheat(I_GAME_CHEAT_DEATH) then - begin - if gPlayer1 <> nil then gPlayer1.Damage(CHEAT_DAMAGE, 0, 0, 0, HIT_TRAP); - if gPlayer2 <> nil then gPlayer2.Damage(CHEAT_DAMAGE, 0, 0, 0, HIT_TRAP); - s := 'SOUND_MONSTER_HAHA'; - goto Cheated; - end; - // - if CheckCheat(I_GAME_CHEAT_DOORS) then - begin - g_Triggers_OpenAll(); - goto Cheated; - end; - // GOODBYE - if CheckCheat(I_GAME_CHEAT_NEXTMAP) then - begin - if gTriggers <> nil then - for a := 0 to High(gTriggers) do - if gTriggers[a].TriggerType = TRIGGER_EXIT then - begin - gExitByTrigger := True; - //g_Game_ExitLevel(gTriggers[a].Data.MapName); - g_Game_ExitLevel(gTriggers[a].tgcMap); - Break; - end; - goto Cheated; - end; - // - s2 := Copy(charbuff, 15, 2); - if CheckCheat(I_GAME_CHEAT_CHANGEMAP, 2) and (s2[1] >= '0') and (s2[1] <= '9') and (s2[2] >= '0') and (s2[2] <= '9') then - begin - if g_Map_Exist(gGameSettings.WAD + ':\MAP' + s2) then - begin - c := 'MAP' + s2; - g_Game_ExitLevel(c); - end; - goto Cheated; - end; - // - if CheckCheat(I_GAME_CHEAT_FLY) then - begin - gFly := not gFly; - goto Cheated; - end; - // BULLFROG - if CheckCheat(I_GAME_CHEAT_JUMPS) then - begin - VEL_JUMP := 30-VEL_JUMP; - goto Cheated; - end; - // FORMULA1 - if CheckCheat(I_GAME_CHEAT_SPEED) then - begin - MAX_RUNVEL := 32-MAX_RUNVEL; - goto Cheated; - end; - // CONDOM - if CheckCheat(I_GAME_CHEAT_SUIT) then - begin - if gPlayer1 <> nil then gPlayer1.GiveItem(ITEM_SUIT); - if gPlayer2 <> nil then gPlayer2.GiveItem(ITEM_SUIT); - goto Cheated; - end; - // - if CheckCheat(I_GAME_CHEAT_AIR) then - begin - if gPlayer1 <> nil then gPlayer1.GiveItem(ITEM_OXYGEN); - if gPlayer2 <> nil then gPlayer2.GiveItem(ITEM_OXYGEN); - goto Cheated; - end; - // PURELOVE - if CheckCheat(I_GAME_CHEAT_BERSERK) then - begin - if gPlayer1 <> nil then gPlayer1.GiveItem(ITEM_MEDKIT_BLACK); - if gPlayer2 <> nil then gPlayer2.GiveItem(ITEM_MEDKIT_BLACK); - goto Cheated; - end; - // - if CheckCheat(I_GAME_CHEAT_JETPACK) then - begin - if gPlayer1 <> nil then gPlayer1.GiveItem(ITEM_JETPACK); - if gPlayer2 <> nil then gPlayer2.GiveItem(ITEM_JETPACK); - goto Cheated; - end; - // CASPER - if CheckCheat(I_GAME_CHEAT_NOCLIP) then - begin - if gPlayer1 <> nil then gPlayer1.SwitchNoClip; - if gPlayer2 <> nil then gPlayer2.SwitchNoClip; - goto Cheated; - end; - // - if CheckCheat(I_GAME_CHEAT_NOTARGET) then - begin - if gPlayer1 <> nil then gPlayer1.NoTarget := not gPlayer1.NoTarget; - if gPlayer2 <> nil then gPlayer2.NoTarget := not gPlayer2.NoTarget; - goto Cheated; - end; - // INFERNO - if CheckCheat(I_GAME_CHEAT_NORELOAD) then - begin - if gPlayer1 <> nil then gPlayer1.NoReload := not gPlayer1.NoReload; - if gPlayer2 <> nil then gPlayer2.NoReload := not gPlayer2.NoReload; - goto Cheated; - end; - if CheckCheat(I_GAME_CHEAT_AIMLINE) then - begin - gAimLine := not gAimLine; - goto Cheated; - end; - if CheckCheat(I_GAME_CHEAT_AUTOMAP) then - begin - gShowMap := not gShowMap; - goto Cheated; - end; - Exit; - -Cheated: - g_Sound_PlayEx(s); -end; - - -procedure KeyPress (K: Word); -{$IFNDEF HEADLESS} -var - Msg: g_gui.TMessage; -{$ENDIF} -begin -{$IFNDEF HEADLESS} - case K of - VK_ESCAPE: // : - begin - if (g_ActiveWindow <> nil) then - begin - Msg.Msg := WM_KEYDOWN; - Msg.WParam := VK_ESCAPE; - g_ActiveWindow.OnMessage(Msg); - if (not g_Game_IsNet) and (g_ActiveWindow = nil) then g_Game_Pause(false); //Fn loves to do this - end - else if (gState <> STATE_FOLD) then - begin - if gGameOn or (gState = STATE_INTERSINGLE) or (gState = STATE_INTERCUSTOM) then - begin - g_Game_InGameMenu(True); - end - else if (gExit = 0) and (gState <> STATE_SLIST) then - begin - if (gState <> STATE_MENU) then - begin - if (NetMode <> NET_NONE) then - begin - g_Game_StopAllSounds(True); - g_Game_Free; - gState := STATE_MENU; - Exit; - end; - end; - g_GUI_ShowWindow('MainMenu'); - g_Sound_PlayEx('MENU_OPEN'); - end; - end; - end; - - IK_F2, IK_F3, IK_F4, IK_F5, IK_F6, IK_F7, IK_F10: - begin // .. � - if gGameOn and (not gConsoleShow) and (not gChatShow) then - begin - while (g_ActiveWindow <> nil) do g_GUI_HideWindow(False); - if (not g_Game_IsNet) then g_Game_Pause(True); - case K of - IK_F2: g_Menu_Show_SaveMenu(); - IK_F3: g_Menu_Show_LoadMenu(); - IK_F4: g_Menu_Show_GameSetGame(); - IK_F5: g_Menu_Show_OptionsVideo(); - IK_F6: g_Menu_Show_OptionsSound(); - IK_F7: g_Menu_Show_EndGameMenu(); - IK_F10: g_Menu_Show_QuitGameMenu(); - end; - end; - end; - - else - begin - gJustChatted := False; - if gConsoleShow or gChatShow then - begin - g_Console_Control(K); - end - else if (g_ActiveWindow <> nil) then - begin - Msg.Msg := WM_KEYDOWN; - Msg.WParam := K; - g_ActiveWindow.OnMessage(Msg); - end - else if (gState = STATE_MENU) then - begin - g_GUI_ShowWindow('MainMenu'); - g_Sound_PlayEx('MENU_OPEN'); - end; - end; - end; -{$ENDIF} -end; - - -procedure CharPress (C: AnsiChar); -var - Msg: g_gui.TMessage; - a: Integer; -begin - if gConsoleShow or gChatShow then - begin - g_Console_Char(C) - end - else if (g_ActiveWindow <> nil) then - begin - Msg.Msg := WM_CHAR; - Msg.WParam := Ord(C); - g_ActiveWindow.OnMessage(Msg); - end - else - begin - for a := 0 to 14 do charbuff[a] := charbuff[a+1]; - charbuff[15] := upcase1251(C); - Cheat(); - end; -end; - -end. diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 7ec904b..eb94542 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -246,7 +246,7 @@ var implementation uses - e_input, g_main, e_log, e_res, g_items, g_gfx, g_console, + e_input, e_log, e_res, g_items, g_gfx, g_console, g_weapons, g_game, g_sound, e_sound, CONFIG, g_options, g_triggers, g_player, Math, g_monsters, g_saveload, g_language, g_netmsg, diff --git a/src/game/g_menu.pas b/src/game/g_menu.pas index 61da4c4..265bade 100644 --- a/src/game/g_menu.pas +++ b/src/game/g_menu.pas @@ -43,7 +43,7 @@ var implementation uses - g_gui, g_textures, r_graphics, g_main, g_window, g_game, g_map, + g_gui, g_textures, r_graphics, g_window, g_game, g_map, g_base, g_basic, g_console, g_sound, g_gfx, g_player, g_options, g_weapons, e_log, SysUtils, CONFIG, g_playermodel, DateUtils, MAPDEF, Math, g_saveload, diff --git a/src/game/g_monsters.pas b/src/game/g_monsters.pas index 434730b..5824ffe 100644 --- a/src/game/g_monsters.pas +++ b/src/game/g_monsters.pas @@ -488,7 +488,7 @@ var implementation uses - e_log, g_main, g_sound, g_gfx, g_player, g_game, + e_log, g_sound, g_gfx, g_player, g_game, g_weapons, g_triggers, g_items, g_options, g_console, g_map, Math, g_menu, wadreader, g_language, g_netmsg, idpool, utils, xstreams; diff --git a/src/game/g_net.pas b/src/game/g_net.pas index 63e4cb9..2316d1c 100644 --- a/src/game/g_net.pas +++ b/src/game/g_net.pas @@ -254,9 +254,9 @@ implementation uses SysUtils, - e_input, e_res, + e_input, e_res, g_options, g_nethandler, g_netmsg, g_netmaster, g_player, g_window, g_console, - g_main, g_game, g_language, g_weapons, ctypes, g_system, g_map; + g_game, g_language, g_weapons, ctypes, g_system, g_map; const FILE_CHUNK_SIZE = 8192; diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index b5edf0a..c49ffaa 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -277,7 +277,7 @@ implementation uses Math, ENet, e_input, e_log, g_base, g_basic, - g_textures, g_gfx, g_sound, g_console, g_options, g_main, + g_textures, g_gfx, g_sound, g_console, g_options, g_game, g_player, g_map, g_panel, g_items, g_weapons, g_phys, g_gui, g_language, g_monsters, g_netmaster, utils, wadreader, MAPDEF; diff --git a/src/game/g_options.pas b/src/game/g_options.pas index 487dbd2..f1f0653 100644 --- a/src/game/g_options.pas +++ b/src/game/g_options.pas @@ -86,6 +86,28 @@ var g_dbg_scale: Single = 1.0; r_pixel_scale: Single = 1.0; + {--- Read-only dirs ---} + GameWAD: string; + DataDirs: SSArray; + ModelDirs: SSArray; + MegawadDirs: SSArray; + MapDirs: SSArray; + WadDirs: SSArray; + AllMapDirs: SSArray; // Maps + Megawads + + {--- Read-Write dirs ---} + LogFileName: string; + LogDirs: SSArray; + SaveDirs: SSArray; + CacheDirs: SSArray; + ConfigDirs: SSArray; + ScreenshotDirs: SSArray; + StatsDirs: SSArray; + MapDownloadDirs: SSArray; + WadDownloadDirs: SSArray; + + GameWADName: string = 'GAME'; + implementation uses @@ -93,7 +115,7 @@ uses SDL2, {$ENDIF} e_log, e_input, g_console, g_window, g_sound, g_gfx, g_player, Math, - g_map, g_net, g_netmaster, SysUtils, CONFIG, g_game, g_main, + g_map, g_net, g_netmaster, SysUtils, CONFIG, g_game, g_items, wadreader, g_touch, envvars, g_system; var diff --git a/src/game/g_player.pas b/src/game/g_player.pas index e2e9e97..dab24ae 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -637,7 +637,7 @@ uses {$ENDIF} e_log, g_map, g_items, g_console, g_gfx, Math, g_options, g_triggers, g_menu, g_game, g_grid, e_res, - wadreader, g_main, g_monsters, CONFIG, g_language, + wadreader, g_monsters, CONFIG, g_language, g_net, g_netmsg, g_window, utils, xstreams; diff --git a/src/game/g_playermodel.pas b/src/game/g_playermodel.pas index 9b018cb..b2f57e6 100644 --- a/src/game/g_playermodel.pas +++ b/src/game/g_playermodel.pas @@ -167,7 +167,7 @@ function g_PlayerModel_GetGibs(ModelName: String; var Gibs: TGibsArray): Boolea implementation uses - g_main, g_sound, g_console, SysUtils, g_player, CONFIG, + g_sound, g_console, SysUtils, g_player, CONFIG, e_sound, g_options, g_map, Math, e_log, wadreader; type diff --git a/src/game/g_res_downloader.pas b/src/game/g_res_downloader.pas index 7fc2951..8bd5e04 100644 --- a/src/game/g_res_downloader.pas +++ b/src/game/g_res_downloader.pas @@ -17,7 +17,7 @@ unit g_res_downloader; interface -uses sysutils, Classes, md5, g_net, g_netmsg, g_console, g_main, e_log; +uses sysutils, Classes, md5, g_net, g_netmsg, g_console, e_log; // download map wad from server (if necessary) @@ -35,7 +35,7 @@ procedure g_Res_CreateDatabases (allowRescan: Boolean=false); implementation -uses g_language, sfs, utils, wadreader, g_game, hashtable, fhashdb, e_res; +uses g_language, sfs, utils, wadreader, g_game, hashtable, fhashdb, e_res, g_options; var // cvars diff --git a/src/game/g_saveload.pas b/src/game/g_saveload.pas index eb1a79a..32f6821 100644 --- a/src/game/g_saveload.pas +++ b/src/game/g_saveload.pas @@ -38,9 +38,9 @@ implementation uses MAPDEF, utils, xstreams, g_game, g_items, g_map, g_monsters, g_triggers, - g_basic, g_main, Math, wadreader, + g_basic, Math, wadreader, g_weapons, g_player, g_console, - e_log, e_res, g_language; + e_log, e_res, g_language, g_options; const SAVE_SIGNATURE = $56534644; // 'DFSV' diff --git a/src/game/g_triggers.pas b/src/game/g_triggers.pas index f89aa9f..e8891a0 100644 --- a/src/game/g_triggers.pas +++ b/src/game/g_triggers.pas @@ -105,7 +105,7 @@ uses Math, g_player, g_map, g_panel, g_gfx, g_game, g_textures, g_console, g_monsters, g_items, g_phys, g_weapons, - wadreader, g_main, e_log, g_language, e_res, + wadreader, e_log, g_language, e_res, g_options, g_net, g_netmsg, utils, xparser, xstreams; const diff --git a/src/game/g_weapons.pas b/src/game/g_weapons.pas index 21c5803..81767e6 100644 --- a/src/game/g_weapons.pas +++ b/src/game/g_weapons.pas @@ -113,7 +113,7 @@ var implementation uses - Math, g_map, g_player, g_gfx, g_sound, g_main, g_panel, + Math, g_map, g_player, g_gfx, g_sound, g_panel, g_console, g_options, g_game, g_triggers, MAPDEF, e_log, g_monsters, g_saveload, g_language, g_netmsg, g_grid, diff --git a/src/game/g_window.pas b/src/game/g_window.pas index 4e84b5d..bfd4377 100644 --- a/src/game/g_window.pas +++ b/src/game/g_window.pas @@ -37,8 +37,8 @@ uses {$IFDEF ENABLE_HOLMES} g_holmes, sdlcarcass, fui_ctls, {$ENDIF} - SysUtils, Classes, MAPDEF, Math, - r_window, e_log, g_main, + SysUtils, Classes, MAPDEF, Math, r_graphics, + r_window, e_log, r_game, g_console, r_console, e_input, g_options, g_game, g_basic, g_textures, e_sound, g_sound, g_menu, ENet, g_net, g_map, g_gfx, g_monsters, xprofiler, @@ -51,6 +51,79 @@ var wNeedTimeReset: Boolean = false; wLoadingQuit: Boolean = false; +procedure Update (); +begin + // remember old mobj positions, prepare for update + g_Game_PreUpdate(); + // server: receive client commands for new frame + // client: receive game state changes from server + if (NetMode = NET_SERVER) then g_Net_Host_Update() + else if (NetMode = NET_CLIENT) then g_Net_Client_Update(); + // think + g_Game_Update(); + // server: send any accumulated outgoing data to clients + if NetMode = NET_SERVER then g_Net_Flush(); +end; + + +procedure Draw (); +begin + r_Game_Draw(); +end; + + +procedure Init(); +var + NoSound: Boolean; +begin + Randomize; + +{$IFDEF HEADLESS} + {$IFDEF USE_SDLMIXER} + NoSound := False; // hope env has set SDL_AUDIODRIVER to dummy + {$ELSE} + NoSound := True; // FMOD backend will sort it out + {$ENDIF} +{$ELSE} + NoSound := False; +{$ENDIF} + + g_Touch_Init; + +(* + if (e_JoysticksAvailable > 0) then + e_WriteLog('Input: Joysticks available.', TMsgType.Notify) + else + e_WriteLog('Input: No Joysticks.', TMsgType.Notify); +*) + + if (not gNoSound) then + begin + e_WriteLog('Initializing sound system', TMsgType.Notify); + e_InitSoundSystem(NoSound); + end; + + e_WriteLog('Init game', TMsgType.Notify); + g_Game_Init(); + +// FillChar(charbuff, sizeof(charbuff), ' '); +end; + +procedure Release(); +begin + e_WriteLog('Releasing engine', TMsgType.Notify); + e_ReleaseEngine(); + + e_WriteLog('Releasing input', TMsgType.Notify); + e_ReleaseInput(); + + if not gNoSound then + begin + e_WriteLog('Releasing sound', TMsgType.Notify); + e_ReleaseSoundSystem(); + end; +end; + procedure ResetTimer (); begin wNeedTimeReset := true; diff --git a/src/game/opengl/r_console.pas b/src/game/opengl/r_console.pas index e7a0b6a..1d5081e 100644 --- a/src/game/opengl/r_console.pas +++ b/src/game/opengl/r_console.pas @@ -25,9 +25,9 @@ implementation uses SysUtils, Classes, Math, - e_log, r_graphics, + e_log, r_graphics, g_options, conbuf, - g_base, g_main, g_console, g_game, g_menu, g_textures + g_base, g_console, g_game, g_menu, g_textures ; (* ====== Console ====== *) diff --git a/src/game/opengl/r_playermodel.pas b/src/game/opengl/r_playermodel.pas index 9b0f244..2f40e9f 100644 --- a/src/game/opengl/r_playermodel.pas +++ b/src/game/opengl/r_playermodel.pas @@ -28,8 +28,8 @@ implementation uses SysUtils, Classes, Math, MAPDEF, - r_graphics, - g_base, g_basic, g_map, g_weapons, g_textures, g_main + r_graphics, g_options, + g_base, g_basic, g_map, g_weapons, g_textures ; const diff --git a/src/game/sdl/g_system.pas b/src/game/sdl/g_system.pas index fe7225f..7527073 100644 --- a/src/game/sdl/g_system.pas +++ b/src/game/sdl/g_system.pas @@ -37,13 +37,16 @@ interface procedure sys_Init; procedure sys_Final; + var (* hooks *) + sys_CharPress: procedure (ch: AnsiChar) = nil; + implementation uses SysUtils, SDL, Math, {$INCLUDE ../nogl/noGLuses.inc} e_log, r_graphics, e_input, e_sound, - g_options, g_window, g_console, g_game, g_menu, g_gui, g_main, g_basic; + g_options, g_window, g_console, g_game, g_menu, g_gui, g_basic; const GameTitle = 'Doom 2D: Forever (SDL 1.2, %s)'; @@ -453,8 +456,9 @@ implementation begin g_Console_ProcessBindRepeat(key) end; - if down and IsValid1251(ev.keysym.unicode) and IsPrintable1251(ch) then - CharPress(ch) + if @sys_CharPress <> nil then + if down and IsValid1251(ev.keysym.unicode) and IsPrintable1251(ch) then + sys_CharPress(ch) end; procedure HandleResize (var ev: TSDL_ResizeEvent); diff --git a/src/game/sdl2/g_system.pas b/src/game/sdl2/g_system.pas index 40e0dff..fd79aa6 100644 --- a/src/game/sdl2/g_system.pas +++ b/src/game/sdl2/g_system.pas @@ -37,6 +37,9 @@ interface procedure sys_Init; procedure sys_Final; + var (* hooks *) + sys_CharPress: procedure (ch: AnsiChar) = nil; + implementation uses @@ -46,7 +49,7 @@ implementation {$IFDEF ENABLE_HOLMES} g_holmes, sdlcarcass, fui_ctls, {$ENDIF} - g_touch, g_options, g_window, g_console, g_game, g_menu, g_gui, g_main, g_basic; + g_touch, g_options, g_window, g_console, g_game, g_menu, g_gui, g_basic; const GameTitle = 'Doom 2D: Forever (SDL 2, %s)'; @@ -522,8 +525,9 @@ implementation sch := AnsiChar(wchar2win(ch)); if g_dbg_input then e_LogWritefln('Input Debug: text, text="%s", ch = %s, sch = %s', [ev.text, Ord(ch), Ord(sch)]); - if IsValid1251(Word(ch)) and IsPrintable1251(ch) then - CharPress(sch); + if @sys_CharPress <> nil then + if IsValid1251(Word(ch)) and IsPrintable1251(ch) then + sys_CharPress(sch) end; function sys_HandleInput (): Boolean; diff --git a/src/game/sdl2/g_touch.pas b/src/game/sdl2/g_touch.pas index c6a9e23..12a4664 100644 --- a/src/game/sdl2/g_touch.pas +++ b/src/game/sdl2/g_touch.pas @@ -36,7 +36,7 @@ implementation uses SysUtils, - e_log, r_graphics, e_input, g_options, g_game, g_main, g_gui, g_weapons, g_console, g_window; + e_log, r_graphics, e_input, g_options, g_game, g_gui, g_weapons, g_console, g_window; var angleFire: Boolean; diff --git a/src/game/stub/g_system.pas b/src/game/stub/g_system.pas index c3b4b23..4e4f423 100644 --- a/src/game/stub/g_system.pas +++ b/src/game/stub/g_system.pas @@ -37,6 +37,9 @@ interface procedure sys_Init; procedure sys_Final; + var (* hooks *) + sys_CharPress: procedure (ch: AnsiChar) = nil; + implementation uses SysUtils; -- 2.29.2