mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-23 15:52:55 +01:00
add scenario loading and title script
This commit is contained in:
@@ -98,6 +98,8 @@
|
||||
|
||||
#define RCT2_ADDRESS_CURRENT_LOAN 0x013573E0
|
||||
#define RCT2_ADDRESS_GUESTS_IN_PARK 0x01357844
|
||||
#define RCT2_ADDRESS_CURRENT_PARK_RATING 0x01357CB0
|
||||
#define RCT2_ADDRESS_PARK_RATING_HISTORY 0x01357CB2
|
||||
#define RCT2_ADDRESS_CURRENT_PARK_VALUE 0x0135853C
|
||||
#define RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED 0x013587F8
|
||||
|
||||
|
||||
37
src/map.c
37
src/map.c
@@ -61,7 +61,7 @@ void map_init()
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, sint16) = 150;
|
||||
RCT2_GLOBAL(0x01358836, sint16) = 4767;
|
||||
RCT2_GLOBAL(0x01359208, sint16) = 7;
|
||||
tiles_init();
|
||||
map_update_tile_pointers();
|
||||
RCT2_CALLPROC_EBPSAFE(0x0068ADBC);
|
||||
|
||||
climate_reset(CLIMATE_WARM);
|
||||
@@ -71,7 +71,7 @@ void map_init()
|
||||
*
|
||||
* rct2: 0x0068AFFD
|
||||
*/
|
||||
static void tiles_init()
|
||||
void map_update_tile_pointers()
|
||||
{
|
||||
int i, x, y, lastTile;
|
||||
|
||||
@@ -93,3 +93,36 @@ static void tiles_init()
|
||||
// Possible next free map element
|
||||
RCT2_GLOBAL(0x0140E9A4, rct_map_element*) = mapElement;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00662783
|
||||
* UNFINISHED
|
||||
*/
|
||||
int sub_662783(int x, int y)
|
||||
{
|
||||
int i;
|
||||
rct_map_element *mapElement;
|
||||
|
||||
if (x >= 8192 || y >= 8192)
|
||||
return 16;
|
||||
|
||||
x &= 0xFFFFFFE0;
|
||||
y &= 0xFFFFFFE0;
|
||||
|
||||
i = ((y * 256) + x) / 8;
|
||||
|
||||
mapElement = TILE_MAP_ELEMENT_POINTER(i);
|
||||
while (mapElement->type & MAP_ELEMENT_TYPE_MASK) {
|
||||
mapElement++;
|
||||
}
|
||||
|
||||
uint32 result =
|
||||
((mapElement->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK) << 20) |
|
||||
(mapElement->base_height << 3);
|
||||
|
||||
uint32 ebx = (mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK) & ~0x16;
|
||||
// slope logic
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -157,11 +157,15 @@ enum {
|
||||
#define MAP_ELEMENT_TYPE_MASK 0x3C
|
||||
#define MAP_ELEMENT_DIRECTION_MASK 0x03
|
||||
|
||||
#define MAP_ELEMENT_SLOPE_MASK 0x1F
|
||||
#define MAP_ELEMENT_WATER_HEIGHT_MASK 0x1F
|
||||
|
||||
#define MAX_MAP_ELEMENTS 196608
|
||||
#define MAX_TILE_MAP_ELEMENT_POINTERS (256 * 256)
|
||||
|
||||
#define TILE_UNDEFINED_MAP_ELEMENT -1
|
||||
|
||||
void map_init();
|
||||
void map_update_tile_pointers();
|
||||
|
||||
#endif
|
||||
113
src/scenario.c
113
src/scenario.c
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <windows.h>
|
||||
#include "addresses.h"
|
||||
#include "map.h"
|
||||
#include "rct2.h"
|
||||
#include "sawyercoding.h"
|
||||
#include "scenario.h"
|
||||
@@ -249,8 +250,6 @@ static void scenario_scores_save()
|
||||
}
|
||||
}
|
||||
|
||||
void sub_67685F(HFILE hFile, uint32 address);
|
||||
|
||||
/**
|
||||
* Loads only the basic information from a scenario.
|
||||
* rct2: 0x006761D6
|
||||
@@ -262,8 +261,9 @@ static int scenario_load_basic(char *path)
|
||||
rct_s6_header *s6Header = 0x009E34E4;
|
||||
rct_s6_info *s6Info = 0x0141F570;
|
||||
|
||||
hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
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;
|
||||
|
||||
@@ -294,9 +294,8 @@ static int scenario_load_basic(char *path)
|
||||
loc_67628F :
|
||||
return _eax;
|
||||
}
|
||||
} else {
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
RCT2_GLOBAL(0x009AC31B, sint8) = -1;
|
||||
@@ -304,12 +303,112 @@ static int scenario_load_basic(char *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AA2B7
|
||||
*/
|
||||
static int object_load_packed()
|
||||
{
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
RCT2_CALLFUNC_X(0x006AA2B7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
return eax;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00676053
|
||||
* scenario (ebx)
|
||||
*/
|
||||
void scenario_load(char *path)
|
||||
{
|
||||
HANDLE hFile;
|
||||
int i, j;
|
||||
rct_s6_header *s6Header = 0x009E34E4;
|
||||
rct_s6_info *s6Info = 0x0141F570;
|
||||
|
||||
strcpy(RCT2_ADDRESS(0x0141EF68, char), path);
|
||||
RCT2_CALLPROC_EBPSAFE(0x00676053);
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
// Read first chunk
|
||||
sawyercoding_read_chunk(hFile, s6Header);
|
||||
if (s6Header->type == S6_TYPE_SCENARIO) {
|
||||
// Read second chunk
|
||||
sawyercoding_read_chunk(hFile, s6Info);
|
||||
|
||||
// Read packed objects
|
||||
if (s6Header->num_packed_objects > 0) {
|
||||
j = 0;
|
||||
for (i = 0; i < s6Header->num_packed_objects; i++)
|
||||
j += object_load_packed();
|
||||
if (j > 0)
|
||||
RCT2_CALLPROC_EBPSAFE(0x006A8B40); // object_load_list
|
||||
}
|
||||
|
||||
// Read available items (721 * 16)
|
||||
RCT2_CALLPROC_EBPSAFE(0x006AA0C6);
|
||||
|
||||
// Read flags (16 bytes)
|
||||
sawyercoding_read_chunk(hFile, RCT2_ADDRESS_CURRENT_MONTH_YEAR);
|
||||
|
||||
// Read map elements
|
||||
memset(RCT2_ADDRESS_MAP_ELEMENTS, 0, MAX_MAP_ELEMENTS * sizeof(rct_map_element));
|
||||
sawyercoding_read_chunk(hFile, RCT2_ADDRESS_MAP_ELEMENTS);
|
||||
|
||||
// Read game data, including sprites
|
||||
sawyercoding_read_chunk(hFile, 0x010E63B8);
|
||||
|
||||
// Read number of guests in park and something else
|
||||
sawyercoding_read_chunk(hFile, RCT2_ADDRESS_GUESTS_IN_PARK);
|
||||
|
||||
// Read ?
|
||||
sawyercoding_read_chunk(hFile, 0x01357BC8);
|
||||
|
||||
// Read park rating
|
||||
sawyercoding_read_chunk(hFile, RCT2_ADDRESS_CURRENT_PARK_RATING);
|
||||
|
||||
// Read ?
|
||||
sawyercoding_read_chunk(hFile, 0x01357CF2);
|
||||
|
||||
// Read ?
|
||||
sawyercoding_read_chunk(hFile, 0x0135832C);
|
||||
|
||||
// Read ?
|
||||
sawyercoding_read_chunk(hFile, RCT2_ADDRESS_CURRENT_PARK_VALUE);
|
||||
|
||||
// Read more game data, including research items and rides
|
||||
sawyercoding_read_chunk(hFile, 0x01358740);
|
||||
|
||||
CloseHandle(hFile);
|
||||
|
||||
// Check expansion pack
|
||||
// RCT2_CALLPROC_EBPSAFE(0x006757E6);
|
||||
|
||||
RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
|
||||
map_update_tile_pointers();
|
||||
RCT2_CALLPROC_EBPSAFE(0x0069EBE4);
|
||||
return;
|
||||
}
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
RCT2_GLOBAL(0x009AC31B, uint8) = 255;
|
||||
RCT2_GLOBAL(0x009AC31C, uint16) = 3011;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00678282
|
||||
* scenario (ebx)
|
||||
*/
|
||||
void scenario_load(rct_scenario_basic *scenario)
|
||||
void scenario_load_and_play(rct_scenario_basic *scenario)
|
||||
{
|
||||
RCT2_CALLPROC_X(0x00678282, 0, scenario, 0, 0, 0, 0, 0);
|
||||
}
|
||||
@@ -108,6 +108,7 @@ enum {
|
||||
};
|
||||
|
||||
void scenario_load_list();
|
||||
void scenario_load(rct_scenario_basic *scenario);
|
||||
void scenario_load(char *path);
|
||||
void scenario_load_and_play(rct_scenario_basic *scenario);
|
||||
|
||||
#endif
|
||||
192
src/title.c
192
src/title.c
@@ -1,22 +1,22 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
* 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.
|
||||
* 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/>.
|
||||
*****************************************************************************/
|
||||
* 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 "date.h"
|
||||
@@ -28,20 +28,58 @@
|
||||
#include "park.h"
|
||||
#include "rct2.h"
|
||||
#include "ride.h"
|
||||
#include "scenario.h"
|
||||
#include "viewport.h"
|
||||
|
||||
static void title_create_windows();
|
||||
static void title_init_showcase();
|
||||
|
||||
// External functions
|
||||
void window_main_open();
|
||||
void window_title_menu_open();
|
||||
void window_title_exit_open();
|
||||
void window_title_logo_open();
|
||||
|
||||
#pragma region Showcase script
|
||||
|
||||
enum {
|
||||
TITLE_SCRIPT_WAIT,
|
||||
TITLE_SCRIPT_LOAD,
|
||||
TITLE_SCRIPT_LOCATION,
|
||||
TITLE_SCRIPT_ROTATE,
|
||||
TITLE_SCRIPT_RESTART,
|
||||
};
|
||||
|
||||
#define WAIT(t) TITLE_SCRIPT_WAIT, t
|
||||
#define LOAD() TITLE_SCRIPT_LOAD
|
||||
#define LOCATION(x, y) TITLE_SCRIPT_LOCATION, x, y
|
||||
#define ROTATE(n) TITLE_SCRIPT_ROTATE, n
|
||||
#define RESTART() TITLE_SCRIPT_RESTART
|
||||
|
||||
static const uint8 _magicMountainScript[] = {
|
||||
LOAD(),
|
||||
LOCATION(210, 112), WAIT(13),
|
||||
ROTATE(1), LOCATION(210, 112), WAIT(14),
|
||||
ROTATE(3), LOCATION(167, 180), WAIT(12),
|
||||
ROTATE(1), LOCATION(155, 189), WAIT(12),
|
||||
LOCATION(106, 39), WAIT(12),
|
||||
LOCATION(182, 50), WAIT(12),
|
||||
ROTATE(3), LOCATION(209, 47), WAIT(12),
|
||||
ROTATE(1), LOCATION(159, 93), WAIT(12),
|
||||
RESTART(),
|
||||
};
|
||||
|
||||
static const uint8* _currentScript;
|
||||
static int _scriptWaitCounter;
|
||||
|
||||
static void title_init_showcase();
|
||||
static void title_update_showcase();
|
||||
|
||||
#pragma endregion
|
||||
|
||||
static void title_create_windows();
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0068E8DA
|
||||
*/
|
||||
*
|
||||
* rct2: 0x0068E8DA
|
||||
*/
|
||||
void title_load()
|
||||
{
|
||||
if (RCT2_GLOBAL(0x009DEA6E, uint8) & 1)
|
||||
@@ -74,10 +112,10 @@ void title_load()
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the windows shown on the title screen; New game, load game,
|
||||
* tutorial, toolbox and exit.
|
||||
* rct2: 0x0066B5C0 (part of 0x0066B3E8)
|
||||
*/
|
||||
* Creates the windows shown on the title screen; New game, load game,
|
||||
* tutorial, toolbox and exit.
|
||||
* rct2: 0x0066B5C0 (part of 0x0066B3E8)
|
||||
*/
|
||||
static void title_create_windows()
|
||||
{
|
||||
// RCT2_CALLPROC_EBPSAFE(0x0066B3E8);
|
||||
@@ -90,12 +128,104 @@ static void title_create_windows()
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00678680
|
||||
*/
|
||||
*
|
||||
* rct2: 0x00678680
|
||||
*/
|
||||
static void title_init_showcase()
|
||||
{
|
||||
RCT2_CALLPROC_EBPSAFE(0x00678680);
|
||||
_currentScript = _magicMountainScript;
|
||||
_scriptWaitCounter = 0;
|
||||
title_update_showcase();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00678761
|
||||
*/
|
||||
static void title_update_showcase()
|
||||
{
|
||||
rct_window* w;
|
||||
uint8 script_opcode, script_operand;
|
||||
short x, y;
|
||||
int i, _edx;
|
||||
|
||||
if (_scriptWaitCounter <= 0) {
|
||||
do {
|
||||
script_opcode = *_currentScript++;
|
||||
switch (script_opcode) {
|
||||
case TITLE_SCRIPT_WAIT:
|
||||
_scriptWaitCounter = (*_currentScript++) * 32;
|
||||
break;
|
||||
case TITLE_SCRIPT_LOAD:
|
||||
scenario_load(get_file_path(PATH_ID_SIXFLAGS_MAGICMOUNTAIN));
|
||||
|
||||
w = window_get_main();
|
||||
w->var_4B0 = -1;
|
||||
w->var_4B2 = RCT2_GLOBAL(0x0138869A, sint16);
|
||||
w->var_4B4 = RCT2_GLOBAL(0x0138869C, sint16);
|
||||
|
||||
{
|
||||
char _cl = (RCT2_GLOBAL(0x0138869E, sint16) & 0xFF) - w->viewport->zoom;
|
||||
w->viewport->zoom = RCT2_GLOBAL(0x0138869E, sint16) & 0xFF;
|
||||
*((char*)(&RCT2_GLOBAL(0x0141E9E0, sint32))) = RCT2_GLOBAL(0x0138869E, sint16) >> 8;
|
||||
if (_cl != 0) {
|
||||
if (_cl < 0) {
|
||||
_cl = -_cl;
|
||||
w->viewport->view_width >>= _cl;
|
||||
w->viewport->view_height >>= _cl;
|
||||
} else {
|
||||
w->viewport->view_width <<= _cl;
|
||||
w->viewport->view_height <<= _cl;
|
||||
}
|
||||
}
|
||||
w->var_4B2 -= w->viewport->view_width >> 1;
|
||||
w->var_4B4 -= w->viewport->view_height >> 1;
|
||||
}
|
||||
|
||||
window_invalidate(w);
|
||||
RCT2_CALLPROC_EBPSAFE(0x0069E9A7);
|
||||
RCT2_CALLPROC_EBPSAFE(0x006ACA58);
|
||||
RCT2_CALLPROC_EBPSAFE(0x00684AC3);
|
||||
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
|
||||
news_item_init_queue();
|
||||
gfx_invalidate_screen();
|
||||
RCT2_GLOBAL(0x009DEA66, sint16) = 0;
|
||||
RCT2_GLOBAL(0x009DEA5C, sint16) = 0x0D6D8;
|
||||
break;
|
||||
case TITLE_SCRIPT_LOCATION:
|
||||
x = (*_currentScript++) * 32 + 16;
|
||||
y = (*_currentScript++) * 32 + 16;
|
||||
|
||||
// Set location
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
eax = x;
|
||||
ecx = y;
|
||||
RCT2_CALLFUNC_X(0x00662783, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
_edx = edx;
|
||||
|
||||
// Update viewport
|
||||
w = window_get_main();
|
||||
if (w != NULL) {
|
||||
RCT2_CALLPROC_X(0x006E7C9C, x, 0, y, _edx, w, 0, 0);
|
||||
w->flags &= ~0x08;
|
||||
viewport_update_position(w);
|
||||
}
|
||||
break;
|
||||
case TITLE_SCRIPT_ROTATE:
|
||||
script_operand = (*_currentScript++);
|
||||
w = window_get_main();
|
||||
if (w != NULL)
|
||||
for (i = 0; i < script_operand; i++)
|
||||
window_rotate_camera(w);
|
||||
break;
|
||||
case TITLE_SCRIPT_RESTART:
|
||||
_currentScript = _magicMountainScript;
|
||||
break;
|
||||
}
|
||||
} while (_scriptWaitCounter == 0);
|
||||
}
|
||||
|
||||
_scriptWaitCounter--;
|
||||
}
|
||||
|
||||
void title_update()
|
||||
@@ -103,7 +233,7 @@ void title_update()
|
||||
int tmp;
|
||||
|
||||
if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0) {
|
||||
RCT2_CALLPROC_EBPSAFE(0x00678761); // screen_title_script_tick()
|
||||
title_update_showcase();
|
||||
game_logic_update();
|
||||
}
|
||||
|
||||
|
||||
@@ -439,6 +439,15 @@ rct_window *window_get_main()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0068881A
|
||||
*/
|
||||
void window_rotate_camera(rct_window *w)
|
||||
{
|
||||
RCT2_CALLPROC_X(0x0068881A, 0, 0, 0, 0, w, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a window that is in the specified region.
|
||||
* rct2: 0x006E756C
|
||||
|
||||
@@ -283,6 +283,8 @@ rct_window *window_bring_to_front(rct_window *w);
|
||||
|
||||
rct_window *window_get_main();
|
||||
|
||||
void window_rotate_camera(rct_window *w);
|
||||
|
||||
void window_draw(rct_window *w, int left, int top, int right, int bottom);
|
||||
void window_draw_widgets(rct_window *w, rct_drawpixelinfo *dpi);
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ static void window_scenarioselect_scrollmousedown()
|
||||
continue;
|
||||
|
||||
sound_play_panned(4, w->width / 2 + w->x);
|
||||
scenario_load(scenario);
|
||||
scenario_load_and_play(scenario);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user