Compare commits
3 Commits
main
...
olympus-su
Author | SHA1 | Date |
---|---|---|
Alexander Batalov | 8d4057366e | |
Alexander Batalov | 80b58bd174 | |
Alexander Batalov | ca268ecb2c |
31
src/dfile.cc
31
src/dfile.cc
|
@ -43,6 +43,8 @@ static int dfileReadCharInternal(DFile* stream);
|
||||||
static bool dfileReadCompressed(DFile* stream, void* ptr, size_t size);
|
static bool dfileReadCompressed(DFile* stream, void* ptr, size_t size);
|
||||||
static void dfileUngetCompressed(DFile* stream, int ch);
|
static void dfileUngetCompressed(DFile* stream, int ch);
|
||||||
|
|
||||||
|
static void dfile_normalize_path(char* path);
|
||||||
|
|
||||||
// Reads .DAT file contents.
|
// Reads .DAT file contents.
|
||||||
//
|
//
|
||||||
// 0x4E4F58
|
// 0x4E4F58
|
||||||
|
@ -122,6 +124,9 @@ DBase* dbaseOpen(const char* filePath)
|
||||||
|
|
||||||
entry->path[pathLength] = '\0';
|
entry->path[pathLength] = '\0';
|
||||||
|
|
||||||
|
// CE: Normalize entry path.
|
||||||
|
dfile_normalize_path(entry->path);
|
||||||
|
|
||||||
if (fread(&(entry->compressed), sizeof(entry->compressed), 1, stream) != 1) {
|
if (fread(&(entry->compressed), sizeof(entry->compressed), 1, stream) != 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -201,11 +206,18 @@ bool dbaseClose(DBase* dbase)
|
||||||
// 0x4E5308
|
// 0x4E5308
|
||||||
bool dbaseFindFirstEntry(DBase* dbase, DFileFindData* findFileData, const char* pattern)
|
bool dbaseFindFirstEntry(DBase* dbase, DFileFindData* findFileData, const char* pattern)
|
||||||
{
|
{
|
||||||
|
// CE: Normalize pattern to match entries. Underlying `fpattern`
|
||||||
|
// implementation is case-sensitive on non-Windows platforms, so both
|
||||||
|
// pattern and entries should match in case and have native path separators.
|
||||||
|
char normalizedPattern[COMPAT_MAX_PATH];
|
||||||
|
strcpy(normalizedPattern, pattern);
|
||||||
|
dfile_normalize_path(normalizedPattern);
|
||||||
|
|
||||||
for (int index = 0; index < dbase->entriesLength; index++) {
|
for (int index = 0; index < dbase->entriesLength; index++) {
|
||||||
DBaseEntry* entry = &(dbase->entries[index]);
|
DBaseEntry* entry = &(dbase->entries[index]);
|
||||||
if (fpattern_match(pattern, entry->path)) {
|
if (fpattern_match(normalizedPattern, entry->path)) {
|
||||||
strcpy(findFileData->fileName, entry->path);
|
strcpy(findFileData->fileName, entry->path);
|
||||||
strcpy(findFileData->pattern, pattern);
|
strcpy(findFileData->pattern, normalizedPattern);
|
||||||
findFileData->index = index;
|
findFileData->index = index;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -632,7 +644,14 @@ static int dbaseFindEntryByFilePath(const void* a1, const void* a2)
|
||||||
// 0x4E5D9C
|
// 0x4E5D9C
|
||||||
static DFile* dfileOpenInternal(DBase* dbase, const char* filePath, const char* mode, DFile* dfile)
|
static DFile* dfileOpenInternal(DBase* dbase, const char* filePath, const char* mode, DFile* dfile)
|
||||||
{
|
{
|
||||||
DBaseEntry* entry = (DBaseEntry*)bsearch(filePath, dbase->entries, dbase->entriesLength, sizeof(*dbase->entries), dbaseFindEntryByFilePath);
|
// CE: Normalize path to match entries. Even though
|
||||||
|
// `dbaseFindEntryByFilePath` uses case-insensitive compare, it still needs
|
||||||
|
// native path separators.
|
||||||
|
char normalizedFilePath[COMPAT_MAX_PATH];
|
||||||
|
strcpy(normalizedFilePath, filePath);
|
||||||
|
dfile_normalize_path(normalizedFilePath);
|
||||||
|
|
||||||
|
DBaseEntry* entry = (DBaseEntry*)bsearch(normalizedFilePath, dbase->entries, dbase->entriesLength, sizeof(*dbase->entries), dbaseFindEntryByFilePath);
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -854,4 +873,10 @@ static void dfileUngetCompressed(DFile* stream, int ch)
|
||||||
stream->position--;
|
stream->position--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dfile_normalize_path(char* path)
|
||||||
|
{
|
||||||
|
compat_windows_path_to_native(path);
|
||||||
|
compat_strlwr(path);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace fallout
|
} // namespace fallout
|
||||||
|
|
|
@ -4663,8 +4663,31 @@ static void opGetPartyMember(Program* program)
|
||||||
// 0x45C6DC
|
// 0x45C6DC
|
||||||
static void opGetRotationToTile(Program* program)
|
static void opGetRotationToTile(Program* program)
|
||||||
{
|
{
|
||||||
int tile2 = programStackPopInteger(program);
|
// CE: There is a bug in Olympus (tgrdqest) - object is passed as one of the
|
||||||
int tile1 = programStackPopInteger(program);
|
// arguments instead of tile. Original game (x86) does not distinguish
|
||||||
|
// between integers and pointers, so one of the tiles is silently ignored
|
||||||
|
// while calculating rotation. As a workaround this opcode now accepts
|
||||||
|
// both integers and objects.
|
||||||
|
ProgramValue value2 = programStackPopValue(program);
|
||||||
|
ProgramValue value1 = programStackPopValue(program);
|
||||||
|
|
||||||
|
int tile2;
|
||||||
|
if (value2.isInt()) {
|
||||||
|
tile2 = value2.integerValue;
|
||||||
|
} else if (value2.isPointer()) {
|
||||||
|
tile2 = static_cast<Object*>(value2.pointerValue)->tile;
|
||||||
|
} else {
|
||||||
|
programFatalError("script error: %s: invalid arg 2 to rotation_to_tile", program->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tile1;
|
||||||
|
if (value1.isInt()) {
|
||||||
|
tile1 = value1.integerValue;
|
||||||
|
} else if (value1.isPointer()) {
|
||||||
|
tile1 = static_cast<Object*>(value1.pointerValue)->tile;
|
||||||
|
} else {
|
||||||
|
programFatalError("script error: %s: invalid arg 1 to rotation_to_tile", program->name);
|
||||||
|
}
|
||||||
|
|
||||||
int rotation = tileGetRotationTo(tile1, tile2);
|
int rotation = tileGetRotationTo(tile1, tile2);
|
||||||
programStackPushInteger(program, rotation);
|
programStackPushInteger(program, rotation);
|
||||||
|
|
|
@ -46,17 +46,21 @@ bool sfall_gl_scr_init()
|
||||||
*end = '\0';
|
*end = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
char drive[COMPAT_MAX_DRIVE];
|
char path[COMPAT_MAX_PATH];
|
||||||
char dir[COMPAT_MAX_DIR];
|
strcpy(path, curr);
|
||||||
compat_splitpath(curr, drive, dir, nullptr, nullptr);
|
|
||||||
|
char* fname = strrchr(path, '\\');
|
||||||
|
if (fname != nullptr) {
|
||||||
|
fname += 1;
|
||||||
|
} else {
|
||||||
|
fname = path;
|
||||||
|
}
|
||||||
|
|
||||||
char** files;
|
char** files;
|
||||||
int filesLength = fileNameListInit(curr, &files, 0, 0);
|
int filesLength = fileNameListInit(curr, &files, 0, 0);
|
||||||
if (filesLength != 0) {
|
if (filesLength != 0) {
|
||||||
for (int index = 0; index < filesLength; index++) {
|
for (int index = 0; index < filesLength; index++) {
|
||||||
char path[COMPAT_MAX_PATH];
|
strcpy(fname, files[index]);
|
||||||
compat_makepath(path, drive, dir, files[index], nullptr);
|
|
||||||
|
|
||||||
state->paths.push_back(std::string { path });
|
state->paths.push_back(std::string { path });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue