Initial rodecomp source snapshot
This commit is contained in:
commit
d456e8f64a
916 changed files with 156023 additions and 0 deletions
93
Source/File/CommonObject.cpp
Normal file
93
Source/File/CommonObject.cpp
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#include "File/CommonObject.h"
|
||||
#include "Resource/BitmapResource.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
|
||||
// OFFSET: 0x006D3700
|
||||
// FUNCTION: fn_06543
|
||||
CCommonObject::~CCommonObject() {
|
||||
this->Clear();
|
||||
}
|
||||
|
||||
// OFFSET: 0x005B7C90
|
||||
// FUNCTION: fn_03417
|
||||
void CCommonObject::Clear() {
|
||||
for (char* buffer : this->m_buffers) {
|
||||
std::free(buffer);
|
||||
}
|
||||
|
||||
this->m_buffers.clear();
|
||||
}
|
||||
|
||||
// OFFSET: 0x005B8810
|
||||
// FUNCTION: fn_03422
|
||||
bool CCommonObject::LoadTokens(std::vector<char*>& tokens, const char* name, int mode, ResourceBytes& file) {
|
||||
tokens.clear();
|
||||
|
||||
if (tokens.capacity() < 4096) {
|
||||
tokens.reserve(4096);
|
||||
}
|
||||
|
||||
// ResourceBytes supplies the original resolved, archive-aware read boundary.
|
||||
// No loose-file fallback is hidden in this table parser.
|
||||
if (!file.Open(name)) {
|
||||
file.Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto bytes = static_cast<unsigned>(file.Size());
|
||||
std::unique_ptr<char, decltype(&std::free)> buffer(
|
||||
static_cast<char*>(std::malloc(static_cast<std::size_t>(bytes) + 1)), &std::free
|
||||
);
|
||||
|
||||
if (!buffer) {
|
||||
file.Close();
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
std::memcpy(buffer.get(), file.Data(), bytes);
|
||||
buffer.get()[bytes] = '\0';
|
||||
file.Close();
|
||||
char* start = buffer.get();
|
||||
|
||||
for (unsigned index = 0; index < bytes; ++index) {
|
||||
char& value = buffer.get()[index];
|
||||
|
||||
switch (value) {
|
||||
case '\n':
|
||||
start = buffer.get() + index + 1;
|
||||
break;
|
||||
case '\r':
|
||||
value = '\0';
|
||||
|
||||
if (*start != '\0' && mode != 0 && std::strncmp(start, "//", 2) != 0) {
|
||||
tokens.push_back(start);
|
||||
}
|
||||
|
||||
start = buffer.get() + index + 1;
|
||||
break;
|
||||
case '#':
|
||||
if (std::strncmp(start, "//", 2) != 0) {
|
||||
value = '\0';
|
||||
tokens.push_back(start);
|
||||
|
||||
if (mode == 2) {
|
||||
tokens.push_back(nullptr);
|
||||
}
|
||||
|
||||
start = buffer.get() + index + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_buffers.push_back(buffer.get());
|
||||
buffer.release();
|
||||
return true;
|
||||
}
|
||||
27
Source/File/CommonObject.h
Normal file
27
Source/File/CommonObject.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef RAGNAROK_SOURCE_FILE_COMMONOBJECT_H
|
||||
#define RAGNAROK_SOURCE_FILE_COMMONOBJECT_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
class ResourceBytes;
|
||||
|
||||
// RTTI CCommonObject. Token pointers borrow the
|
||||
// retained file allocations until Clear/destruction, not the input file view.
|
||||
class CCommonObject {
|
||||
public:
|
||||
CCommonObject() = default;
|
||||
virtual ~CCommonObject();
|
||||
void Clear();
|
||||
bool LoadTokens(std::vector<char*>& tokens, const char* name, int mode, ResourceBytes& file);
|
||||
|
||||
private:
|
||||
/* 0004 */ std::vector<char*> m_buffers;
|
||||
CCommonObject(const CCommonObject&) = delete;
|
||||
CCommonObject& operator=(const CCommonObject&) = delete;
|
||||
};
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
static_assert(sizeof(CCommonObject) == 16);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
143
Source/File/File.cpp
Normal file
143
Source/File/File.cpp
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
#include "Client/ErrorDialog.h"
|
||||
#include "File/File.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
// ORIGINAL_SITE: 0x00E48460 in fn_24220 (fragment)
|
||||
CFile::CFile() : m_handle(INVALID_HANDLE_VALUE), m_data(nullptr), m_position(0), m_size(0) {
|
||||
}
|
||||
|
||||
// OFFSET: 0x005222F0
|
||||
// FUNCTION: fn_01126
|
||||
CFile::~CFile() {
|
||||
this->Close();
|
||||
}
|
||||
|
||||
// OFFSET: 0x0057C030
|
||||
// FUNCTION: fn_02597
|
||||
bool CFile::OpenWrite(const char* path, CRenderSystemBase* renderSystem) {
|
||||
this->m_path = path;
|
||||
this->m_handle = CreateFileA(
|
||||
path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr
|
||||
);
|
||||
if (this->m_handle == INVALID_HANDLE_VALUE) {
|
||||
ShowErrorDialog(renderSystem, this->m_path.c_str(), 0);
|
||||
return false;
|
||||
}
|
||||
LARGE_INTEGER size;
|
||||
GetFileSizeEx(this->m_handle, &size);
|
||||
this->m_size = size.LowPart;
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0057C340
|
||||
// FUNCTION: fn_02601
|
||||
bool CFile::Write(const void* data, std::uint32_t bytes) {
|
||||
DWORD written;
|
||||
return this->m_handle != INVALID_HANDLE_VALUE && WriteFile(this->m_handle, data, bytes, &written, nullptr);
|
||||
}
|
||||
|
||||
// OFFSET: 0x0057C260
|
||||
// FUNCTION: fn_02599
|
||||
bool CFile::Read(void* data, std::uint32_t bytes) {
|
||||
if (this->m_handle != INVALID_HANDLE_VALUE) {
|
||||
DWORD read;
|
||||
return ReadFile(this->m_handle, data, bytes, &read, nullptr) != FALSE;
|
||||
}
|
||||
|
||||
if (!this->m_data || this->m_position + bytes > this->m_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::memcpy(data, static_cast<const unsigned char*>(this->m_data) + this->m_position, bytes);
|
||||
this->m_position += bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0057C1E0
|
||||
// FUNCTION: fn_02598
|
||||
bool CFile::Peek(void* data, std::uint32_t bytes) {
|
||||
if (this->m_handle != INVALID_HANDLE_VALUE) {
|
||||
DWORD read;
|
||||
|
||||
if (!ReadFile(this->m_handle, data, bytes, &read, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LARGE_INTEGER distance;
|
||||
// The reference zero-extends the negated low DWORD, not sign-extension.
|
||||
distance.QuadPart = static_cast<std::uint32_t>(0u - bytes);
|
||||
SetFilePointerEx(this->m_handle, distance, nullptr, FILE_CURRENT);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this->m_data || this->m_position + bytes > this->m_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::memcpy(data, static_cast<const unsigned char*>(this->m_data) + this->m_position, bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0057C2D0
|
||||
// FUNCTION: fn_02600
|
||||
bool CFile::Seek(std::uint32_t distance, DWORD origin) {
|
||||
if (this->m_handle != INVALID_HANDLE_VALUE) {
|
||||
LARGE_INTEGER offset;
|
||||
offset.QuadPart = distance;
|
||||
SetFilePointerEx(this->m_handle, offset, nullptr, origin);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this->m_data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (origin) {
|
||||
case FILE_BEGIN:
|
||||
this->m_position = distance;
|
||||
break;
|
||||
case FILE_CURRENT:
|
||||
this->m_position += distance;
|
||||
break;
|
||||
case FILE_END:
|
||||
this->m_position = this->m_size + distance;
|
||||
break;
|
||||
}
|
||||
|
||||
if (this->m_position > this->m_size) {
|
||||
this->m_position = this->m_size;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0057B940
|
||||
// FUNCTION: fn_02592
|
||||
void CFile::Close() {
|
||||
if (this->m_handle == INVALID_HANDLE_VALUE) {
|
||||
if (this->m_data) {
|
||||
// Release helper.
|
||||
VirtualFree(this->m_data, 0, MEM_RELEASE);
|
||||
this->m_data = nullptr;
|
||||
}
|
||||
} else {
|
||||
CloseHandle(this->m_handle);
|
||||
this->m_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x0057BB20
|
||||
// FUNCTION: fn_02593
|
||||
void* CFile::ReadPtr(std::uint32_t bytes) {
|
||||
std::uint32_t offset = this->m_position;
|
||||
this->m_position = offset + bytes;
|
||||
return static_cast<char*>(this->m_data) + offset;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0057BB40
|
||||
// FUNCTION: fn_02594
|
||||
bool CFile::IsEOF() const {
|
||||
return this->m_position >= this->m_size;
|
||||
}
|
||||
60
Source/File/File.h
Normal file
60
Source/File/File.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef RAGNAROK_SOURCE_FILE_FILE_H
|
||||
#define RAGNAROK_SOURCE_FILE_FILE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
|
||||
class CRenderSystemBase;
|
||||
|
||||
class CFile {
|
||||
public:
|
||||
CFile();
|
||||
virtual ~CFile();
|
||||
// Recovered write branch only; not a replacement for original general Open,
|
||||
// whose archive read/extraction dependency remains unresolved.
|
||||
bool OpenWrite(const char* path, CRenderSystemBase* renderSystem);
|
||||
bool Open(const char* path) {
|
||||
this->m_path = path;
|
||||
this->m_handle = CreateFileA(
|
||||
path,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr
|
||||
);
|
||||
if (this->m_handle == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LARGE_INTEGER size;
|
||||
GetFileSizeEx(this->m_handle, &size);
|
||||
this->m_size = size.LowPart;
|
||||
return true;
|
||||
}
|
||||
std::uint32_t GetSize() const {
|
||||
return this->m_size;
|
||||
}
|
||||
bool Write(const void* data, std::uint32_t bytes);
|
||||
bool Read(void* data, std::uint32_t bytes);
|
||||
bool Peek(void* data, std::uint32_t bytes);
|
||||
bool Seek(std::uint32_t distance, DWORD origin);
|
||||
void* ReadPtr(std::uint32_t bytes);
|
||||
bool IsEOF() const;
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
/* 0004 */ HANDLE m_handle;
|
||||
/* 0008 */ void* m_data;
|
||||
/* 000C */ std::uint32_t m_position;
|
||||
/* 0010 */ std::uint32_t m_size;
|
||||
/* 0014 */ std::string m_path;
|
||||
};
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
static_assert(sizeof(CFile) == 44);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
24
Source/File/MapName.cpp
Normal file
24
Source/File/MapName.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include "File/MapName.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
#include <windows.h>
|
||||
|
||||
// OFFSET: 0x00CD4E40
|
||||
// FUNCTION: fn_21276
|
||||
const char* ScriptMapName(std::string name) {
|
||||
// STATIC: 0x017203E0
|
||||
// GLOBAL: gl_24517
|
||||
static std::map<std::intptr_t, std::array<char, 16>> buffers;
|
||||
auto& output = buffers[reinterpret_cast<std::intptr_t>(GetCurrentThread())];
|
||||
const std::size_t marker = name.rfind('@');
|
||||
|
||||
if (marker != std::string::npos && marker >= 4) {
|
||||
name.erase(marker - 4, 3);
|
||||
}
|
||||
|
||||
_snprintf_s(output.data(), output.size(), _TRUNCATE, "%s", name.c_str());
|
||||
return output.data();
|
||||
}
|
||||
13
Source/File/MapName.h
Normal file
13
Source/File/MapName.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef RAGNAROK_SOURCE_FILE_MAPNAME_H
|
||||
#define RAGNAROK_SOURCE_FILE_MAPNAME_H
|
||||
|
||||
#include <string>
|
||||
|
||||
// Removes three bytes starting four bytes before the final '@', if that '@'
|
||||
// has at least four preceding bytes, then formats at most 15 bytes plus NUL.
|
||||
// Returned storage belongs to the original GetCurrentThread pseudo-handle map.
|
||||
// The pseudo-handle is shared across threads: later calls overwrite the same
|
||||
// buffer. This is deliberately not thread-local storage and is not synchronized.
|
||||
const char* ScriptMapName(std::string name);
|
||||
|
||||
#endif
|
||||
55
Source/File/ResourcePath.cpp
Normal file
55
Source/File/ResourcePath.cpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#include "Archive/PakRegistry.h"
|
||||
#include "File/ResourcePath.h"
|
||||
|
||||
// OFFSET: 0x0057BC20
|
||||
// FUNCTION: fn_02596
|
||||
std::string MakeResourcePath(std::string filename) {
|
||||
std::string path = "data\\";
|
||||
path.append(filename);
|
||||
|
||||
std::size_t colon = path.find(':');
|
||||
if (colon != std::string::npos && colon >= 1) {
|
||||
path = path.substr(colon - 1);
|
||||
}
|
||||
|
||||
std::size_t duplicate;
|
||||
while ((duplicate = path.find("//")) != std::string::npos) {
|
||||
path.replace(duplicate, 2, "/", 1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
// OFFSET: 0x0057BB50
|
||||
// FUNCTION: fn_02595
|
||||
bool ResourceExists(const char* filename, int looseOnly) {
|
||||
std::string path = MakeResourcePath(std::string(filename));
|
||||
return g_pakRegistry.Exists(path.c_str(), static_cast<char>(looseOnly) != 0);
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AE9EE0
|
||||
// FUNCTION: fn_18113
|
||||
void* ReadLooseResource(const char* filename, std::uint32_t* size) {
|
||||
HANDLE file =
|
||||
CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (file == INVALID_HANDLE_VALUE) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LARGE_INTEGER fileSize;
|
||||
GetFileSizeEx(file, &fileSize);
|
||||
*size = fileSize.LowPart;
|
||||
|
||||
void* data = VirtualAlloc(nullptr, *size, MEM_COMMIT, PAGE_READWRITE);
|
||||
if (!data) {
|
||||
VirtualFree(nullptr, 0, MEM_RELEASE);
|
||||
CloseHandle(file);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DWORD read;
|
||||
ReadFile(file, data, *size, &read, nullptr);
|
||||
CloseHandle(file);
|
||||
|
||||
// The original's non-.ebm post-read hook is an established empty routine.
|
||||
return data;
|
||||
}
|
||||
17
Source/File/ResourcePath.h
Normal file
17
Source/File/ResourcePath.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef RAGNAROK_SOURCE_FILE_RESOURCEPATH_H
|
||||
#define RAGNAROK_SOURCE_FILE_RESOURCEPATH_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
// Reconstructed names for the original resource path and existence helpers.
|
||||
std::string MakeResourcePath(std::string filename);
|
||||
bool ResourceExists(const char* filename, int looseOnly);
|
||||
|
||||
// Full loose-file reader used after archive lookup. size must be non-null.
|
||||
// Publishes the low file-size DWORD after opening, even when allocation fails;
|
||||
// a successful allocation is returned regardless of ReadFile's status/count.
|
||||
// Caller owns the returned region and releases it with VirtualFree/MEM_RELEASE.
|
||||
void* ReadLooseResource(const char* filename, std::uint32_t* size);
|
||||
|
||||
#endif
|
||||
19
Source/File/ShortcutFilename.cpp
Normal file
19
Source/File/ShortcutFilename.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include "File/ShortcutFilename.h"
|
||||
|
||||
// OFFSET: 0x00DD9430
|
||||
// FUNCTION: fn_23335
|
||||
std::string ShortcutFilename(std::uint32_t identifier) {
|
||||
std::string result;
|
||||
constexpr char digits[] = "3867012495";
|
||||
for (std::uint32_t divisor = 1000000000; divisor; divisor /= 10) {
|
||||
if (!result.empty() && divisor == 100) {
|
||||
result.push_back('-');
|
||||
}
|
||||
unsigned digit = identifier / divisor;
|
||||
identifier %= divisor;
|
||||
if (digit || !result.empty()) {
|
||||
result.push_back(digits[digit]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
10
Source/File/ShortcutFilename.h
Normal file
10
Source/File/ShortcutFilename.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef RAGNAROK_SOURCE_FILE_SHORTCUTFILENAME_H
|
||||
#define RAGNAROK_SOURCE_FILE_SHORTCUTFILENAME_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
// Reconstructed semantic name for the original numeric filename transformation.
|
||||
std::string ShortcutFilename(std::uint32_t identifier);
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue