mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2025-03-31 23:41:25 +00:00
filesystem: sort files in pack and use binary search in packs
This commit is contained in:
parent
ae4845782c
commit
30861e07ef
1 changed files with 107 additions and 49 deletions
|
@ -353,6 +353,54 @@ FS_FCloseFile(fileHandle_t f)
|
|||
memset(handle, 0, sizeof(*handle));
|
||||
}
|
||||
|
||||
static int
|
||||
FS_SortPackCompare(const void *p1, const void *p2)
|
||||
{
|
||||
fsPackFile_t *file1, *file2;
|
||||
|
||||
file1 = (fsPackFile_t*)p1;
|
||||
file2 = (fsPackFile_t*)p2;
|
||||
return Q_stricmp(file1->name, file2->name);
|
||||
}
|
||||
|
||||
static void
|
||||
FS_SortPack(fsPack_t *pak)
|
||||
{
|
||||
qsort(pak->files, pak->numFiles, sizeof(fsPackFile_t), FS_SortPackCompare);
|
||||
}
|
||||
|
||||
static int
|
||||
FS_PackQuickSearch(const fsPack_t *pak, const char *name)
|
||||
{
|
||||
int start, end;
|
||||
|
||||
start = 0;
|
||||
end = pak->numFiles;
|
||||
|
||||
while (start <= end)
|
||||
{
|
||||
int i, res;
|
||||
|
||||
i = start + (end - start) / 2;
|
||||
|
||||
res = Q_stricmp(pak->files[i].name, name);
|
||||
if (res == 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
else if (res < 0)
|
||||
{
|
||||
start = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
end = i - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the file in the search path. Returns filesize and an open FILE *. Used
|
||||
* for streaming data out of either a pak file or a seperate file.
|
||||
|
@ -364,14 +412,14 @@ FS_FOpenFile(const char *rawname, fileHandle_t *f, qboolean gamedir_only)
|
|||
fsHandle_t *handle;
|
||||
fsPack_t *pack;
|
||||
fsSearchPath_t *search;
|
||||
int i;
|
||||
int input, output;
|
||||
|
||||
// Remove self references and empty dirs from the requested path.
|
||||
// ZIPs and PAKs don't support them, but they may be hardcoded in
|
||||
// some custom maps or models.
|
||||
char name[MAX_QPATH] = {0};
|
||||
size_t namelen = strlen(rawname);
|
||||
for (int input = 0, output = 0; input < namelen; input++)
|
||||
for (input = 0, output = 0; input < namelen; input++)
|
||||
{
|
||||
// Remove self reference.
|
||||
if (rawname[input] == '.')
|
||||
|
@ -448,74 +496,74 @@ FS_FOpenFile(const char *rawname, fileHandle_t *f, qboolean gamedir_only)
|
|||
/* Search inside a pack file. */
|
||||
if (search->pack)
|
||||
{
|
||||
int i;
|
||||
|
||||
pack = search->pack;
|
||||
i = FS_PackQuickSearch(pack, handle->name);
|
||||
|
||||
for (i = 0; i < pack->numFiles; i++)
|
||||
if (i >= 0)
|
||||
{
|
||||
if (Q_stricmp(pack->files[i].name, handle->name) == 0)
|
||||
/* Found it! */
|
||||
if (fs_debug->value)
|
||||
{
|
||||
/* Found it! */
|
||||
if (fs_debug->value)
|
||||
Com_Printf("FS_FOpenFile: '%s' (found in '%s').\n",
|
||||
handle->name, pack->name);
|
||||
}
|
||||
|
||||
// save the name with *correct case* in the handle
|
||||
// (relevant for savegames, when starting map with wrong case but it's still found
|
||||
// because it's from pak, but save/bla/MAPname.sav/sv2 will have wrong case and can't be found then)
|
||||
Q_strlcpy(handle->name, pack->files[i].name, sizeof(handle->name));
|
||||
handle->compressed_size = 0;
|
||||
handle->format = PAK_MODE_Q2;
|
||||
|
||||
if (pack->pak)
|
||||
{
|
||||
/* PAK and DAT */
|
||||
if (pack->isProtectedPak)
|
||||
{
|
||||
Com_Printf("FS_FOpenFile: '%s' (found in '%s').\n",
|
||||
handle->name, pack->name);
|
||||
file_from_protected_pak = true;
|
||||
}
|
||||
|
||||
// save the name with *correct case* in the handle
|
||||
// (relevant for savegames, when starting map with wrong case but it's still found
|
||||
// because it's from pak, but save/bla/MAPname.sav/sv2 will have wrong case and can't be found then)
|
||||
Q_strlcpy(handle->name, pack->files[i].name, sizeof(handle->name));
|
||||
handle->compressed_size = 0;
|
||||
handle->format = PAK_MODE_Q2;
|
||||
handle->file = Q_fopen(pack->name, "rb");
|
||||
|
||||
if (pack->pak)
|
||||
if (handle->file)
|
||||
{
|
||||
/* PAK and DAT */
|
||||
if (pack->isProtectedPak)
|
||||
{
|
||||
file_from_protected_pak = true;
|
||||
}
|
||||
|
||||
handle->file = Q_fopen(pack->name, "rb");
|
||||
|
||||
if (handle->file)
|
||||
{
|
||||
handle->compressed_size = pack->files[i].compressed_size;
|
||||
handle->format = pack->files[i].format;
|
||||
fseek(handle->file, pack->files[i].offset, SEEK_SET);
|
||||
return pack->files[i].size;
|
||||
}
|
||||
handle->compressed_size = pack->files[i].compressed_size;
|
||||
handle->format = pack->files[i].format;
|
||||
fseek(handle->file, pack->files[i].offset, SEEK_SET);
|
||||
return pack->files[i].size;
|
||||
}
|
||||
else if (pack->pk3)
|
||||
}
|
||||
else if (pack->pk3)
|
||||
{
|
||||
/* PK3 */
|
||||
if (pack->isProtectedPak)
|
||||
{
|
||||
/* PK3 */
|
||||
if (pack->isProtectedPak)
|
||||
{
|
||||
file_from_protected_pak = true;
|
||||
}
|
||||
file_from_protected_pak = true;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
handle->zip = unzOpen2(pack->name, &zlib_file_api);
|
||||
handle->zip = unzOpen2(pack->name, &zlib_file_api);
|
||||
#else
|
||||
handle->zip = unzOpen(pack->name);
|
||||
handle->zip = unzOpen(pack->name);
|
||||
#endif
|
||||
|
||||
if (handle->zip)
|
||||
if (handle->zip)
|
||||
{
|
||||
if (unzLocateFile(handle->zip, handle->name, 2) == UNZ_OK)
|
||||
{
|
||||
if (unzLocateFile(handle->zip, handle->name, 2) == UNZ_OK)
|
||||
if (unzOpenCurrentFile(handle->zip) == UNZ_OK)
|
||||
{
|
||||
if (unzOpenCurrentFile(handle->zip) == UNZ_OK)
|
||||
{
|
||||
return pack->files[i].size;
|
||||
}
|
||||
return pack->files[i].size;
|
||||
}
|
||||
|
||||
unzClose(handle->zip);
|
||||
}
|
||||
}
|
||||
|
||||
Com_Error(ERR_FATAL, "Couldn't reopen '%s'", pack->name);
|
||||
unzClose(handle->zip);
|
||||
}
|
||||
}
|
||||
|
||||
Com_Error(ERR_FATAL, "Couldn't reopen '%s'", pack->name);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1301,8 +1349,10 @@ FS_LoadPAK(const char *packPath)
|
|||
}
|
||||
|
||||
fclose(handle);
|
||||
|
||||
Com_Printf("WARNING: skipped unsupported '%s' PAK format.\n",
|
||||
packPath);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -2058,8 +2108,12 @@ FS_AddPAKFromGamedir(const char *pak)
|
|||
}
|
||||
else
|
||||
{
|
||||
fsSearchPath_t *search;
|
||||
|
||||
FS_SortPack(pakfile);
|
||||
|
||||
// Add it.
|
||||
fsSearchPath_t *search = Z_Malloc(sizeof(fsSearchPath_t));
|
||||
search = Z_Malloc(sizeof(fsSearchPath_t));
|
||||
search->pack = pakfile;
|
||||
search->next = fs_searchPaths;
|
||||
fs_searchPaths = search;
|
||||
|
@ -2204,6 +2258,8 @@ FS_AddDirToSearchPath(char *dir, qboolean create) {
|
|||
continue;
|
||||
}
|
||||
|
||||
FS_SortPack(pack);
|
||||
|
||||
search = Z_Malloc(sizeof(fsSearchPath_t));
|
||||
search->pack = pack;
|
||||
search->next = fs_searchPaths;
|
||||
|
@ -2278,6 +2334,8 @@ FS_AddDirToSearchPath(char *dir, qboolean create) {
|
|||
continue;
|
||||
}
|
||||
|
||||
FS_SortPack(pack);
|
||||
|
||||
pack->isProtectedPak = false;
|
||||
|
||||
search = Z_Malloc(sizeof(fsSearchPath_t));
|
||||
|
|
Loading…
Reference in a new issue