diff --git a/src/addresses.h b/src/addresses.h index 21b1ba53ed..8a16f77c8b 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -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 diff --git a/src/map.c b/src/map.c index c4dd8e4320..359386a5f3 100644 --- a/src/map.c +++ b/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; @@ -92,4 +92,37 @@ 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; } \ No newline at end of file diff --git a/src/map.h b/src/map.h index 9b05e27f5d..5508f52d0a 100644 --- a/src/map.h +++ b/src/map.h @@ -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 \ No newline at end of file diff --git a/src/scenario.c b/src/scenario.c index bed0b8d1d7..aeb96c4567 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -22,6 +22,7 @@ #include #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); } \ No newline at end of file diff --git a/src/scenario.h b/src/scenario.h index c64f125c3d..bbb42ef501 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -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 \ No newline at end of file diff --git a/src/title.c b/src/title.c index 6b14e1daa0..a67d8bc987 100644 --- a/src/title.c +++ b/src/title.c @@ -1,23 +1,23 @@ /***************************************************************************** - * 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 . +*****************************************************************************/ - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - #include "addresses.h" #include "date.h" #include "game.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(); } diff --git a/src/window.c b/src/window.c index cb4e169a5b..997e15fb23 100644 --- a/src/window.c +++ b/src/window.c @@ -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 diff --git a/src/window.h b/src/window.h index b962edbb3e..4dfaaa7d0e 100644 --- a/src/window.h +++ b/src/window.h @@ -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); diff --git a/src/window_title_scenarioselect.c b/src/window_title_scenarioselect.c index f0f4369a64..9eb5d4fa90 100644 --- a/src/window_title_scenarioselect.c +++ b/src/window_title_scenarioselect.c @@ -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; } }