Fixed and refactored code in FileSystem.cpp (from Mr.Stalin)

This commit is contained in:
NovaRain
2019-01-20 00:18:32 +08:00
parent 82f068c3e7
commit 774e31b9f6
3 changed files with 95 additions and 89 deletions
+1 -1
View File
@@ -60,7 +60,7 @@ get/set_unspent_ap_bonus alter the AC bonus you receive per unused action point
nb_* functions are reserved for the brotherhood tactical training mod, and should be avoided. nb_* functions are reserved for the brotherhood tactical training mod, and should be avoided.
The fs_* functions are used to manipulate a virtual file system. Files saved here should have paths relative to the data folder, and use backslashes as the directory separator. They will take precedence over files stored in the normal data folder. They will also be saved into save games, so be avoid creating large files. Using fs_copy followed by fs_read_xxx, you can read the contents of existing files. The fs_* functions are used to manipulate a virtual file system. Files saved here should have paths relative to the data folder, and use backslashes as the directory separator. They will take precedence over files stored in the normal data folder. They will also be saved into save games if you set a flag for them using fs_resize(fileId, -1), so be avoid creating large files. Using fs_copy followed by fs_read_xxx, you can read the contents of existing files.
get/set_proto_data are used to manipulate the in memory copies of the .pro files Fallout makes when they are loaded. The offset refers to the offset in memory from the start of the proto to the element you are reading. Changes are not stored on disc, and are not permanent. If you modify the protos, and then Fallout subsequently reloads the file your changes will be lost. get/set_proto_data are used to manipulate the in memory copies of the .pro files Fallout makes when they are loaded. The offset refers to the offset in memory from the start of the proto to the element you are reading. Changes are not stored on disc, and are not permanent. If you modify the protos, and then Fallout subsequently reloads the file your changes will be lost.
+1 -1
View File
@@ -219,7 +219,7 @@
0x81e9 - int get_unspent_ap_perk_bonus() 0x81e9 - int get_unspent_ap_perk_bonus()
0x81ec - float sqrt(float) 0x81ec - float sqrt(float)
0x81ed - float abs(float) 0x81ed - int/float abs(int/float)
0x81ee - float sin(float) 0x81ee - float sin(float)
0x81ef - float cos(float) 0x81ef - float cos(float)
0x81f0 - float tan(float) 0x81f0 - float tan(float)
+93 -87
View File
@@ -27,20 +27,18 @@
namespace sfall namespace sfall
{ {
#define MAX_FILE_SIZE 0xA00000
struct fsFile { struct fsFile {
char* data; BYTE* data;
DWORD length; DWORD length;
char name[128]; char name[128];
DWORD wpos; DWORD wpos; // current fs read/write position
BYTE isSave;
}; };
std::vector<fsFile> files;
static DWORD loadedFiles = 0;
bool FileSystem::UsingFileSystem = false;
struct openFile { struct openFile {
DWORD pos; DWORD pos; // current xread/xwrite position
fsFile* file; fsFile* file;
openFile(fsFile* pFile) { openFile(fsFile* pFile) {
@@ -51,11 +49,16 @@ struct openFile {
struct sFile { struct sFile {
DWORD type; DWORD type;
openFile* file; openFile* opnFile;
}; };
std::vector<fsFile> files;
static DWORD loadedFiles = 0; // used for internal sfall data
bool FileSystem::UsingFileSystem = false;
static void _stdcall xfclose(sFile* file) { static void _stdcall xfclose(sFile* file) {
delete file->file; delete file->opnFile;
delete file; delete file;
} }
@@ -78,7 +81,7 @@ static sFile* _stdcall xfopen(const char* path, const char* mode) {
if (!_stricmp(path, files[i].name)) { if (!_stricmp(path, files[i].name)) {
sFile* file = new sFile(); sFile* file = new sFile();
file->type = 3; file->type = 3;
file->file = new openFile(&files[i]); file->opnFile = new openFile(&files[i]);
return file; return file;
} }
} }
@@ -121,9 +124,9 @@ end:
} }
} }
static int _stdcall xfgetc(sFile* file) { static DWORD _stdcall xfgetc(sFile* file) {
if (file->file->pos >= file->file->file->length) return -1; if (file->opnFile->pos >= file->opnFile->file->length) return -1;
return file->file->file->data[file->file->pos++]; return static_cast<DWORD>(file->opnFile->file->data[file->opnFile->pos++]);
} }
static __declspec(naked) int asm_xfgetc(sFile* file) { static __declspec(naked) int asm_xfgetc(sFile* file) {
@@ -143,7 +146,7 @@ end:
} }
static char* _stdcall xfgets(char* buf, int max_count, sFile* file) { static char* _stdcall xfgets(char* buf, int max_count, sFile* file) {
if (file->file->pos >= file->file->file->length) return 0; if (file->opnFile->pos >= file->opnFile->file->length) return 0;
for (int i = 0; i < max_count; i++) { for (int i = 0; i < max_count; i++) {
int c = xfgetc(file); int c = xfgetc(file);
if (c == -1) { if (c == -1) {
@@ -212,9 +215,9 @@ end:
} }
static int _stdcall xfungetc(int c, sFile* file) { static int _stdcall xfungetc(int c, sFile* file) {
if (file->file->pos == 0) return -1; if (file->opnFile->pos == 0) return -1;
if (file->file->file->data[file->file->pos - 1] != c) return -1; if (file->opnFile->file->data[file->opnFile->pos - 1] != static_cast<BYTE>(c)) return -1;
file->file->pos--; file->opnFile->pos--;
return c; return c;
} }
@@ -235,9 +238,10 @@ end:
static int __fastcall xfread(sFile* file, int elsize, void* buf, int count) { static int __fastcall xfread(sFile* file, int elsize, void* buf, int count) {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
if (file->file->pos + elsize >= file->file->file->length) return i; if (file->opnFile->pos + elsize > file->opnFile->file->length) return i;
memcpy(buf, &file->file->file->data[file->file->pos], elsize);
file->file->pos += elsize; memcpy(buf, &file->opnFile->file->data[file->opnFile->pos], elsize);
file->opnFile->pos += elsize;
} }
return count; return count;
} }
@@ -275,13 +279,13 @@ end:
static int _stdcall xfseek(sFile* file, long pos, int origin) { static int _stdcall xfseek(sFile* file, long pos, int origin) {
switch(origin) { switch(origin) {
case 0: case 0:
file->file->pos = pos; file->opnFile->pos = pos;
break; break;
case 1: case 1:
file->file->pos += pos; file->opnFile->pos += pos;
break; break;
case 2: case 2:
file->file->pos = file->file->file->length + pos; file->opnFile->pos = file->opnFile->file->length + pos;
break; break;
} }
return 0; return 0;
@@ -304,7 +308,7 @@ end:
} }
static long _stdcall xftell(sFile* file) { static long _stdcall xftell(sFile* file) {
return file->file->pos; return file->opnFile->pos;
} }
static __declspec(naked) long asm_xftell(sFile* file) { static __declspec(naked) long asm_xftell(sFile* file) {
@@ -324,8 +328,9 @@ end:
} }
static void _stdcall xfrewind(sFile* file) { static void _stdcall xfrewind(sFile* file) {
file->file->pos = 0; file->opnFile->pos = 0;
} }
static __declspec(naked) void asm_xfrewind(sFile* file) { static __declspec(naked) void asm_xfrewind(sFile* file) {
__asm { __asm {
cmp [eax], 3; cmp [eax], 3;
@@ -341,7 +346,7 @@ end:
} }
static int _stdcall xfeof(sFile* file) { static int _stdcall xfeof(sFile* file) {
if (file->file->pos >= file->file->file->length) { if (file->opnFile->pos >= file->opnFile->file->length) {
return 1; return 1;
} }
return 0; return 0;
@@ -364,7 +369,7 @@ end:
} }
static int _stdcall xfilelength(sFile* file) { static int _stdcall xfilelength(sFile* file) {
return file->file->file->length; return file->opnFile->file->length;
} }
static __declspec(naked) int asm_xfilelength(sFile* file) { static __declspec(naked) int asm_xfilelength(sFile* file) {
@@ -384,25 +389,25 @@ end:
} }
void FileSystemReset() { void FileSystemReset() {
//if (!FileSystem::UsingFileSystem) return; if (files.empty()) return;
for (DWORD i = loadedFiles; i < files.size(); i++) { for (DWORD i = loadedFiles; i < files.size(); i++) {
if (files[i].data) delete[] files[i].data; if (files[i].data) delete[] files[i].data;
} }
if (!loadedFiles) { if (!loadedFiles) {
files.clear(); files.clear();
} else { } else {
for (DWORD i = files.size() - 1; i >= loadedFiles; i--) files.erase(files.begin() + i); files.erase(files.begin() + loadedFiles, files.end() - 1);
} }
} }
void FileSystem::Save(HANDLE h) { void FileSystem::Save(HANDLE h) {
DWORD count = 0, unused; DWORD count = 0, unused;
for (DWORD i = 0; i < files.size(); i++) { for (DWORD i = loadedFiles; i < files.size(); i++) {
if (files[i].data) count++; if (files[i].isSave && files[i].data) count++;
} }
WriteFile(h, &count, 4, &unused, 0); WriteFile(h, &count, 4, &unused, 0);
for (DWORD i = 0; i < files.size(); i++) { for (DWORD i = loadedFiles; i < files.size(); i++) {
if (files[i].data) { if (files[i].isSave && files[i].data) {
WriteFile(h, &files[i].length, 128 + 8, &unused, 0); WriteFile(h, &files[i].length, 128 + 8, &unused, 0);
WriteFile(h, files[i].data, files[i].length, &unused, 0); WriteFile(h, files[i].data, files[i].length, &unused, 0);
} }
@@ -422,8 +427,9 @@ static void FileSystemLoad() {
for (DWORD i = 0; i < count; i++) { for (DWORD i = 0; i < count; i++) {
fsFile file; fsFile file;
ReadFile(h, &file.length, 128 + 8, &read, 0); ReadFile(h, &file.length, 128 + 8, &read, 0);
file.data = new char[file.length]; file.data = new BYTE[file.length];
ReadFile(h, file.data, file.length, &read, 0); ReadFile(h, file.data, file.length, &read, 0);
file.isSave = 1;
files.push_back(file); files.push_back(file);
} }
} }
@@ -471,21 +477,11 @@ void FileSystemInit() {
HookCalls(asm_xfilelength, {0x4C5DB4, 0x4C5E2D, 0x4C68BC}); HookCalls(asm_xfilelength, {0x4C5DB4, 0x4C5E2D, 0x4C68BC});
} }
DWORD _stdcall FScreate(const char* path, int size) { DWORD NewFile(fsFile &file, const char* path, int size) {
for (DWORD i = 0; i < files.size(); i++) {
if (!files[i].data) {
files[i].data = new char[size];
strcpy_s(files[i].name, path);
files[i].length = size;
files[i].wpos = 0;
return i;
}
}
fsFile file;
file.data = new char[size];
strcpy_s(file.name, path); strcpy_s(file.name, path);
file.length = size; file.length = size;
file.wpos = 0; file.wpos = 0;
file.isSave = 0;
files.push_back(file); files.push_back(file);
return files.size() - 1; return files.size() - 1;
} }
@@ -493,13 +489,27 @@ DWORD _stdcall FScreate(const char* path, int size) {
DWORD _stdcall FScreateFromData(const char* path, void* data, int size) { DWORD _stdcall FScreateFromData(const char* path, void* data, int size) {
loadedFiles++; loadedFiles++;
fsFile file; fsFile file;
file.data = new char[size]; file.data = new BYTE[size];
memcpy(file.data, data, size); memcpy(file.data, data, size);
strcpy_s(file.name, path);
file.length = size; return NewFile(file, path, size); // return file index in vector
file.wpos = 0; }
files.push_back(file);
return files.size() - 1; DWORD _stdcall FScreate(const char* path, int size) {
if (size > MAX_FILE_SIZE) return -1; // size limit 10Mb
for (DWORD i = 0; i < files.size(); i++) {
if (!files[i].data) {
files[i].data = new BYTE[size];
strcpy_s(files[i].name, path);
files[i].length = size;
files[i].wpos = 0;
return i;
}
}
fsFile file;
file.data = new BYTE[size];
return NewFile(file, path, size); // return file index in vector
} }
DWORD _stdcall FScopy(const char* path, const char* source) { DWORD _stdcall FScopy(const char* path, const char* source) {
@@ -524,7 +534,7 @@ DWORD _stdcall FScopy(const char* path, const char* source) {
mov fsize, eax; mov fsize, eax;
} }
char* fdata = new char[fsize]; BYTE* fdata = new BYTE[fsize];
__asm { __asm {
mov eax, file; mov eax, file;
call fo::funcoffs::xfclose_; call fo::funcoffs::xfclose_;
@@ -533,7 +543,7 @@ DWORD _stdcall FScopy(const char* path, const char* source) {
call fo::funcoffs::db_read_to_buf_; call fo::funcoffs::db_read_to_buf_;
} }
fsFile* fsfile = 0; fsFile* fsfile = nullptr;
for (DWORD i = 0; i < files.size(); i++) { for (DWORD i = 0; i < files.size(); i++) {
if (!files[i].data) { if (!files[i].data) {
result = i; result = i;
@@ -544,14 +554,15 @@ DWORD _stdcall FScopy(const char* path, const char* source) {
if (!fsfile) { if (!fsfile) {
files.push_back(fsFile()); files.push_back(fsFile());
result = files.size() - 1; result = files.size() - 1;
fsfile = &files[result]; fsfile = &files.back();
} }
fsfile->data = fdata; fsfile->data = fdata;
strcpy_s(fsfile->name, path); strcpy_s(fsfile->name, path);
fsfile->length = fsize; fsfile->length = fsize;
fsfile->wpos = 0; fsfile->wpos = 0;
fsfile->isSave = 0;
return result; return result; // return file index in vector
} }
DWORD _stdcall FSfind(const char* path) { DWORD _stdcall FSfind(const char* path) {
@@ -571,26 +582,21 @@ void _stdcall FSwrite_byte(DWORD id, int data) {
void _stdcall FSwrite_short(DWORD id, int data) { void _stdcall FSwrite_short(DWORD id, int data) {
if (id >= files.size() || !files[id].data) return; if (id >= files.size() || !files[id].data) return;
if (files[id].wpos + 2 > files[id].length) return; if (files[id].wpos + 2 > files[id].length) return;
char data2[2];
memcpy(data2, &data, 2); char* data2 = (char*)&data;
char c = data2[0]; data2++;
data2[0] = data2[1]; // write & reverse bytes
data2[1] = c; for (int i = 0; i < 2; i++) files[id].data[files[id].wpos++] = *(data2 - i);
for (int i = 0; i < 2; i++) files[id].data[files[id].wpos++] = data2[i];
} }
void _stdcall FSwrite_int(DWORD id, int data) { void _stdcall FSwrite_int(DWORD id, int data) {
if (id >= files.size() || !files[id].data) return; if (id >= files.size() || !files[id].data) return;
if (files[id].wpos + 4 > files[id].length) return; if (files[id].wpos + 4 > files[id].length) return;
char data2[4];
memcpy(data2, &data, 4); char* data2 = (char*)&data;
char c = data2[1]; data2 += 3;
data2[1] = data2[2]; // write & reverse bytes
data2[2] = c; for (int i = 0; i < 4; i++) files[id].data[files[id].wpos++] = *(data2 - i);
c = data2[0];
data2[0] = data2[3];
data2[3] = c;
for (int i = 0; i < 4; i++) files[id].data[files[id].wpos++] = data2[i];
} }
void _stdcall FSwrite_string(DWORD id, const char* data) { void _stdcall FSwrite_string(DWORD id, const char* data) {
@@ -616,25 +622,22 @@ int _stdcall FSread_byte(DWORD id) {
int _stdcall FSread_short(DWORD id) { int _stdcall FSread_short(DWORD id) {
if (id >= files.size() || !files[id].data) return 0; if (id >= files.size() || !files[id].data) return 0;
if (files[id].wpos + 2 > files[id].length) return 0; if (files[id].wpos + 2 > files[id].length) return 0;
char data[2]; char data[2];
data[1] = files[id].data[files[id].wpos++]; data[1] = files[id].data[files[id].wpos++];
data[0] = files[id].data[files[id].wpos++]; data[0] = files[id].data[files[id].wpos++];
short result;
memcpy(&result, data, 2); return static_cast<int>(*(short*)data);
return result;
} }
int _stdcall FSread_int(DWORD id) { int _stdcall FSread_int(DWORD id) {
if (id >= files.size() || !files[id].data) return 0; if (id >= files.size() || !files[id].data) return 0;
if (files[id].wpos + 4 > files[id].length) return 0; if (files[id].wpos + 4 > files[id].length) return 0;
char data[4]; char data[4];
data[3] = files[id].data[files[id].wpos++]; for (int i = 3; i >= 0; i--) data[i] = files[id].data[files[id].wpos++];
data[2] = files[id].data[files[id].wpos++];
data[1] = files[id].data[files[id].wpos++]; return *(int*)data;
data[0] = files[id].data[files[id].wpos++];
int result;
memcpy(&result, data, 4);
return result;
} }
void _stdcall FSdelete(DWORD id) { void _stdcall FSdelete(DWORD id) {
@@ -663,9 +666,13 @@ void _stdcall FSseek(DWORD id, DWORD pos) {
} }
void _stdcall FSresize(DWORD id, DWORD size) { void _stdcall FSresize(DWORD id, DWORD size) {
if (id >= files.size() || !files[id].data) return; if (id >= files.size() || !files[id].data || (size != -1 && size > MAX_FILE_SIZE)) return; // size limit 10Mb
char* buf = files[id].data; if (size == -1) {
files[id].data = new char[size]; files[id].isSave = 1;
return;
}
BYTE* buf = files[id].data;
files[id].data = new BYTE[size];
CopyMemory(files[id].data, buf, min(files[id].length, size)); CopyMemory(files[id].data, buf, min(files[id].length, size));
files[id].length = size; files[id].length = size;
files[id].wpos = 0; files[id].wpos = 0;
@@ -675,9 +682,8 @@ void _stdcall FSresize(DWORD id, DWORD size) {
void FileSystem::init() { void FileSystem::init() {
if (GetConfigInt("Misc", "UseFileSystemOverride", 0)) { if (GetConfigInt("Misc", "UseFileSystemOverride", 0)) {
FileSystemInit(); FileSystemInit();
LoadGameHook::OnGameReset() += FileSystemReset;
} }
LoadGameHook::OnGameReset() += FileSystemReset;
} }
} }