summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 1f8100a)
raw | patch | inline | side by side (parent: 1f8100a)
author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Tue, 15 Jun 2021 15:44:26 +0000 (18:44 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Tue, 29 Jun 2021 09:51:12 +0000 (12:51 +0300) |
25 files changed:
diff --git a/src/game/Doom2DF.lpr b/src/game/Doom2DF.lpr
index f42c4b57cc24d2def0530e4701e0e1834e33fb20..bbbcdd3089eeacf26c5e688d19b377a3e1b76990 100644 (file)
--- a/src/game/Doom2DF.lpr
+++ b/src/game/Doom2DF.lpr
ctypes,
{$ENDIF}
{$IFDEF UNIX}
- cthreads,
+ cthreads, BaseUnix,
+{$ENDIF}
+{$IFDEF DARWIN}
+ MacOSAll, CocoaAll,
{$ENDIF}
mempool in '../shared/mempool.pas',
conbuf in '../shared/conbuf.pas',
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',
{$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
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 9db9e79273ebc64c28d7c789b1ac37a88fa58c55..02beb87ee76fc14509f2d5253f9c666a59d70972 100644 (file)
--- a/src/game/g_console.pas
+++ b/src/game/g_console.pas
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 6fc6035b7944ad839a09033261edef58ba675c59..9095b1d4ab6de440e131a4fbfd1aaf2ffb2c90b5 100644 (file)
--- a/src/game/g_game.pas
+++ b/src/game/g_game.pas
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
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: // <Esc>:
+ 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 // <F2> .. <F6> � <F12>
+ 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 b31ead3b2da0b03712af63801a5f2ba2da972dbb..7f74dc18f600bfd8e24343f0a1d98797560c9c61 100644 (file)
--- a/src/game/g_holmes.pas
+++ b/src/game/g_holmes.pas
{$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 02c8b5fc86dc50e62410e335f7fa0eb61aafea48..6c8041ddd97bfe0ba46c4e2081f5dd1ffd8ab866 100644 (file)
--- a/src/game/g_items.pas
+++ b/src/game/g_items.pas
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
--- 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 <http://www.gnu.org/licenses/>.
- *)
-{$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: // <Esc>:
- 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 // <F2> .. <F6> � <F12>
- 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 7ec904be0437189e8670f3079ed3a3ff8481c4e5..eb9454263364990821dbb6ab0bdd5b4bc4ded22c 100644 (file)
--- a/src/game/g_map.pas
+++ b/src/game/g_map.pas
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 61da4c4b89857cad02e905c8c9b78429db4b4f77..265bade66424b2a0412cac54634581691f123a91 100644 (file)
--- a/src/game/g_menu.pas
+++ b/src/game/g_menu.pas
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,
index 434730b492cccf9c686c0d5c546dd5fa57fa40a3..5824ffe082020edf16f9c29e215005f4e38a789f 100644 (file)
--- a/src/game/g_monsters.pas
+++ b/src/game/g_monsters.pas
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 63e4cb91ed172945f96137fe185d91895a5f6020..2316d1c7e5e77f354434d250c393a516c38660e4 100644 (file)
--- a/src/game/g_net.pas
+++ b/src/game/g_net.pas
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 b5edf0afdcfcc5950293be410d82d0f7b35eb202..c49ffaa6aa6ae4a192465faad13ef82a7e3e3973 100644 (file)
--- a/src/game/g_netmsg.pas
+++ b/src/game/g_netmsg.pas
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 487dbd22b9c286bc2ebaea676535b69d6fa2d8d8..f1f0653493f8ba86a2b3c107d89c75871090f0fd 100644 (file)
--- a/src/game/g_options.pas
+++ b/src/game/g_options.pas
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
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 e2e9e97e645187117633e7b6d47fbeb930d41eeb..dab24aed016a61ee69982a742f4aac794d9b6e17 100644 (file)
--- a/src/game/g_player.pas
+++ b/src/game/g_player.pas
{$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;
index 9b018cb216d53d5dc161702bace1ed287250be0f..b2f57e6c95997ff2835acc80f58380b4ec6827ca 100644 (file)
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
index 7fc295119c4cdada4b8e7b98f8db5fb2026f6f6e..8bd5e04cd70ddd6dcd87e2be585261c3e067c480 100644 (file)
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)
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
index eb1a79a8db17dd725634f3e4f8ae28319a6e2493..32f6821770c20af0affaf213d2b5ee23853e6cc2 100644 (file)
--- a/src/game/g_saveload.pas
+++ b/src/game/g_saveload.pas
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'
index f89aa9f3de7f89d23c63367c846260100139e9a3..e8891a06467dffaf806ba96cb96dabc9dbe824b1 100644 (file)
--- a/src/game/g_triggers.pas
+++ b/src/game/g_triggers.pas
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 21c580375a533aa95e6f2dc6b8e9e0791bb52c27..81767e653f03be80e7d7a5b58fb7dd0970db4413 100644 (file)
--- a/src/game/g_weapons.pas
+++ b/src/game/g_weapons.pas
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 4e84b5d53eb9823a4b5234c44a38cbbc99ca9077..bfd4377830c271bc278fe5480357782093cec5f7 100644 (file)
--- a/src/game/g_window.pas
+++ b/src/game/g_window.pas
{$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,
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;
index e7a0b6a81e28522ef7b1c2e9e6c3f64998629065..1d5081efaa2975ed967e95eff00af459d3b87533 100644 (file)
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 ====== *)
index 9b0f244eed5d4ea446a524f161f5b1386125f1a4..2f40e9fea9f8aa6cf7c8769c46105ee2c8b55cb1 100644 (file)
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
index fe7225f6573ebfdaa68a1649600b74e12b600b66..7527073c1ad7e0ad811001cf519c7bcf2476bd46 100644 (file)
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)';
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);
index 40e0dff752b0b90b3ac59a9ebf9246cb96314896..fd79aa60e30f651f9ecda934dcc1d90bf1cbc674 100644 (file)
procedure sys_Init;
procedure sys_Final;
+ var (* hooks *)
+ sys_CharPress: procedure (ch: AnsiChar) = nil;
+
implementation
uses
{$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)';
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;
index c6a9e232048d3e5b670ad063c7f92a4753e990a9..12a46645989b8d016dd6cc056c3aeab61e4ad935 100644 (file)
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;
index c3b4b23e0ee43fbacdec4756a62f4bdd782c4dcd..4e4f42377e3da2e59abb09b1967ce97add6ad01f 100644 (file)
procedure sys_Init;
procedure sys_Final;
+ var (* hooks *)
+ sys_CharPress: procedure (ch: AnsiChar) = nil;
+
implementation
uses SysUtils;