mirror of
https://github.com/ZDoom/Raze.git
synced 2025-01-31 04:20:42 +00:00
- tested and fixed game list loader.
This commit is contained in:
parent
2a7beeff69
commit
c6753a3fec
10 changed files with 148 additions and 175 deletions
|
@ -138,34 +138,6 @@ void G_ExtInit(void)
|
|||
CommandPaths = s;
|
||||
}
|
||||
}
|
||||
|
||||
if (!access("user_profiles_enabled", F_OK))
|
||||
{
|
||||
char *homedir;
|
||||
int32_t asperr;
|
||||
|
||||
if ((homedir = Bgethomedir()))
|
||||
{
|
||||
Bsnprintf(cwd,sizeof(cwd),"%s/"
|
||||
#if defined(_WIN32)
|
||||
APPNAME
|
||||
#elif defined(GEKKO)
|
||||
"apps/" APPBASENAME
|
||||
#else
|
||||
".config/" APPBASENAME
|
||||
#endif
|
||||
,homedir);
|
||||
asperr = addsearchpath(cwd);
|
||||
if (asperr == -2)
|
||||
{
|
||||
if (Bmkdir(cwd,S_IRWXU) == 0) asperr = addsearchpath(cwd);
|
||||
else asperr = -1;
|
||||
}
|
||||
if (asperr == 0)
|
||||
Bchdir(cwd);
|
||||
Bfree(homedir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t G_TryLoadingGrp(char const * const grpfile)
|
||||
|
|
|
@ -132,7 +132,7 @@ bool CDemo::Create(const char *pzFile)
|
|||
for (int i = 0; i < 8 && !vc; i++)
|
||||
{
|
||||
G_ModDirSnprintf(buffer, BMAX_PATH, "%s0%02d.dem", BloodIniPre, i);
|
||||
if (access(buffer, F_OK) != -1)
|
||||
if (access(buffer, 0) != -1)
|
||||
vc = 1;
|
||||
}
|
||||
if (vc == 1)
|
||||
|
|
|
@ -672,10 +672,6 @@ inline void Bexit(int a)
|
|||
# define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define strtoll _strtoi64
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
|
@ -687,34 +683,6 @@ inline void Bexit(int a)
|
|||
# define F_OK 0
|
||||
#endif
|
||||
|
||||
#ifdef GEKKO
|
||||
# undef PRIdPTR
|
||||
# define PRIdPTR "d"
|
||||
# undef PRIxPTR
|
||||
# define PRIxPTR "x"
|
||||
# undef SCNx32
|
||||
# define SCNx32 "x"
|
||||
#endif
|
||||
|
||||
#if defined EDUKE32_OSX
|
||||
# if !defined __x86_64__ && defined __GNUC__
|
||||
// PK 20110617: is*() crashes for me in x86 code compiled from 64-bit, and gives link errors on ppc
|
||||
// This hack patches all occurences.
|
||||
# define isdigit(ch) ({ int32_t c__dontuse_=ch; c__dontuse_>='0' && c__dontuse_<='9'; })
|
||||
# define isalpha(ch) ({ int32_t c__dontuse2_=ch; (c__dontuse2_>='A' && c__dontuse2_<='Z') || (c__dontuse2_>='a' && c__dontuse2_<='z'); })
|
||||
# define isalnum(ch2) ({ int32_t c2__dontuse_=ch2; isalpha(c2__dontuse_) || isdigit(c2__dontuse_); })
|
||||
# if defined __BIG_ENDIAN__
|
||||
# define isspace(ch) ({ int32_t c__dontuse_=ch; (c__dontuse_==' ' || c__dontuse_=='\t' || c__dontuse_=='\n' || c__dontuse_=='\v' || c__dontuse_=='\f' || c__dontuse_=='\r'); })
|
||||
# define isprint(ch) ({ int32_t c__dontuse_=ch; (c__dontuse_>=0x20 && c__dontuse_<0x7f); })
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
void eduke32_exit_return(int) ATTRIBUTE((noreturn));
|
||||
# define exit(x) eduke32_exit_return(x)
|
||||
#endif
|
||||
|
||||
|
||||
////////// Metaprogramming structs //////////
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ static inline int64_t buildvfs_flength(FILE * f)
|
|||
return buildvfs_length(fileno(f));
|
||||
#endif
|
||||
}
|
||||
#define buildvfs_exists(fn) (access((fn), F_OK) == 0)
|
||||
#define buildvfs_exists(fn) (access((fn), 0) == 0)
|
||||
static inline int buildvfs_isdir(char const *path)
|
||||
{
|
||||
struct Bstat st;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
InputState inputState;
|
||||
void SetClipshapes();
|
||||
TArray<FString> CollectSearchPaths();
|
||||
|
||||
struct GameFuncNameDesc
|
||||
{
|
||||
|
@ -308,11 +307,11 @@ void CONFIG_Init()
|
|||
G_LoadConfig();
|
||||
// Startup dialog must be presented here so that everything can be set up before reading the keybinds.
|
||||
|
||||
TArray<FString> paths = CollectSearchPaths();
|
||||
for (auto& path : paths)
|
||||
auto groups = GrpScan();
|
||||
for (auto& grp : groups)
|
||||
{
|
||||
OutputDebugStringA(path);
|
||||
OutputDebugStringA("\r\n");
|
||||
FStringf grpinfo("%s: %s, %s, %s, %s\r\n", grp.FileInfo.name.GetChars(), grp.FileName.GetChars(), grp.FileInfo.scriptname.GetChars(), grp.FileInfo.rtsname.GetChars(), grp.FileInfo.defname.GetChars());
|
||||
OutputDebugStringA(grpinfo);
|
||||
}
|
||||
LumpFilter = currentGame;
|
||||
if (LumpFilter.Compare("Redneck") == 0) LumpFilter = "Redneck.Redneck";
|
||||
|
|
|
@ -132,4 +132,32 @@ enum
|
|||
GAMEFLAG_STANDALONE = 0x00000800,
|
||||
GAMEFLAGMASK = 0x000007FF, // flags allowed from grpinfo
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct GrpInfo
|
||||
{
|
||||
FString name;
|
||||
FString scriptname;
|
||||
FString dirname;
|
||||
FString defname;
|
||||
FString rtsname;
|
||||
FString gamefilter;
|
||||
uint32_t CRC = 0;
|
||||
uint32_t dependencyCRC = 0;
|
||||
size_t size = 0;
|
||||
int flags = 0;
|
||||
TArray<FString> loadfiles;
|
||||
TArray<FString> loadart;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct GrpEntry
|
||||
{
|
||||
FString FileName;
|
||||
GrpInfo FileInfo;
|
||||
uint32_t FileIndex;
|
||||
};
|
||||
|
||||
TArray<GrpEntry> GrpScan();
|
||||
|
|
|
@ -39,32 +39,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
|
||||
|
||||
|
||||
// These two structs need to be expoted
|
||||
struct GrpInfo
|
||||
{
|
||||
FString name;
|
||||
FString scriptname;
|
||||
FString dirname;
|
||||
FString defname;
|
||||
FString rtsname;
|
||||
uint32_t CRC = 0;
|
||||
uint32_t dependencyCRC = 0;
|
||||
size_t size = 0;
|
||||
int flags = 0;
|
||||
TArray<FString> loadfiles;
|
||||
TArray<FString> loadart;
|
||||
};
|
||||
|
||||
|
||||
struct GrpEntry
|
||||
{
|
||||
FString FileName;
|
||||
GrpInfo FileInfo;
|
||||
uint32_t FileIndex;
|
||||
};
|
||||
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
||||
|
@ -578,7 +552,6 @@ TArray<FileEntry> CollectAllFilesInSearchPath()
|
|||
flentry.FileLength = entry.file_size();
|
||||
flentry.FileTime = entry.last_write_time().time_since_epoch().count();
|
||||
flentry.Index = index++; // to preserve order when working on the list.
|
||||
filelist.Push(flentry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -604,19 +577,20 @@ static TArray<FileEntry> LoadCRCCache(void)
|
|||
while (sc.GetString())
|
||||
{
|
||||
crclist.Reserve(1);
|
||||
auto flentry = crclist.Last();
|
||||
auto &flentry = crclist.Last();
|
||||
flentry.FileName = sc.String;
|
||||
sc.MustGetString();
|
||||
flentry.FileLength = strtoull(sc.String, nullptr, 0); // Cannot use sc.Number because that's only 32 bit.
|
||||
sc.MustGetString();
|
||||
flentry.FileTime = strtoull(sc.String, nullptr, 0); // Cannot use sc.Number because that's only 32 bit.
|
||||
sc.MustGetString();
|
||||
flentry.CRCValue = strtoull(sc.String, nullptr, 0); // Cannot use sc.Number because that's only 32 bit.
|
||||
sc.MustGetNumber();
|
||||
flentry.FileLength = sc.BigNumber;
|
||||
sc.MustGetNumber();
|
||||
flentry.FileTime = sc.BigNumber;
|
||||
sc.MustGetNumber();
|
||||
flentry.CRCValue = (unsigned)sc.BigNumber;
|
||||
}
|
||||
}
|
||||
catch (std::runtime_error &)
|
||||
catch (std::runtime_error &err)
|
||||
{
|
||||
// If there's a parsing error, return what we got and discard the rest.
|
||||
OutputDebugStringA(err.what());
|
||||
}
|
||||
return crclist;
|
||||
}
|
||||
|
@ -627,10 +601,31 @@ static TArray<FileEntry> LoadCRCCache(void)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static TArray<GrpInfo> ParseGrpInfo(const char *fn, FileReader &fr)
|
||||
void SaveCRCs(TArray<FileEntry>& crclist)
|
||||
{
|
||||
auto cachepath = M_GetAppDataPath(true) + "/grpcrccache.txt";
|
||||
|
||||
FileWriter* fw = FileWriter::Open(cachepath);
|
||||
if (fw)
|
||||
{
|
||||
for (auto& crc : crclist)
|
||||
{
|
||||
FStringf line("\"%s\" %llu %llu %u\n", crc.FileName.GetChars(), (long long)crc.FileLength, (long long)crc.FileTime, crc.CRCValue);
|
||||
fw->Write(line.GetChars(), line.Len());
|
||||
}
|
||||
delete fw;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static TArray<GrpInfo> ParseGrpInfo(const char *fn, FileReader &fr, TMap<FString, uint32_t> &CRCMap)
|
||||
{
|
||||
TArray<GrpInfo> groups;
|
||||
TMap<FString, uint32_t> CRCMap;
|
||||
TMap<FString, int> FlagMap;
|
||||
|
||||
FlagMap.Insert("GAMEFLAG_DUKE", GAMEFLAG_DUKE);
|
||||
|
@ -667,10 +662,10 @@ static TArray<GrpInfo> ParseGrpInfo(const char *fn, FileReader &fr)
|
|||
CRCMap.Insert(key, (uint32_t)sc.BigNumber);
|
||||
}
|
||||
}
|
||||
if (sc.Compare("grpinfo"))
|
||||
else if (sc.Compare("grpinfo"))
|
||||
{
|
||||
groups.Reserve(1);
|
||||
auto grp = groups.Last();
|
||||
auto& grp = groups.Last();
|
||||
sc.MustGetToken('{');
|
||||
while (!sc.CheckToken('}'))
|
||||
{
|
||||
|
@ -700,6 +695,11 @@ static TArray<GrpInfo> ParseGrpInfo(const char *fn, FileReader &fr)
|
|||
sc.MustGetToken(TK_StringConst);
|
||||
grp.rtsname = sc.String;
|
||||
}
|
||||
else if (sc.Compare("gamefilter"))
|
||||
{
|
||||
sc.MustGetToken(TK_StringConst);
|
||||
grp.gamefilter = sc.String;
|
||||
}
|
||||
else if (sc.Compare("crc"))
|
||||
{
|
||||
sc.MustGetAnyToken();
|
||||
|
@ -707,6 +707,11 @@ static TArray<GrpInfo> ParseGrpInfo(const char *fn, FileReader &fr)
|
|||
{
|
||||
grp.CRC = (uint32_t)sc.BigNumber;
|
||||
}
|
||||
else if (sc.TokenType == '-')
|
||||
{
|
||||
sc.MustGetToken(TK_IntConst);
|
||||
grp.CRC = (uint32_t)-sc.BigNumber;
|
||||
}
|
||||
else if (sc.TokenType == TK_Identifier)
|
||||
{
|
||||
auto ip = CRCMap.CheckKey(sc.String);
|
||||
|
@ -722,6 +727,11 @@ static TArray<GrpInfo> ParseGrpInfo(const char *fn, FileReader &fr)
|
|||
{
|
||||
grp.dependencyCRC = (uint32_t)sc.BigNumber;
|
||||
}
|
||||
else if (sc.TokenType == '-')
|
||||
{
|
||||
sc.MustGetToken(TK_IntConst);
|
||||
grp.dependencyCRC = (uint32_t)-sc.BigNumber;
|
||||
}
|
||||
else if (sc.TokenType == TK_Identifier)
|
||||
{
|
||||
auto ip = CRCMap.CheckKey(sc.String);
|
||||
|
@ -789,6 +799,7 @@ static TArray<GrpInfo> ParseGrpInfo(const char *fn, FileReader &fr)
|
|||
TArray<GrpInfo> ParseAllGrpInfos(TArray<FileEntry>& filelist)
|
||||
{
|
||||
TArray<GrpInfo> groups;
|
||||
TMap<FString, uint32_t> CRCMap;
|
||||
extern FString progdir;
|
||||
// This opens the base resource only for reading the grpinfo from it.
|
||||
std::unique_ptr<FResourceFile> engine_res;
|
||||
|
@ -802,7 +813,7 @@ TArray<GrpInfo> ParseAllGrpInfos(TArray<FileEntry>& filelist)
|
|||
auto fr = basegrp->NewReader();
|
||||
if (fr.isOpen())
|
||||
{
|
||||
groups = ParseGrpInfo("demolition/demolition.grpinfo", fr);
|
||||
groups = ParseGrpInfo("demolition/demolition.grpinfo", fr, CRCMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -818,7 +829,7 @@ TArray<GrpInfo> ParseAllGrpInfos(TArray<FileEntry>& filelist)
|
|||
FileReader fr;
|
||||
if (fr.OpenFile(entry.FileName))
|
||||
{
|
||||
auto g = ParseGrpInfo(entry.FileName, fr);
|
||||
auto g = ParseGrpInfo(entry.FileName, fr, CRCMap);
|
||||
groups.Append(g);
|
||||
}
|
||||
}
|
||||
|
@ -838,7 +849,7 @@ void GetCRC(FileEntry *entry, TArray<FileEntry> &CRCCache)
|
|||
for (auto &ce : CRCCache)
|
||||
{
|
||||
// File size, modification date snd name all must match exactly to pick an entry.
|
||||
if (entry->FileLength == ce.FileLength && entry->FileTime == ce.FileTime && entry->FileName.Compare(ce.FileName))
|
||||
if (entry->FileLength == ce.FileLength && entry->FileTime == ce.FileTime && entry->FileName.Compare(ce.FileName) == 0)
|
||||
{
|
||||
entry->CRCValue = ce.CRCValue;
|
||||
return;
|
||||
|
@ -880,28 +891,29 @@ GrpInfo *IdentifyGroup(FileEntry *entry, TArray<GrpInfo *> &groups)
|
|||
TArray<GrpEntry> GrpScan()
|
||||
{
|
||||
TArray<GrpEntry> foundGames;
|
||||
|
||||
TArray<FileEntry *> sortedFileList;
|
||||
TArray<GrpInfo *> sortedGroupList;
|
||||
|
||||
|
||||
TArray<FileEntry*> sortedFileList;
|
||||
TArray<GrpInfo*> sortedGroupList;
|
||||
|
||||
auto allFiles = CollectAllFilesInSearchPath();
|
||||
auto allGroups = ParseAllGrpInfos(allFiles);
|
||||
|
||||
auto cachedCRCs = LoadCRCCache();
|
||||
|
||||
auto numCRCs = cachedCRCs.Size();
|
||||
|
||||
// Remove all unnecessary content from the file list. Since this contains all data from the search path's directories it can be quite large.
|
||||
// Sort both lists by file size so that we only need to pass over each list once to weed out all unrelated content. Go backward to avoid too much item movement
|
||||
// (most will be deleted anyway.)
|
||||
for (auto &f : allFiles) sortedFileList.Push(&f);
|
||||
for (auto &g : allGroups) sortedGroupList.Push(&g);
|
||||
|
||||
for (auto& f : allFiles) sortedFileList.Push(&f);
|
||||
for (auto& g : allGroups) sortedGroupList.Push(&g);
|
||||
|
||||
std::sort(sortedFileList.begin(), sortedFileList.end(), [](FileEntry* lhs, FileEntry* rhs) { return lhs->FileLength < rhs->FileLength; });
|
||||
std::sort(sortedGroupList.begin(), sortedGroupList.end(), [](GrpInfo* lhs, GrpInfo* rhs) { return lhs->size < rhs->size; });
|
||||
|
||||
int findex = sortedFileList.Size();
|
||||
int gindex = sortedGroupList.Size();
|
||||
int cindex = sortedGroupList.Size();
|
||||
int findex = sortedFileList.Size() - 1;
|
||||
int gindex = sortedGroupList.Size() - 1;
|
||||
|
||||
while (findex > 0 || gindex > 0)
|
||||
while (findex > 0 && gindex > 0)
|
||||
{
|
||||
if (sortedFileList[findex]->FileLength > sortedGroupList[gindex]->size)
|
||||
{
|
||||
|
@ -915,12 +927,19 @@ TArray<GrpEntry> GrpScan()
|
|||
}
|
||||
else
|
||||
{
|
||||
findex--;
|
||||
gindex--;
|
||||
// We found a matching file. Skip over all other entries of the same size so we can analyze those later as well
|
||||
while (findex > 0 && sortedFileList[findex]->FileLength == sortedFileList[findex-1]->FileLength) findex--;
|
||||
while (gindex > 0 && sortedGroupList[gindex]->size == sortedGroupList[gindex-1]->size) gindex--;
|
||||
while (findex > 0 && sortedFileList[findex]->FileLength == sortedFileList[findex + 1]->FileLength) findex--;
|
||||
while (gindex > 0 && sortedGroupList[gindex]->size == sortedGroupList[gindex + 1]->size) gindex--;
|
||||
}
|
||||
}
|
||||
sortedFileList.Delete(0, findex + 1);
|
||||
sortedGroupList.Delete(0, gindex + 1);
|
||||
|
||||
if (sortedGroupList.Size() == 0 || sortedFileList.Size() == 0)
|
||||
return foundGames;
|
||||
|
||||
for (auto entry : sortedFileList)
|
||||
{
|
||||
GetCRC(entry, cachedCRCs);
|
||||
|
@ -928,21 +947,21 @@ TArray<GrpEntry> GrpScan()
|
|||
if (grp)
|
||||
{
|
||||
foundGames.Reserve(1);
|
||||
auto fg = foundGames.Last();
|
||||
auto& fg = foundGames.Last();
|
||||
fg.FileInfo = *grp;
|
||||
fg.FileName = entry->FileName;
|
||||
fg.FileIndex = entry->Index;
|
||||
}
|
||||
}
|
||||
|
||||
// One last thing: We must check for all addons if their dependency is present.
|
||||
for( int i = foundGames.Size()-1; i >= 0; i--)
|
||||
|
||||
// We must check for all addons if their dependency is present.
|
||||
for (int i = foundGames.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
auto crc = foundGames[i].FileInfo.dependencyCRC;
|
||||
if (crc != 0)
|
||||
{
|
||||
bool found = false;
|
||||
for (auto fg : foundGames)
|
||||
for (auto& fg : foundGames)
|
||||
{
|
||||
if (fg.FileInfo.CRC == crc)
|
||||
{
|
||||
|
@ -953,6 +972,31 @@ TArray<GrpEntry> GrpScan()
|
|||
if (!found) foundGames.Delete(i); // Dependent add-on without dependency cannot be played.
|
||||
}
|
||||
}
|
||||
|
||||
// return everything to its proper order (using qsort because sorting an array of complex structs with std::sort is a messy affair.)
|
||||
qsort(foundGames.Data(), foundGames.Size(), sizeof(foundGames[0]), [](const void* a, const void* b)->int
|
||||
{
|
||||
auto A = (const GrpEntry*)a;
|
||||
auto B = (const GrpEntry*)b;
|
||||
return (int)A->FileIndex - (int)B->FileIndex;
|
||||
});
|
||||
|
||||
// Finally, scan the list for duplicstes. Only the first occurence should count.
|
||||
|
||||
for (unsigned i = 0; i < foundGames.Size(); i++)
|
||||
{
|
||||
for (unsigned j = foundGames.Size(); j > i; j--)
|
||||
{
|
||||
if (foundGames[i].FileInfo.CRC == foundGames[j].FileInfo.CRC)
|
||||
foundGames.Delete(j);
|
||||
}
|
||||
}
|
||||
|
||||
// new CRCs got added so save the list.
|
||||
if (cachedCRCs.Size() > numCRCs)
|
||||
{
|
||||
SaveCRCs(cachedCRCs);
|
||||
}
|
||||
|
||||
// Do we have anything left? If not, error out
|
||||
if (foundGames.Size() == 0)
|
||||
|
|
|
@ -167,8 +167,8 @@ void FScanner::Open (const char *name)
|
|||
void FScanner::OpenFile (const char *name)
|
||||
{
|
||||
Close ();
|
||||
auto fr = fopenFileReader(name, 0);
|
||||
if (!fr.isOpen()) return;
|
||||
FileReader fr;
|
||||
if (!fr.OpenFile(name)) return;
|
||||
auto data = fr.ReadPadded(1);
|
||||
ScriptBuffer = data;
|
||||
ScriptName = name; // This is used for error messages so the full file name is preferable
|
||||
|
@ -631,7 +631,8 @@ bool FScanner::GetNumber ()
|
|||
}
|
||||
else
|
||||
{
|
||||
Number = strtol (String, &stopper, 0);
|
||||
BigNumber = strtoll(String, &stopper, 0);
|
||||
Number = (int)clamp(BigNumber, INT_MIN, INT_MAX);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
ScriptError ("SC_GetNumber: Bad numeric constant \"%s\".", String);
|
||||
|
@ -682,11 +683,13 @@ bool FScanner::CheckNumber ()
|
|||
}
|
||||
else if (strcmp (String, "MAXINT") == 0)
|
||||
{
|
||||
BigNumber = INT64_MAX;
|
||||
Number = INT_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
Number = strtol (String, &stopper, 0);
|
||||
BigNumber = strtoll (String, &stopper, 0);
|
||||
Number = (int)clamp(BigNumber, INT_MIN, INT_MAX);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
UnGet();
|
||||
|
|
|
@ -247,46 +247,6 @@ void G_ExtInit(void)
|
|||
CommandPaths = s;
|
||||
}
|
||||
}
|
||||
|
||||
if (!access("user_profiles_enabled", F_OK))
|
||||
{
|
||||
char *homedir;
|
||||
int32_t asperr;
|
||||
|
||||
if ((homedir = Bgethomedir()))
|
||||
{
|
||||
Bsnprintf(cwd,sizeof(cwd),"%s/"
|
||||
#if defined(_WIN32)
|
||||
APPNAME
|
||||
#elif defined(GEKKO)
|
||||
"apps/" APPBASENAME
|
||||
#else
|
||||
".config/" APPBASENAME
|
||||
#endif
|
||||
,homedir);
|
||||
asperr = addsearchpath(cwd);
|
||||
if (asperr == -2)
|
||||
{
|
||||
if (Bmkdir(cwd,S_IRWXU) == 0) asperr = addsearchpath(cwd);
|
||||
else asperr = -1;
|
||||
}
|
||||
if (asperr == 0)
|
||||
Bchdir(cwd);
|
||||
Bfree(homedir);
|
||||
}
|
||||
}
|
||||
|
||||
// JBF 20031220: Because it's annoying renaming GRP files whenever I want to test different game data
|
||||
if (g_grpNamePtr == NULL)
|
||||
{
|
||||
const char *cp = getenv("DUKE3DGRP");
|
||||
if (cp)
|
||||
{
|
||||
clearGrpNamePtr();
|
||||
g_grpNamePtr = dup_filename(cp);
|
||||
initprintf("Using \"%s\" as main GRP file\n", g_grpNamePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G_ScanGroups(void)
|
||||
|
|
|
@ -340,7 +340,6 @@ grpinfo
|
|||
scriptname "GAME66.CON"
|
||||
flags GAMEFLAG_RR|GAMEFLAG_ADDON
|
||||
dependency RR_CRC
|
||||
loaddirectory
|
||||
loadart "TILESA66.ART", "TILESB66.ART"
|
||||
gamefilter "Redneck.Route66"
|
||||
}
|
||||
|
@ -359,7 +358,7 @@ grpinfo
|
|||
|
||||
grpinfo
|
||||
{
|
||||
name "BlOOD: Cryptic Passage"
|
||||
name "BLOOD: Cryptic Passage"
|
||||
crc 0x2144DF1C // tests CP01.MAP
|
||||
size 327015
|
||||
loaddirectory "CP01.MAP"
|
||||
|
|
Loading…
Reference in a new issue