Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Olympus support #299

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions src/dfile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ static int dfileReadCharInternal(DFile* stream);
static bool dfileReadCompressed(DFile* stream, void* ptr, size_t size);
static void dfileUngetCompressed(DFile* stream, int ch);

static void dfile_normalize_path(char* path);

// Reads .DAT file contents.
//
// 0x4E4F58
Expand Down Expand Up @@ -122,6 +124,9 @@ DBase* dbaseOpen(const char* filePath)

entry->path[pathLength] = '\0';

// CE: Normalize entry path.
dfile_normalize_path(entry->path);

if (fread(&(entry->compressed), sizeof(entry->compressed), 1, stream) != 1) {
break;
}
Expand Down Expand Up @@ -201,11 +206,18 @@ bool dbaseClose(DBase* dbase)
// 0x4E5308
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++) {
DBaseEntry* entry = &(dbase->entries[index]);
if (fpattern_match(pattern, entry->path)) {
if (fpattern_match(normalizedPattern, entry->path)) {
strcpy(findFileData->fileName, entry->path);
strcpy(findFileData->pattern, pattern);
strcpy(findFileData->pattern, normalizedPattern);
findFileData->index = index;
return true;
}
Expand Down Expand Up @@ -632,7 +644,14 @@ static int dbaseFindEntryByFilePath(const void* a1, const void* a2)
// 0x4E5D9C
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) {
goto err;
}
Expand Down Expand Up @@ -854,4 +873,10 @@ static void dfileUngetCompressed(DFile* stream, int ch)
stream->position--;
}

static void dfile_normalize_path(char* path)
{
compat_windows_path_to_native(path);
compat_strlwr(path);
}

} // namespace fallout
27 changes: 25 additions & 2 deletions src/interpreter_extra.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4663,8 +4663,31 @@ static void opGetPartyMember(Program* program)
// 0x45C6DC
static void opGetRotationToTile(Program* program)
{
int tile2 = programStackPopInteger(program);
int tile1 = programStackPopInteger(program);
// CE: There is a bug in Olympus (tgrdqest) - object is passed as one of the
// 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the bug should be fixed in the script?) Sounds like a rabbit hole allowing such ambiguity in arguments. If it says tile num, it should be tile num IMO.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe good to implement original game behavior - just ignore, maybe with warning

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, keep the original behavior (only accept int) but write warning in the debug log. This is a really bad idea to try and hack the engine around bugs in scripts :)

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);
programStackPushInteger(program, rotation);
Expand Down
16 changes: 10 additions & 6 deletions src/sfall_global_scripts.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,21 @@ bool sfall_gl_scr_init()
*end = '\0';
}

char drive[COMPAT_MAX_DRIVE];
char dir[COMPAT_MAX_DIR];
compat_splitpath(curr, drive, dir, nullptr, nullptr);
char path[COMPAT_MAX_PATH];
strcpy(path, curr);

char* fname = strrchr(path, '\\');
if (fname != nullptr) {
fname += 1;
} else {
fname = path;
}

char** files;
int filesLength = fileNameListInit(curr, &files, 0, 0);
if (filesLength != 0) {
for (int index = 0; index < filesLength; index++) {
char path[COMPAT_MAX_PATH];
compat_makepath(path, drive, dir, files[index], nullptr);

strcpy(fname, files[index]);
state->paths.push_back(std::string { path });
}

Expand Down