mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-18 20:43:04 +01:00
Cleanup allocated segments on disposal
This commit is contained in:
@@ -58,6 +58,12 @@ bool gOpenRCT2Headless = false;
|
||||
|
||||
bool gOpenRCT2ShowChangelog;
|
||||
|
||||
#if defined(__linux__)
|
||||
void *gDataSegment;
|
||||
void *gTextSegment;
|
||||
int gExeFd;
|
||||
#endif // defined(__linux__)
|
||||
|
||||
/** If set, will end the OpenRCT2 game loop. Intentially private to this module so that the flag can not be set back to 0. */
|
||||
int _finished;
|
||||
|
||||
@@ -66,6 +72,7 @@ static struct { sint16 x, y, z; } _spritelocations1[MAX_SPRITES], _spritelocatio
|
||||
|
||||
static void openrct2_loop();
|
||||
static bool openrct2_setup_rct2_segment();
|
||||
static bool openrct2_release_rct2_segment();
|
||||
static void openrct2_setup_rct2_hooks();
|
||||
|
||||
static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 *newDirectory, const utf8 *extension)
|
||||
@@ -308,6 +315,7 @@ void openrct2_dispose()
|
||||
network_close();
|
||||
http_dispose();
|
||||
language_close_all();
|
||||
openrct2_release_rct2_segment();
|
||||
platform_free();
|
||||
}
|
||||
|
||||
@@ -465,8 +473,8 @@ static bool openrct2_setup_rct2_segment()
|
||||
#define DATA_OFFSET 0x004A4000
|
||||
|
||||
const char *exepath = "openrct2.exe";
|
||||
int fd = open(exepath, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
gExeFd = open(exepath, O_RDONLY);
|
||||
if (gExeFd < 0) {
|
||||
log_fatal("failed to open %s, errno = %d", exepath, errno);
|
||||
exit(1);
|
||||
}
|
||||
@@ -503,23 +511,22 @@ static bool openrct2_setup_rct2_segment()
|
||||
|
||||
int len = 0x01429000 - 0x8a4000; // 0xB85000, 12079104 bytes or around 11.5MB
|
||||
// section: rw data
|
||||
void *base = mmap((void *)0x8a4000, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, 0, 0);
|
||||
log_warning("base = %x, 0x01423b40 >= base == %i, 0x01423b40 < base + len == %i", base, (void *)0x01423b40 >= base, (void *)0x01423b40 < base + len);
|
||||
if (base == MAP_FAILED) {
|
||||
log_warning("errno = %i", errno);
|
||||
gDataSegment = mmap((void *)0x8a4000, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, 0, 0);
|
||||
if (gDataSegment != (void *)0x8a4000) {
|
||||
log_fatal("mmap failed to get required offset for data segment! got %p, expected %p, errno = %d", gDataSegment, (void *)(0x8a4000), errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
len = 0x004A3000;
|
||||
// section: text
|
||||
void *base2 = mmap((void *)(0x401000), len, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_FIXED | MAP_PRIVATE, fd, 0x1000);
|
||||
if (base2 != (void *)(0x401000))
|
||||
gTextSegment = mmap((void *)(0x401000), len, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_FIXED | MAP_PRIVATE, gExeFd, 0x1000);
|
||||
if (gTextSegment != (void *)(0x401000))
|
||||
{
|
||||
log_fatal("mmap failed to get required offset! got %p, expected %p, errno = %d", base2, (void *)(0x401000), errno);
|
||||
log_fatal("mmap failed to get required offset for text segment! got %p, expected %p, errno = %d", gTextSegment, (void *)(0x401000), errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, gExeFd, 0);
|
||||
int err = errno;
|
||||
log_warning("mmapped file to %p", fbase);
|
||||
if (fbase == MAP_FAILED)
|
||||
@@ -529,7 +536,13 @@ static bool openrct2_setup_rct2_segment()
|
||||
}
|
||||
// .rdata and real part of .data
|
||||
// 0x9e2000 - 0x8a4000 = 0x13e000
|
||||
memcpy(base, fbase + DATA_OFFSET, 0x13e000);
|
||||
memcpy(gDataSegment, fbase + DATA_OFFSET, 0x13e000);
|
||||
err = munmap(fbase, file_size);
|
||||
if (err != 0)
|
||||
{
|
||||
err = errno;
|
||||
log_error("Failed to unmap file! errno = %d", err);
|
||||
}
|
||||
#endif // __linux__
|
||||
|
||||
// Check that the expected data is at various addresses.
|
||||
@@ -546,6 +559,41 @@ static bool openrct2_setup_rct2_segment()
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases segments created with @ref openrct2_setup_rct2_segment, if any.
|
||||
*/
|
||||
static bool openrct2_release_rct2_segment()
|
||||
{
|
||||
bool result = true;
|
||||
#if defined(__linux__)
|
||||
int len = 0x01429000 - 0x8a4000; // 0xB85000, 12079104 bytes or around 11.5MB
|
||||
int err;
|
||||
err = munmap(gDataSegment, len);
|
||||
if (err != 0)
|
||||
{
|
||||
err = errno;
|
||||
log_error("Failed to unmap data segment! errno = %d", err);
|
||||
result = false;
|
||||
}
|
||||
len = 0x004A3000;
|
||||
err = munmap(gTextSegment, len);
|
||||
if (err != 0)
|
||||
{
|
||||
err = errno;
|
||||
log_error("Failed to unmap text segment! errno = %d", err);
|
||||
result = false;
|
||||
}
|
||||
err = close(gExeFd);
|
||||
if (err != 0)
|
||||
{
|
||||
err = errno;
|
||||
log_error("Failed to close file! errno = %d", err);
|
||||
result = false;
|
||||
}
|
||||
#endif // defined(__linux__)
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup hooks to allow RCT2 to call OpenRCT2 functions instead.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user