DEADSOFTWARE

fix work under msdos
[d2df-sdl.git] / src / shared / utils.pas
index 59a49f251dbb3b927cfea195b442f38ab3656ae8..89ecb9097fa605ac105f6b1e9cb4b5d6409f39ce 100644 (file)
@@ -1,4 +1,4 @@
-(* Copyright (C)  DooM 2D:Forever Developers
+(* 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
@@ -100,6 +100,9 @@ function utf8to1251 (s: AnsiString): AnsiString;
 // nobody cares about shitdoze, so i'll use the same code path for it
 function findFileCI (var pathname: AnsiString; lastIsDir: Boolean=false): Boolean;
 
+// return fixed AnsiString or empty AnsiString
+function findDiskWad (fname: AnsiString): AnsiString;
+
 // they throws
 function openDiskFileRO (pathname: AnsiString): TStream;
 function createDiskFile (pathname: AnsiString): TStream;
@@ -162,7 +165,9 @@ function nmin (a, b: Int64): Int64; inline; overload;
 function nmin (a, b: UInt64): UInt64; inline; overload;
 function nmin (a, b: Single): Single; inline; overload;
 function nmin (a, b: Double): Double; inline; overload;
+{$IF DEFINED(CPU386) OR DEFINED(CPUAMD64)}
 function nmin (a, b: Extended): Extended; inline; overload;
+{$ENDIF}
 
 function nmax (a, b: Byte): Byte; inline; overload;
 function nmax (a, b: ShortInt): ShortInt; inline; overload;
@@ -174,8 +179,9 @@ function nmax (a, b: Int64): Int64; inline; overload;
 function nmax (a, b: UInt64): UInt64; inline; overload;
 function nmax (a, b: Single): Single; inline; overload;
 function nmax (a, b: Double): Double; inline; overload;
+{$IF DEFINED(CPU386) OR DEFINED(CPUAMD64)}
 function nmax (a, b: Extended): Extended; inline; overload;
-
+{$ENDIF}
 function nclamp (v, a, b: Byte): Byte; inline; overload;
 function nclamp (v, a, b: ShortInt): ShortInt; inline; overload;
 function nclamp (v, a, b: Word): Word; inline; overload;
@@ -186,8 +192,9 @@ function nclamp (v, a, b: Int64): Int64; inline; overload;
 function nclamp (v, a, b: UInt64): UInt64; inline; overload;
 function nclamp (v, a, b: Single): Single; inline; overload;
 function nclamp (v, a, b: Double): Double; inline; overload;
+{$IF DEFINED(CPU386) OR DEFINED(CPUAMD64)}
 function nclamp (v, a, b: Extended): Extended; inline; overload;
-
+{$ENDIF}
 
 type
   TFormatStrFCallback = procedure (constref buf; len: SizeUInt);
@@ -266,9 +273,15 @@ procedure ZeroMemory (Dest: Pointer; Len: LongWord); inline;
 
 implementation
 
-uses
-  xstreams;
+  uses
+    xstreams, StrUtils, e_Log;
 
+  const
+    {$IFDEF GO32V2}
+      DirSep = '\';
+    {$ELSE}
+      DirSep = '/';
+    {$ENDIF}
 
 // ////////////////////////////////////////////////////////////////////////// //
 procedure CopyMemory (Dest: Pointer; Src: Pointer; Len: LongWord); inline;
@@ -751,7 +764,7 @@ var
   pos: Integer;
   ch: AnsiChar;
 begin
-  if (Length(fn) = 0) then begin result := './'; exit; end;
+  if (Length(fn) = 0) then begin result := '.' + DirSep; exit; end;
   if (fn[Length(fn)] = '/') or (fn[Length(fn)] = '\') then begin result := fn; exit; end;
   pos := Length(fn);
   while (pos > 0) do
@@ -760,7 +773,7 @@ begin
     if (ch = '/') or (ch = '\') then begin result := Copy(fn, 1, pos); exit; end;
     Dec(pos);
   end;
-  result := './'; // no path -> current dir
+  result := '.' + DirSep; // no path -> current dir
 end;
 
 
@@ -787,7 +800,7 @@ begin
   pos := 1;
   while (pos <= Length(fn)) and ((fn[pos] = '/') or (fn[pos] = '\')) do Inc(pos);
   result := path;
-  if (Length(result) > 0) and ((result[Length(result)] <> '/') and (result[Length(result)] <> '\')) then result += '/';
+  if (Length(result) > 0) and ((result[Length(result)] <> '/') and (result[Length(result)] <> '\')) then result += DirSep;
   if (pos <= Length(fn)) then
   begin
     result += Copy(fn, pos, Length(fn)-pos+1);
@@ -796,7 +809,7 @@ begin
     begin
       Delete(result, Length(result), 1);
     end;
-    if (fn[Length(fn)] = '/') or (fn[Length(fn)] = '\') then result += '/';
+    if (fn[Length(fn)] = '/') or (fn[Length(fn)] = '\') then result += DirSep;
   end;
 end;
 
@@ -806,7 +819,7 @@ var
   ext: AnsiString;
 begin
   ext := getFilenameExt(fn);
-  result := StrEquCI1251(ext, '.wad') or StrEquCI1251(ext, '.pk3') or StrEquCI1251(ext, '.zip');
+  result := StrEquCI1251(ext, '.wad') or StrEquCI1251(ext, '.pk3') or StrEquCI1251(ext, '.zip') or StrEquCI1251(ext, '.dfz');
 end;
 
 
@@ -832,7 +845,7 @@ begin
       if (pos-4 > 1) and (fn[pos-4] = '.') and ((fn[pos+1] = '\') or (fn[pos+1] = '/')) then
       begin
         s := Copy(fn, pos-4, 4);
-        if StrEquCI1251(s, '.wad') or StrEquCI1251(s, '.pk3') or StrEquCI1251(s, '.zip') then
+        if StrEquCI1251(s, '.wad') or StrEquCI1251(s, '.pk3') or StrEquCI1251(s, '.zip') or StrEquCI1251(s, '.dfz') then
         begin
           result := true;
           exit;
@@ -1069,7 +1082,7 @@ var
 begin
   npt := pathname;
   result := (length(npt) > 0);
-  if (length(npt) > 0) and ((npt[1] = '/') or (npt[1] = '\')) then newname := '/';
+  if (length(npt) > 0) and ((npt[1] = '/') or (npt[1] = '\')) then newname := DirSep;
   while length(npt) > 0 do
   begin
     // remove trailing slashes
@@ -1085,7 +1098,7 @@ begin
     // remove trailing slashes again
     while (length(npt) > 0) and ((npt[1] = '/') or (npt[1] = '\')) do Delete(npt, 1, 1);
     wantdir := lastIsDir or (length(npt) > 0); // do we want directory here?
-    //writeln(Format('npt=[%s]; newname=[%s]; curname=[%s]; wantdir=%d', [npt, newname, curname, Integer(wantdir)]));
+    //e_LogWritefln('npt=[%s]; newname=[%s]; curname=[%s]; wantdir=%d', [npt, newname, curname, Integer(wantdir)]);
     // try the easiest case first
     attr := FileGetAttr(newname+curname);
     if attr <> -1 then
@@ -1094,11 +1107,11 @@ begin
       begin
         // i found her!
         newname := newname+curname;
-        if wantdir then newname := newname+'/';
+        if wantdir then newname := newname + DirSep;
         continue;
       end;
     end;
-    //writeln(Format('npt=[%s]; newname=[%s]; curname=[%s]; wantdir=%d', [npt, newname, curname, Integer(wantdir)]));
+    //e_LogWritefLn('npt=[%s]; newname=[%s]; curname=[%s]; wantdir=%d', [npt, newname, curname, Integer(wantdir)]);
     // alas, either not found, or invalid attributes
     foundher := false;
     try
@@ -1108,7 +1121,7 @@ begin
         begin
           // i found her!
           newname := newname+sr.name;
-          if wantdir then newname := newname+'/';
+          if wantdir then newname := newname + DirSep;
           foundher := true;
           break;
         end;
@@ -1122,8 +1135,52 @@ begin
 end;
 
 
+(** Replace slashes to backslashes for DOS **)
+function FixFileName (filename: AnsiString): AnsiString;
+begin
+  {$IFDEF GO32V2}
+    Result := StringReplace(filename, '/', '\', [rfReplaceAll, rfIgnoreCase])
+  {$ELSE}
+    Result := filename
+  {$ENDIF}
+end;
+
+
+const fileExtensions: array [0..6] of AnsiString = ('.wad', '.dfzip', '.dfwad', '.pk3', '.pak', '.zip', '.dfz');
+
+function findDiskWad (fname: AnsiString): AnsiString;
+var
+  origExt: AnsiString = '';
+  newExt: AnsiString = '';
+begin
+  result := '';
+{$IFDEF GO32V2}
+  // FIXIT: it didn't work under MSDOS for some reason, so i just cut extension replacement
+  result := FixFileName(fname);
+{$ELSE}
+  //e_LogWriteLn('findDiskWad00: fname=<' + fname + '>');
+  if (findFileCI(fname)) then begin result := fname; exit; end;
+  origExt := getFilenameExt(fname);
+  fname := forceFilenameExt(fname, '');
+  //e_LogWriteLn(' findDiskWad01: fname=<' + fname + '>; origExt=<' + origExt + '>');
+  for newExt in fileExtensions do
+  begin
+    //e_LogWriteLn(' findDiskWad02: fname=<' + fname + '>; origExt=<' + origExt + '>; newExt=<' + newExt + '>');
+    if (StrEquCI1251(newExt, origExt)) then
+    begin
+      //e_LogWriteLn('   SKIP');
+      continue;
+    end;
+    result := fname+newExt;
+    if (findFileCI(result)) then exit;
+  end;
+  result := '';
+{$ENDIF}
+end;
+
 function openDiskFileRO (pathname: AnsiString): TStream;
 begin
+  pathname := FixFileName(pathname);
   if not findFileCI(pathname) then raise Exception.Create('can''t open file "'+pathname+'"');
   result := TFileStream.Create(pathname, fmOpenRead or {fmShareDenyWrite}fmShareDenyNone);
 end;
@@ -1132,6 +1189,7 @@ function createDiskFile (pathname: AnsiString): TStream;
 var
   path: AnsiString;
 begin
+  pathname := FixFileName(pathname);
   path := ExtractFilePath(pathname);
   if length(path) > 0 then
   begin
@@ -1321,7 +1379,9 @@ function nmin (a, b: Int64): Int64; inline; overload; begin if (a < b) then resu
 function nmin (a, b: UInt64): UInt64; inline; overload; begin if (a < b) then result := a else result := b; end;
 function nmin (a, b: Single): Single; inline; overload; begin if (a < b) then result := a else result := b; end;
 function nmin (a, b: Double): Double; inline; overload; begin if (a < b) then result := a else result := b; end;
+{$IF DEFINED(CPU386) OR DEFINED(CPUAMD64)}
 function nmin (a, b: Extended): Extended; inline; overload; begin if (a < b) then result := a else result := b; end;
+{$ENDIF}
 
 function nmax (a, b: Byte): Byte; inline; overload; begin if (a > b) then result := a else result := b; end;
 function nmax (a, b: ShortInt): ShortInt; inline; overload; begin if (a > b) then result := a else result := b; end;
@@ -1333,7 +1393,9 @@ function nmax (a, b: Int64): Int64; inline; overload; begin if (a > b) then resu
 function nmax (a, b: UInt64): UInt64; inline; overload; begin if (a > b) then result := a else result := b; end;
 function nmax (a, b: Single): Single; inline; overload; begin if (a > b) then result := a else result := b; end;
 function nmax (a, b: Double): Double; inline; overload; begin if (a > b) then result := a else result := b; end;
+{$IF DEFINED(CPU386) OR DEFINED(CPUAMD64)}
 function nmax (a, b: Extended): Extended; inline; overload; begin if (a > b) then result := a else result := b; end;
+{$ENDIF}
 
 function nclamp (v, a, b: Byte): Byte; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
 function nclamp (v, a, b: ShortInt): ShortInt; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
@@ -1345,14 +1407,19 @@ function nclamp (v, a, b: Int64): Int64; inline; overload; begin if (v < a) then
 function nclamp (v, a, b: UInt64): UInt64; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
 function nclamp (v, a, b: Single): Single; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
 function nclamp (v, a, b: Double): Double; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
+{$IF DEFINED(CPU386) OR DEFINED(CPUAMD64)}
 function nclamp (v, a, b: Extended): Extended; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
-
+{$ENDIF}
 
 // ////////////////////////////////////////////////////////////////////////// //
 {$IFDEF WINDOWS}
 function snprintf (buf: PAnsiChar; bufsize: SizeUInt; const fmt: PAnsiChar): SizeUInt; cdecl; varargs; external 'msvcrt.dll' name '_snprintf';
 {$ELSE}
+  {$IFDEF GO32V2}
+function snprintf (buf: PAnsiChar; bufsize: SizeUInt; const fmt: PAnsiChar): SizeUInt; cdecl; varargs; external;
+  {$ELSE}
 function snprintf (buf: PAnsiChar; bufsize: SizeUInt; const fmt: PAnsiChar): SizeUInt; cdecl; varargs; external 'libc' name 'snprintf';
+  {$ENDIF}
 {$ENDIF}