mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-16 03:23:15 +01:00
add scenario list loading
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
<ClInclude Include="..\src\osinterface.h" />
|
||||
<ClInclude Include="..\src\peep.h" />
|
||||
<ClInclude Include="..\src\rct2.h" />
|
||||
<ClInclude Include="..\src\scenario.h" />
|
||||
<ClInclude Include="..\src\sprite.h" />
|
||||
<ClInclude Include="..\src\sprites.h" />
|
||||
<ClInclude Include="..\src\strings.h" />
|
||||
@@ -42,6 +43,8 @@
|
||||
<ClCompile Include="..\src\osinterface.c" />
|
||||
<ClCompile Include="..\src\peep.c" />
|
||||
<ClCompile Include="..\src\rct2.c" />
|
||||
<ClCompile Include="..\src\scenario.c" />
|
||||
<ClCompile Include="..\src\strings.c" />
|
||||
<ClCompile Include="..\src\title.c" />
|
||||
<ClCompile Include="..\src\viewport.c" />
|
||||
<ClCompile Include="..\src\widget.c" />
|
||||
|
||||
@@ -69,6 +69,9 @@
|
||||
<ClInclude Include="..\src\sprites.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\scenario.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\game.c">
|
||||
@@ -122,6 +125,12 @@
|
||||
<ClCompile Include="..\src\window_title_scenarioselect.c">
|
||||
<Filter>Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\scenario.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\strings.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\openrct2.exe">
|
||||
|
||||
@@ -23,16 +23,16 @@
|
||||
|
||||
#pragma warning(disable : 4731)
|
||||
|
||||
#define RCT2_ADDRESS(address, type) ((type*)address)
|
||||
#define RCT2_GLOBAL(address, type) (*((type*)address))
|
||||
#define RCT2_CALLPROC(address) (((void(*)())address)())
|
||||
#define RCT2_CALLFUNC(address, returnType) (((returnType(*)())address)())
|
||||
#define RCT2_ADDRESS(address, type) ((type*)(address))
|
||||
#define RCT2_GLOBAL(address, type) (*((type*)(address)))
|
||||
#define RCT2_CALLPROC(address) (((void(*)())(address))())
|
||||
#define RCT2_CALLFUNC(address, returnType) ((((returnType)(*)())(address))())
|
||||
|
||||
#define RCT2_CALLFUNC_1(address, returnType, a1, v1) (((returnType(*)(a1))address)(v1))
|
||||
#define RCT2_CALLFUNC_2(address, returnType, a1, a2, v1, v2) (((returnType(*)(a1, a2))address)(v1, v2))
|
||||
#define RCT2_CALLFUNC_3(address, returnType, a1, a2, a3, v1, v2, v3) (((returnType(*)(a1, a2, a3))address)(v1, v2, v3))
|
||||
#define RCT2_CALLFUNC_4(address, returnType, a1, a2, a3, a4, v1, v2, v3, v4) (((returnType(*)(a1, a2, a3, a4))address)(v1, v2, v3, v4))
|
||||
#define RCT2_CALLFUNC_5(address, returnType, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5) (((returnType(*)(a1, a2, a3, a4, a5))address)(v1, v2, v3, v4, v5))
|
||||
#define RCT2_CALLFUNC_1(address, returnType, a1, v1) (((returnType(*)(a1))(address))(v1))
|
||||
#define RCT2_CALLFUNC_2(address, returnType, a1, a2, v1, v2) (((returnType(*)(a1, a2))(address))(v1, v2))
|
||||
#define RCT2_CALLFUNC_3(address, returnType, a1, a2, a3, v1, v2, v3) (((returnType(*)(a1, a2, a3))(address))(v1, v2, v3))
|
||||
#define RCT2_CALLFUNC_4(address, returnType, a1, a2, a3, a4, v1, v2, v3, v4) (((returnType(*)(a1, a2, a3, a4))(address))(v1, v2, v3, v4))
|
||||
#define RCT2_CALLFUNC_5(address, returnType, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5) (((returnType(*)(a1, a2, a3, a4, a5))(address))(v1, v2, v3, v4, v5))
|
||||
|
||||
#define RCT2_CALLPROC_1(address, a1, v1) RCT2_CALLFUNC_1(address, void, a1, v1)
|
||||
#define RCT2_CALLPROC_2(address, a1, a2, v1, v2) RCT2_CALLFUNC_2(address, void, a1, a2, v1, v2)
|
||||
@@ -40,7 +40,8 @@
|
||||
#define RCT2_CALLPROC_4(address, a1, a2, a3, a4, v1, v2, v3, v4) RCT2_CALLFUNC_4(address, void, a1, a2, a3, a4, v1, v2, v3, v4)
|
||||
#define RCT2_CALLPROC_5(address, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5) RCT2_CALLFUNC_4(address, void, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5)
|
||||
|
||||
#define RCT2_ADDRESS_CMDLINE 0x009E2D98
|
||||
#define RCT2_ADDRESS_SCENARIO_LIST 0x009A9FF4
|
||||
#define RCT2_ADDRESS_NUM_SCENARIOS 0x009AA008
|
||||
|
||||
#define RCT2_ADDRESS_APP_PATH 0x009AA214
|
||||
#define RCT2_ADDRESS_APP_PATH_SLASH 0x009AB4D9
|
||||
@@ -69,6 +70,8 @@
|
||||
#define RCT2_ADDRESS_PLACE_OBJECT_MODIFIER 0x009DEA70
|
||||
#define RCT2_ADDRESS_ON_TUTORIAL 0x009DEA71
|
||||
|
||||
#define RCT2_ADDRESS_CMDLINE 0x009E2D98
|
||||
|
||||
#define RCT2_ADDRESS_G1_ELEMENTS 0x009EBD28
|
||||
|
||||
#define RCT2_ADDRESS_SPRITE_LIST 0x010E63BC
|
||||
@@ -80,6 +83,9 @@
|
||||
|
||||
#define RCT2_ADDRESS_NEWS_ITEM_LIST 0x013CA754
|
||||
|
||||
#define RCT2_ADDRESS_SCENARIO_NAME 0x0141F5B8
|
||||
#define RCT2_ADDRESS_SCENARIO_DETAILS 0x0141F5F8
|
||||
|
||||
#define RCT2_ADDRESS_WINDOW_LIST 0x01420078
|
||||
#define RCT2_ADDRESS_NEW_WINDOW_PTR 0x014234B8
|
||||
#define RCT2_ADDRESS_VIEWPORT_LIST 0x014234BC
|
||||
@@ -115,10 +121,13 @@ static void RCT2_CALLPROC_X(int address, int _eax, int _ebx, int _ecx, int _edx,
|
||||
static void RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp)
|
||||
{
|
||||
__asm {
|
||||
// Store C's base pointer
|
||||
push ebp
|
||||
|
||||
// Store address to call
|
||||
push address
|
||||
|
||||
// Set register to variable address, then set register to variable value
|
||||
// Set all registers to the input values
|
||||
mov eax, [_eax]
|
||||
mov eax, [eax]
|
||||
mov ebx, [_ebx]
|
||||
@@ -134,15 +143,28 @@ static void RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_
|
||||
mov ebp, [_ebp]
|
||||
mov ebp, [ebp]
|
||||
|
||||
// Call func address
|
||||
call[esp]
|
||||
// Call function
|
||||
call [esp]
|
||||
add esp, 4
|
||||
pop ebp
|
||||
|
||||
// mov[_ebp], ebp
|
||||
// Store output eax
|
||||
push eax
|
||||
|
||||
// Put original C base pointer into eax
|
||||
mov eax, [esp+4]
|
||||
|
||||
// Store output ebp
|
||||
push ebp
|
||||
|
||||
// Set ebp to the original C base pointer
|
||||
mov ebp, eax
|
||||
|
||||
// Put output ebp into ebp parameter
|
||||
mov eax, [esp]
|
||||
mov [_ebp], eax
|
||||
add esp, 4
|
||||
|
||||
// Get resulting ebx, ecx, edx, esi, edi registers
|
||||
push eax
|
||||
mov eax, [_edi]
|
||||
mov [eax], edi
|
||||
mov eax, [_esi]
|
||||
@@ -158,6 +180,8 @@ static void RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_
|
||||
// Get resulting eax register
|
||||
mov ebx, [_eax]
|
||||
mov [ebx], eax
|
||||
|
||||
add esp, 4
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ void news_item_update_current()
|
||||
short ax, bx, remove_time;
|
||||
rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
|
||||
|
||||
// get_system_time();
|
||||
RCT2_CALLPROC_EBPSAFE(0x00407671); // get_system_time()
|
||||
|
||||
ax = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAY, sint16);
|
||||
bx = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MONTH, sint16);
|
||||
|
||||
29
src/rct2.c
29
src/rct2.c
@@ -30,6 +30,7 @@
|
||||
#include "intro.h"
|
||||
#include "osinterface.h"
|
||||
#include "rct2.h"
|
||||
#include "scenario.h"
|
||||
#include "title.h"
|
||||
|
||||
void rct2_init_directories();
|
||||
@@ -98,7 +99,7 @@ void rct2_init()
|
||||
RCT2_CALLPROC_EBPSAFE(0x006752D5); // config_load()
|
||||
// RCT2_CALLPROC_EBPSAFE(0x00674B81); // pointless expansion pack crap
|
||||
RCT2_CALLPROC_EBPSAFE(0x006A8B40); // object_load_list()
|
||||
RCT2_CALLPROC_EBPSAFE(0x006775A8); // scenario_load_list()
|
||||
scenario_load_list();
|
||||
RCT2_CALLPROC_X(0x006CED50, 0, 0, 0, 253, 0, 0, 0); // track_load_list(253)
|
||||
gfx_load_g1();
|
||||
RCT2_CALLPROC_EBPSAFE(0x006C19AC);
|
||||
@@ -167,9 +168,11 @@ void rct2_startup_checks()
|
||||
|
||||
void rct2_update()
|
||||
{
|
||||
// Set 0x009DE564 to the value of esp
|
||||
// RCT2 sets the stack pointer to the value of this address when ending the current game tick from anywhere
|
||||
__asm {
|
||||
mov eax, 009DE564h
|
||||
mov[eax], esp
|
||||
mov [eax], esp
|
||||
}
|
||||
|
||||
if (!setjmp(_end_update_jump))
|
||||
@@ -221,10 +224,30 @@ char *get_file_path(int pathId)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* RCT2 and this DLL can not free each other's allocated memory blocks. Use this to allocate memory if RCT2 is still able to
|
||||
* free it.
|
||||
* rct2: 0x004068B2
|
||||
*/
|
||||
void *rct2_malloc(size_t numBytes)
|
||||
{
|
||||
return RCT2_CALLFUNC_1(0x004068B2, void*, size_t, numBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* RCT2 and this DLL can not free each other's allocated memory blocks. Use this to reallocate memory if RCT2 is still able to
|
||||
* free it.
|
||||
* rct2: 0x004068BD
|
||||
*/
|
||||
void *rct2_realloc(void *block, size_t numBytes)
|
||||
{
|
||||
return RCT2_CALLFUNC_2(0x004068BD, void*, void*, size_t, block, numBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* RCT2 and this DLL can not free each other's allocated memory blocks. Use this to free memory that was allocated by RCT2.
|
||||
* rct2: 0x004068DE
|
||||
*/
|
||||
void rct2_free(void *block)
|
||||
{
|
||||
return RCT2_CALLPROC_1(0x004068DE, void*, block);
|
||||
}
|
||||
@@ -53,5 +53,7 @@ enum {
|
||||
|
||||
char *get_file_path(int pathId);
|
||||
void *rct2_malloc(size_t numBytes);
|
||||
void *rct2_realloc(void *block, size_t numBytes);
|
||||
void rct2_free(void *block);
|
||||
|
||||
#endif
|
||||
287
src/scenario.c
Normal file
287
src/scenario.c
Normal file
@@ -0,0 +1,287 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <windows.h>
|
||||
#include "addresses.h"
|
||||
#include "rct2.h"
|
||||
#include "scenario.h"
|
||||
#include "strings.h"
|
||||
|
||||
#define UNINITIALISED_SCENARIO_LIST ((rct_scenario_basic*)-1)
|
||||
|
||||
#define RCT2_SCENARIO_LIST RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_LIST, rct_scenario_basic*)
|
||||
#define RCT2_NUM_SCENARIOS RCT2_GLOBAL(RCT2_ADDRESS_NUM_SCENARIOS, sint32)
|
||||
int _scenarioListSize;
|
||||
|
||||
static void scenario_list_sort();
|
||||
static int scenario_list_sort_compare(const void* a, const void* b);
|
||||
static void scenario_scores_load();
|
||||
static void scenario_scores_save();
|
||||
static int scenario_load_basic(char *path);
|
||||
|
||||
static void subsitute_path(char *dest, char *path, char *filename)
|
||||
{
|
||||
while (*path != '*') {
|
||||
*dest++ = *path++;
|
||||
}
|
||||
strcpy(dest, filename);
|
||||
}
|
||||
|
||||
static rct_scenario_basic *get_scenario_by_filename(char *filename)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < RCT2_NUM_SCENARIOS; i++)
|
||||
if (strcmp(RCT2_SCENARIO_LIST[i].path, filename) == 0)
|
||||
return &(RCT2_SCENARIO_LIST[i]);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006775A8
|
||||
*/
|
||||
void scenario_load_list()
|
||||
{
|
||||
HANDLE hFindFile;
|
||||
WIN32_FIND_DATAA findFileData;
|
||||
int i;
|
||||
char *src, *dst;
|
||||
|
||||
// Load scores
|
||||
scenario_scores_load();
|
||||
|
||||
// Unset flag 1 for each scenario
|
||||
for (i = 0; i < RCT2_NUM_SCENARIOS; i++)
|
||||
RCT2_SCENARIO_LIST[i].var_0268 &= ~0x01;
|
||||
|
||||
// Enumerate through each scenario in the directory
|
||||
hFindFile = FindFirstFile(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), &findFileData);
|
||||
if (hFindFile != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
// Check if scenario already exists in list, likely if in scores
|
||||
rct_scenario_basic *scenario = get_scenario_by_filename(findFileData.cFileName);
|
||||
if (scenario != NULL) {
|
||||
// Set 0141EF68 to the scenario path
|
||||
subsitute_path(
|
||||
RCT2_ADDRESS(0x0141EF68, char),
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char),
|
||||
findFileData.cFileName
|
||||
);
|
||||
|
||||
// Load the basic scenario information
|
||||
if (!scenario_load_basic(RCT2_ADDRESS(0x0141EF68, char)))
|
||||
continue;
|
||||
|
||||
//
|
||||
if (RCT2_GLOBAL(0x0141F570, sint8) != -1)
|
||||
continue;
|
||||
|
||||
// Update the scenario information
|
||||
scenario->var_0268 |= 0x01;
|
||||
scenario->category = RCT2_GLOBAL(0x0141F571, uint8);
|
||||
scenario->var_0120 = RCT2_GLOBAL(0x0141F572, sint8);
|
||||
scenario->var_0121 = RCT2_GLOBAL(0x0141F573, sint8);
|
||||
scenario->var_0122 = RCT2_GLOBAL(0x0141F574, sint32);
|
||||
scenario->var_0126 = RCT2_GLOBAL(0x0141F578, sint16);
|
||||
strcpy(scenario->name, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_NAME, char));
|
||||
strcpy(scenario->details, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_DETAILS, char));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the scenario list buffer has room for another scenario
|
||||
if ((RCT2_NUM_SCENARIOS + 1) * sizeof(rct_scenario_basic) > _scenarioListSize) {
|
||||
// Allocate more room
|
||||
_scenarioListSize += 16 * sizeof(rct_scenario_basic);
|
||||
RCT2_SCENARIO_LIST = (rct_scenario_basic*)rct2_realloc(RCT2_SCENARIO_LIST, _scenarioListSize);
|
||||
}
|
||||
|
||||
// Set 0141EF68 to the scenario path
|
||||
subsitute_path(
|
||||
RCT2_ADDRESS(0x0141EF68, char),
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char),
|
||||
findFileData.cFileName
|
||||
);
|
||||
|
||||
// Load the scenario information
|
||||
if (!scenario_load_basic(RCT2_ADDRESS(0x0141EF68, char)))
|
||||
continue;
|
||||
|
||||
//
|
||||
if (RCT2_GLOBAL(0x0141F570, sint8) != -1)
|
||||
continue;
|
||||
|
||||
// Increment the number of scenarios
|
||||
i = RCT2_NUM_SCENARIOS;
|
||||
RCT2_NUM_SCENARIOS++;
|
||||
|
||||
// Add this new scenario to the list
|
||||
strcpy(RCT2_SCENARIO_LIST[i].path, findFileData.cFileName);
|
||||
RCT2_SCENARIO_LIST[i].var_0268 = 0x01;
|
||||
if (RCT2_GLOBAL(0x009AA00C, uint8) & 1)
|
||||
RCT2_SCENARIO_LIST[i].var_0268 |= 0x04;
|
||||
RCT2_SCENARIO_LIST[i].category = RCT2_GLOBAL(0x0141F571, uint8);
|
||||
RCT2_SCENARIO_LIST[i].var_0120 = RCT2_GLOBAL(0x0141F572, sint8);
|
||||
RCT2_SCENARIO_LIST[i].var_0121 = RCT2_GLOBAL(0x0141F573, sint8);
|
||||
RCT2_SCENARIO_LIST[i].var_0122 = RCT2_GLOBAL(0x0141F574, sint32);
|
||||
RCT2_SCENARIO_LIST[i].var_0126 = RCT2_GLOBAL(0x0141F578, sint16);
|
||||
strcpy(RCT2_SCENARIO_LIST[i].name, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_NAME, char));
|
||||
strcpy(RCT2_SCENARIO_LIST[i].details, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_DETAILS, char));
|
||||
} while (FindNextFile(hFindFile, &findFileData));
|
||||
FindClose(hFindFile);
|
||||
}
|
||||
|
||||
scenario_list_sort();
|
||||
|
||||
// Save the scores
|
||||
scenario_scores_save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the list of scenarios. This used to be an insertion sort which took
|
||||
* place as each scenario loaded. It has now been changed to a quicksort which
|
||||
* takes place after all the scenarios have been loaded in.
|
||||
* rct2: 0x00677C3B
|
||||
*/
|
||||
static void scenario_list_sort()
|
||||
{
|
||||
qsort(
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_LIST, rct_scenario_basic*),
|
||||
RCT2_NUM_SCENARIOS,
|
||||
sizeof(rct_scenario_basic),
|
||||
scenario_list_sort_compare
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic scenario information compare function for sorting.
|
||||
* rct2: 0x00677C08
|
||||
*/
|
||||
static int scenario_list_sort_compare(const void* a, const void* b)
|
||||
{
|
||||
return strcmp(((rct_scenario_basic*)a)->name, ((rct_scenario_basic*)b)->name);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006775A8
|
||||
*/
|
||||
static void scenario_scores_load()
|
||||
{
|
||||
HANDLE hFile;
|
||||
DWORD bytes_read;
|
||||
|
||||
// Free scenario list if already allocated
|
||||
if (RCT2_SCENARIO_LIST != UNINITIALISED_SCENARIO_LIST) {
|
||||
rct2_free(RCT2_SCENARIO_LIST);
|
||||
RCT2_SCENARIO_LIST = UNINITIALISED_SCENARIO_LIST;
|
||||
}
|
||||
|
||||
// Try and load the scores
|
||||
hFile = CreateFile(get_file_path(32), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
ReadFile(hFile, (void*)0x009A9FFC, 16, &bytes_read, NULL);
|
||||
if (bytes_read == 16) {
|
||||
_scenarioListSize = RCT2_NUM_SCENARIOS * sizeof(rct_scenario_basic);
|
||||
RCT2_SCENARIO_LIST = (rct_scenario_basic*)rct2_malloc(_scenarioListSize);
|
||||
ReadFile(hFile, RCT2_SCENARIO_LIST, _scenarioListSize, &bytes_read, NULL);
|
||||
CloseHandle(hFile);
|
||||
if (bytes_read == _scenarioListSize)
|
||||
return;
|
||||
} else {
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Unable to load scores, allocate some space for a reload
|
||||
RCT2_NUM_SCENARIOS = 0;
|
||||
_scenarioListSize = 0x4000;
|
||||
RCT2_SCENARIO_LIST = (rct_scenario_basic*)rct2_malloc(_scenarioListSize);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00677B50
|
||||
*/
|
||||
static void scenario_scores_save()
|
||||
{
|
||||
HANDLE hFile;
|
||||
DWORD bytes_written;
|
||||
|
||||
hFile = CreateFile(get_file_path(32), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
WriteFile(hFile, (void*)0x009A9FFC, 16, &bytes_written, NULL);
|
||||
if (RCT2_NUM_SCENARIOS > 0)
|
||||
WriteFile(hFile, RCT2_SCENARIO_LIST, RCT2_NUM_SCENARIOS * sizeof(rct_scenario_basic), &bytes_written, NULL);
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads only the basic information from a scenario.
|
||||
* rct2: 0x006761D6
|
||||
*/
|
||||
static int scenario_load_basic(char *path)
|
||||
{
|
||||
HANDLE hFile;
|
||||
int _eax;
|
||||
|
||||
hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
RCT2_GLOBAL(0x009E382C, HANDLE*) = hFile;
|
||||
RCT2_CALLPROC_X(0x0067685F, 0, 0, 0, 0, 0x009E34E4, 0, 0);
|
||||
if (RCT2_GLOBAL(0x009E34E4, uint8) == 1) {
|
||||
RCT2_CALLPROC_X(0x0067685F, 0, 0, 0, 0, 0x0141F570, 0, 0);
|
||||
CloseHandle(hFile);
|
||||
RCT2_GLOBAL(0x009AA00C, uint8) = 0;
|
||||
if (RCT2_GLOBAL(0x0141F6F8, uint8) != 255) {
|
||||
__asm {
|
||||
push ebp
|
||||
mov ebp, 0141F6F8h
|
||||
mov eax, 006A9428h
|
||||
call eax
|
||||
pop ebp
|
||||
mov _eax, eax
|
||||
jb loc_67628F
|
||||
}
|
||||
|
||||
int ebp = RCT2_GLOBAL(0x009ADAF8, uint32);
|
||||
format_string(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_NAME, char), RCT2_GLOBAL(ebp, sint16), NULL);
|
||||
format_string(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_DETAILS, char), RCT2_GLOBAL(ebp + 4, sint16), NULL);
|
||||
RCT2_GLOBAL(0x009AA00C, uint8) = RCT2_GLOBAL(ebp + 6, uint8);
|
||||
RCT2_CALLPROC(0x006A982D);
|
||||
__asm mov _eax, eax
|
||||
loc_67628F :
|
||||
return _eax;
|
||||
}
|
||||
} else {
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
}
|
||||
|
||||
RCT2_GLOBAL(0x009AC31B, sint8) = -1;
|
||||
RCT2_GLOBAL(0x009AC31C, sint16) = 3011;
|
||||
return 0;
|
||||
}
|
||||
47
src/scenario.h
Normal file
47
src/scenario.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _SCENARIO_H_
|
||||
#define _SCENARIO_H_
|
||||
|
||||
#include "rct2.h"
|
||||
|
||||
/**
|
||||
* Scenario basic structure, mainly for scenario select
|
||||
* size: 0x02B0
|
||||
*/
|
||||
typedef struct {
|
||||
char path[256]; // 0x0000
|
||||
uint8 category; // 0x0100
|
||||
uint8 pad_0101[0x1F];
|
||||
sint8 var_0120;
|
||||
sint8 var_0121;
|
||||
sint32 var_0122;
|
||||
sint16 var_0126;
|
||||
char name[64]; // 0x0128
|
||||
char details[256]; // 0x0168
|
||||
sint32 var_0268;
|
||||
uint32 pad_026C;
|
||||
sint8 var_0270[64];
|
||||
} rct_scenario_basic;
|
||||
|
||||
void scenario_load_list();
|
||||
|
||||
#endif
|
||||
34
src/strings.c
Normal file
34
src/strings.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "addresses.h"
|
||||
#include "strings.h"
|
||||
|
||||
/**
|
||||
* Writes a formatted string to a buffer.
|
||||
* rct2: 0x006C2555
|
||||
* dest (edi)
|
||||
* format (ax)
|
||||
* args (ecx)
|
||||
*/
|
||||
void format_string(char *dest, rct_string_id format, void *args)
|
||||
{
|
||||
RCT2_CALLPROC_X(0x006C2555, format, 0, args, 0, 0, dest, 0);
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
typedef unsigned short rct_string_id;
|
||||
|
||||
void format_string(char* dest, rct_string_id format, void* args);
|
||||
void format_string(char *dest, rct_string_id format, void *args);
|
||||
void generate_string_file();
|
||||
|
||||
enum {
|
||||
|
||||
Reference in New Issue
Block a user