Initial rodecomp source snapshot

This commit is contained in:
ragnarok-clanker 2026-10-24 00:35:19 +00:00
commit d456e8f64a
916 changed files with 156023 additions and 0 deletions

View 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;
}

View 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
View 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
View 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
View 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
View 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

View 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;
}

View 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

View 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;
}

View 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