diff --git a/CMakeLists_mingw.txt b/CMakeLists_mingw.txt index df0bbfacd1..7fb25965c1 100644 --- a/CMakeLists_mingw.txt +++ b/CMakeLists_mingw.txt @@ -17,9 +17,9 @@ else() endif (APPLE) # potential flags to make code more similar to MSVC: -# -fshort-wchar -fshort-enums -mms-bitfields -fpack-struct=1 +# -fshort-wchar -fshort-enums -mms-bitfields # -set(CMAKE_C_FLAGS "-masm=intel -std=gnu99" CACHE STRING "" FORCE) +set(CMAKE_C_FLAGS "-masm=intel -std=gnu99 -fpack-struct=2" CACHE STRING "" FORCE) set(CMAKE_SHARED_LINKER_FLAGS "-static-libgcc" CACHE STRING "" FORCE) include_directories("/usr/include/wine/windows/") diff --git a/src/addresses.h b/src/addresses.h index 8b26cd2209..974a9c7507 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -84,6 +84,8 @@ #define RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS 0x009ABDE8 #define RCT2_ADDRESS_DIRTY_BLOCK_ROWS 0x009ABDEC +#define RCT2_ADDRESS_LIGHTNING_ACTIVE 0x009AC068 + #define RCT2_ADDRESS_RUN_INTRO_TICK_PART 0x009AC319 #define RCT2_ADDRESS_INSTALLED_OBJECT_LIST 0x009ADAE8 @@ -111,6 +113,10 @@ #define RCT2_ADDRESS_CURRENT_TOOL 0x009DE545 #define RCT2_ADDRESS_TOOL_WIDGETINDEX 0x009DE546 +#define RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE 0x009DE550 +#define RCT2_ADDRESS_PICKEDUP_PEEP_X 0x009DE554 +#define RCT2_ADDRESS_PICKEDUP_PEEP_Y 0x009DE556 + #define RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS 0x009DE55C #define RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER 0x009DE55E #define RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX 0x009DE560 @@ -243,6 +249,7 @@ #define RCT2_ADDRESS_NEWS_ITEM_LIST 0x013CA754 #define RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE 0x013CE950 +#define RCT2_ADDRESS_CURRENT_FONT_FLAGS 0x013CE9A2 #define RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS 0x013CE9A4 #define RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT 0x0141E9AC @@ -251,6 +258,8 @@ #define RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID 0x0141E9AE #define RCT2_ADDRESS_CURRENT_ROTATION 0x0141E9E0 +#define RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER 0x0141ED68 + #define RCT2_ADDRESS_WATER_RAISE_COST 0x0141F738 #define RCT2_ADDRESS_WATER_LOWER_COST 0x0141F73C diff --git a/src/award.c b/src/award.c index 12084559ca..3f76984ebf 100644 --- a/src/award.c +++ b/src/award.c @@ -76,7 +76,7 @@ static int award_is_deserved_most_untidy(int awardType, int activeAwardTypes) if (peep->var_2A != 0) continue; - if (peep->thoughts[0].pad_3 > 5) + if (peep->thoughts[0].var_2 > 5) continue; if (peep->thoughts[0].type == PEEP_THOUGHT_TYPE_BAD_LITTER || @@ -109,7 +109,7 @@ static int award_is_deserved_most_tidy(int awardType, int activeAwardTypes) if (peep->var_2A != 0) continue; - if (peep->thoughts[0].pad_3 > 5) + if (peep->thoughts[0].var_2 > 5) continue; if (peep->thoughts[0].type == PEEP_THOUGHT_VERY_CLEAN) @@ -183,7 +183,7 @@ static int award_is_deserved_most_beautiful(int awardType, int activeAwardTypes) if (peep->var_2A != 0) continue; - if (peep->thoughts[0].pad_3 > 5) + if (peep->thoughts[0].var_2 > 5) continue; if (peep->thoughts[0].type == PEEP_THOUGHT_TYPE_SCENERY) @@ -226,7 +226,7 @@ static int award_is_deserved_safest(int awardType, int activeAwardTypes) FOR_ALL_GUESTS(spriteIndex, peep) { if (peep->var_2A != 0) continue; - if (peep->thoughts[0].pad_3 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_VANDALISM) + if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_VANDALISM) peepsWhoDislikeVandalism++; } @@ -307,7 +307,7 @@ static int award_is_deserved_best_food(int awardType, int activeAwardTypes) if (peep->var_2A != 0) continue; - if (peep->thoughts[0].pad_3 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_HUNGRY) + if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_HUNGRY) hungryPeeps++; } @@ -353,7 +353,7 @@ static int award_is_deserved_worst_food(int awardType, int activeAwardTypes) if (peep->var_2A != 0) continue; - if (peep->thoughts[0].pad_3 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_HUNGRY) + if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_HUNGRY) hungryPeeps++; } @@ -388,7 +388,7 @@ static int award_is_deserved_best_restrooms(int awardType, int activeAwardTypes) if (peep->var_2A != 0) continue; - if (peep->thoughts[0].pad_3 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_BATHROOM) + if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_BATHROOM) guestsWhoNeedRestroom++; } @@ -510,7 +510,7 @@ static int award_is_deserved_most_confusing_layout(int awardType, int activeAwar continue; peepsCounted++; - if (peep->thoughts[0].pad_3 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_LOST || peep->thoughts[0].type == PEEP_THOUGHT_TYPE_CANT_FIND) + if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_LOST || peep->thoughts[0].type == PEEP_THOUGHT_TYPE_CANT_FIND) peepsLost++; } @@ -568,6 +568,13 @@ static int award_is_deserved(int awardType, int activeAwardTypes) #pragma endregion +void award_reset() +{ + int i; + for (i = 0; i < MAX_AWARDS; i++) + RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award)[i].time = 0; +} + /** * * rct2: 0x0066A86C diff --git a/src/award.h b/src/award.h index 26074cdaa8..aba8cb9456 100644 --- a/src/award.h +++ b/src/award.h @@ -52,6 +52,7 @@ enum { #define MAX_AWARDS 4 int award_is_positive(int type); +void award_reset(); void award_update_all(); #endif \ No newline at end of file diff --git a/src/climate.c b/src/climate.c index 6c1d4a1fd7..37bae75fda 100644 --- a/src/climate.c +++ b/src/climate.c @@ -19,10 +19,19 @@ *****************************************************************************/ #include "addresses.h" +#include "audio.h" #include "climate.h" #include "date.h" #include "gfx.h" #include "rct2.h" +#include "scenario.h" + +enum { + THUNDER_STATUS_NULL = 0, + THUNDER_STATUS_PLAYING = 1, + + MAX_THUNDER_INSTANCES = 2 +}; typedef struct { sint8 base_temperature; @@ -32,6 +41,8 @@ typedef struct { int gClimateNextWeather; +static int _climateCurrentWeatherEffect; + static int _climateNextTemperature; static int _climateNextWeatherEffect; static int _climateNextWeatherGloom; @@ -39,8 +50,24 @@ static int _climateNextRainLevel; static const rct_weather_transition* climate_transitions[4]; +// Sound data +static int _rainVolume = 1; +static rct_sound _rainSoundInstance; +static unsigned int _lightningTimer, _thunderTimer; +static rct_sound _thunderSoundInstance[MAX_THUNDER_INSTANCES]; +static int _thunderStatus[MAX_THUNDER_INSTANCES] = { THUNDER_STATUS_NULL, THUNDER_STATUS_NULL }; +static unsigned int _thunderSoundId; +static int _thunderVolume; +static int _thunderStereoEcho = 0; + static void climate_determine_future_weather(); +static void climate_update_rain_sound(); +static void climate_update_thunder_sound(); +static void climate_update_lightning(); +static void climate_update_thunder(); +static int climate_play_thunder(int instanceIndex, int soundId, int volume, int pan); + int climate_celsius_to_fahrenheit(int celsius) { return (celsius * 29) / 16 + 32; @@ -88,7 +115,7 @@ void climate_update() if (temperature == target_temperature) { if (cur_gloom == next_gloom) { - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WEATHER_EFFECT, sint8) = _climateNextWeatherEffect; + _climateCurrentWeatherEffect = _climateNextWeatherEffect; if (cur_rain == next_rain) { RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WEATHER, sint8) = gClimateNextWeather; @@ -152,7 +179,127 @@ static void climate_determine_future_weather() RCT2_GLOBAL(RCT2_ADDRESS_CLIMATE_UPDATE_TIMER, sint16) = 1920; } +/** + * + * rct2: 0x006BCB91 + */ +void climate_update_sound() +{ + if (RCT2_GLOBAL(0x009AF280, uint32) == 0xFFFFFFFF) + return; + if (RCT2_GLOBAL(0x009AF59C, uint8) != 0) + return; + if (!(RCT2_GLOBAL(0x009AF59D, uint8) & 1)) + return; + if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1) + return; + climate_update_rain_sound(); + climate_update_thunder_sound(); +} + +static void climate_update_rain_sound() +{ + if (_climateCurrentWeatherEffect == 1 || _climateCurrentWeatherEffect == 2) { + if (_rainVolume == 1) { + // Start playing the rain sound + if (sound_prepare(SOUND_RAIN_1, &_rainSoundInstance, 1, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32))) + sound_play(&_rainSoundInstance, 1, -4000, 0, 0); + _rainVolume = -4000; + } else { + // Increase rain sound + _rainVolume = min(-1400, _rainVolume + 80); + RCT2_CALLPROC_2(0x00404F0D, rct_sound*, int, &_rainSoundInstance, _rainVolume); + } + } else if (_rainVolume != 1) { + // Decrease rain sound + _rainVolume -= 80; + if (_rainVolume > -4000) { + RCT2_CALLPROC_2(0x00404F0D, rct_sound*, int, &_rainSoundInstance, _rainVolume); + } else { + sound_stop(&_rainSoundInstance); + _rainVolume = 1; + } + } +} + +static void climate_update_thunder_sound() +{ + if (_thunderStereoEcho) { + // Play thunder on right side + _thunderStereoEcho = 0; + climate_play_thunder(1, _thunderSoundId, _thunderVolume, 10000); + } else if (_thunderTimer != 0) { + climate_update_lightning(); + climate_update_thunder(); + } else if (_climateCurrentWeatherEffect == 2) { + // Create new thunder and lightning + unsigned int randomNumber = scenario_rand(); + if ((randomNumber & 0xFFFF) <= 0x1B4) { + randomNumber >>= 16; + _thunderTimer = 43 + (randomNumber % 64); + _lightningTimer = randomNumber % 32; + } + } + + // Stop thunder sounds if they have finished + for (int i = 0; i < MAX_THUNDER_INSTANCES; i++) { + if (_thunderStatus[i] == THUNDER_STATUS_NULL) + continue; + + if (!RCT2_CALLFUNC_1(0x00404E53, int, rct_sound*, &_thunderSoundInstance[i])) { + sound_stop(&_thunderSoundInstance[i]); + _thunderStatus[i] = THUNDER_STATUS_NULL; + } + } +} + +static void climate_update_lightning() +{ + if (_lightningTimer == 0) + return; + + _lightningTimer--; + if (RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint16) == 0) + if ((scenario_rand() & 0xFFFF) <= 0x2000) + RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint16) = 1; +} + +static void climate_update_thunder() +{ + _thunderTimer--; + if (_thunderTimer != 0) + return; + + unsigned int randomNumber = scenario_rand(); + if (randomNumber & 0x10000) { + if (_thunderStatus[0] == THUNDER_STATUS_NULL && _thunderStatus[1] == THUNDER_STATUS_NULL) { + // Play thunder on left side + _thunderSoundId = (randomNumber & 0x20000) ? SOUND_THUNDER_1 : SOUND_THUNDER_2; + _thunderVolume = (-((int)((randomNumber >> 18) & 0xFF))) << 3; + climate_play_thunder(0, _thunderSoundId, _thunderVolume, -10000); + + // Let thunder play on right side + _thunderStereoEcho = 1; + } + } else { + _thunderSoundId = (randomNumber & 0x20000) ? SOUND_THUNDER_1 : SOUND_THUNDER_2; + int pan = (((randomNumber >> 18) & 0xFF) - 128) * 16; + climate_play_thunder(0, _thunderSoundId, 0, pan); + } +} + +static int climate_play_thunder(int instanceIndex, int soundId, int volume, int pan) +{ + if (sound_prepare(soundId, &_thunderSoundInstance[instanceIndex], 1, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32))) { + sound_play(&_thunderSoundInstance[instanceIndex], 0, volume, pan, 0); + + _thunderStatus[instanceIndex] = THUNDER_STATUS_PLAYING; + return 1; + } + + return 0; +} #pragma region Climate / Weather data tables diff --git a/src/climate.h b/src/climate.h index 814039f10f..376323d907 100644 --- a/src/climate.h +++ b/src/climate.h @@ -44,5 +44,6 @@ extern const rct_weather climate_weather_data[6]; int climate_celsius_to_fahrenheit(int celsius); void climate_reset(int climate); void climate_update(); +void climate_update_sound(); #endif diff --git a/src/config.c b/src/config.c index ad58991810..41551d94a5 100644 --- a/src/config.c +++ b/src/config.c @@ -76,15 +76,19 @@ static const uint16 _defaultShortcutKeys[SHORTCUT_COUNT] = { general_configuration_t gGeneral_config; general_configuration_t gGeneral_config_default = { - 1, - 1, - SCREENSHOT_FORMAT_PNG, - "", - MEASUREMENT_FORMAT_IMPERIAL, - TEMPERATURE_FORMAT_F, - 0, - 0, - 1, + 0, // play_intro + 1, // confirmation_prompt + SCREENSHOT_FORMAT_PNG, // screenshot_format + "", // game_path + MEASUREMENT_FORMAT_IMPERIAL, // measurement_format + TEMPERATURE_FORMAT_F, // temperature_format + CURRENCY_POUNDS, // currency_format + 0, // construction_marker_colour + 1, // edge_scrolling + 0, // always_show_gridlines + 1, // landscape_smoothing + 0, // show_height_as_units + 1, // save_plugin_data }; sound_configuration_t gSound_config; @@ -100,6 +104,10 @@ static void config_create_default(char *path); static int config_parse_currency(char* currency); static void config_error(char *msg); +void config_save_ini(char *path); +void config_write_ini_general(FILE *fp); +void config_write_ini_sound(FILE *fp); + /** * * rct2: 0x006E3604 @@ -136,6 +144,37 @@ void config_load() RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) = gGeneral_config.measurement_format; RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_TEMPERATURE, sint8) = gGeneral_config.temperature_format; + // always show gridlines + if (gGeneral_config.always_show_gridlines){ + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES; + } + else { + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) &= !CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES; + } + + // landscape smoothing + if (!gGeneral_config.landscape_smoothing){ + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= CONFIG_FLAG_DISABLE_SMOOTH_LANDSCAPE; + } + else { + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) &= !CONFIG_FLAG_DISABLE_SMOOTH_LANDSCAPE; + } + + // show height as units + if (gGeneral_config.show_height_as_units){ + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS; + } + else { + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) &= !CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS; + } + + // save plugin data + if (gGeneral_config.save_plugin_data){ + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= CONFIG_FLAG_SAVE_PLUGIN_DATA; + } + else { + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) &= !CONFIG_FLAG_SAVE_PLUGIN_DATA; + } //sound configuration RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_QUALITY, sint8) = gSound_config.sound_quality; @@ -189,6 +228,7 @@ void config_load() RCT2_GLOBAL(0x009AA00D, sint8) = 1; } + /** * Save configuration to the data/config.cfg file * rct2: 0x00675487 @@ -196,14 +236,144 @@ void config_load() void config_save() { FILE *fp=NULL; + char *configIniPath = osinterface_get_orct2_homefolder();; + fp = fopen(get_file_path(PATH_ID_GAMECFG), "wb"); if (fp != NULL){ fwrite(&MagicNumber, 4, 1, fp); fwrite((void*)0x009AAC5C, 2155, 1, fp); fclose(fp); } + + sprintf(configIniPath, "%s%c%s", configIniPath, osinterface_get_path_separator(), "config.ini"); + config_save_ini(configIniPath); } +void config_save_ini(char *path) +{ + FILE *fp = NULL; + + + fp = fopen(path, "wt+"); + + config_write_ini_general(fp); + config_write_ini_sound(fp); + + fclose(fp); +} + +void config_write_ini_sound(FILE *fp) +{ + fprintf(fp, "[sound]\n"); + if (gSound_config.sound_quality == SOUND_QUALITY_LOW) { + fprintf(fp, "sound_quality = low\n"); + } + else if (gSound_config.sound_quality == SOUND_QUALITY_MEDIUM) { + fprintf(fp, "sound_quality = medium\n"); + } + else{ + fprintf(fp, "sound_quality = high\n"); + } + + if (gSound_config.forced_software_buffering){ + fprintf(fp, "forced_software_buffering = true\n"); + } + else { + fprintf(fp, "forced_software_buffering = false\n"); + } +} + +void config_write_ini_general(FILE *fp) +{ + int currencyIterator = 0; + + fprintf(fp, "[general]\n"); + fprintf(fp, "game_path = %s\n", gGeneral_config.game_path); + + switch (gGeneral_config.screenshot_format) + { + case SCREENSHOT_FORMAT_BMP: + fprintf(fp, "screenshot_format = BMP\n"); + break; + case SCREENSHOT_FORMAT_PNG: + fprintf(fp, "screenshot_format = PNG\n"); + break; + default: + config_error("error saving config.ini: wrong screenshot_format"); + break; + } + + if (gGeneral_config.play_intro){ + fprintf(fp, "play_intro = true\n"); + } + else { + fprintf(fp, "play_intro = false\n"); + } + + if (gGeneral_config.confirmation_prompt){ + fprintf(fp, "confirmation_prompt = true\n"); + } + else { + fprintf(fp, "confirmation_prompt = false\n"); + } + + if (gGeneral_config.edge_scrolling){ + fprintf(fp, "edge_scrolling = true\n"); + } + else { + fprintf(fp, "edge_scrolling = false\n"); + } + + for (currencyIterator = 0; currencyIterator < countof(_currencyLookupTable); currencyIterator++) { + if (_currencyLookupTable[currencyIterator].value == gGeneral_config.currency_format) { + gGeneral_config.currency_format = _currencyLookupTable[currencyIterator].value; + fprintf(fp, "currency = %s\n", _currencyLookupTable[currencyIterator].key); + break; // There are more than one valid item for Pound, Euro and Dollar ... + } + } + + if (gGeneral_config.measurement_format == MEASUREMENT_FORMAT_IMPERIAL) { + fprintf(fp, "measurement_format = imperial\n"); + } + else { + fprintf(fp, "measurement_format = metric\n"); + } + + if (gGeneral_config.temperature_format == TEMPERATURE_FORMAT_F) { + fprintf(fp, "temperature_format = fahrenheit\n"); + } + else { + fprintf(fp, "temperature_format = celsius\n"); + } + + if (gGeneral_config.always_show_gridlines){ + fprintf(fp, "always_show_gridlines = true\n"); + } + else { + fprintf(fp, "always_show_gridlines = false\n"); + } + + if (gGeneral_config.landscape_smoothing){ + fprintf(fp, "landscape_smoothing = true\n"); + } + else { + fprintf(fp, "landscape_smoothing = false\n"); + } + + if (gGeneral_config.show_height_as_units){ + fprintf(fp, "show_height_as_units = true\n"); + } + else { + fprintf(fp, "show_height_as_units = false\n"); + } + + if (gGeneral_config.save_plugin_data){ + fprintf(fp, "save_plugin_data = true\n"); + } + else { + fprintf(fp, "save_plugin_data = false\n"); + } +} /** * Initilise the settings. @@ -278,8 +448,7 @@ static int config_find_rct2_path(char *resultPath) */ static void config_create_default(char *path) { - FILE* fp; - + gGeneral_config = gGeneral_config_default; if (!config_find_rct2_path(gGeneral_config.game_path)) { osinterface_show_messagebox("Unable to find RCT2 installation directory. Please select the directory where you installed RCT2!"); @@ -287,20 +456,7 @@ static void config_create_default(char *path) strcpy(gGeneral_config.game_path, res); } - fp = fopen(path, "w"); - fprintf(fp, "[general]\n"); - fprintf(fp, "game_path = %s\n", gGeneral_config.game_path); - fprintf(fp, "screenshot_format = PNG\n"); - fprintf(fp, "play_intro = false\n"); - fprintf(fp, "confirmation_prompt = true\n"); - fprintf(fp, "edge_scrolling = true\n"); - fprintf(fp, "currency = GBP\n"); - fprintf(fp, "measurement_format = imperial\n"); - fprintf(fp, "temperature_format = fahrenheit\n"); - fprintf(fp, "[sound]\n"); - fprintf(fp, "sound_quality = high\n"); - fprintf(fp, "forced_software_buffering = false\n"); - fclose(fp); + config_save_ini(path); } @@ -415,7 +571,38 @@ static void config_general(char *setting, char *value){ else if (strcmp(setting, "currency") == 0){ config_parse_currency(value); } - + else if (strcmp(setting, "always_show_gridlines") == 0){ + if (strcmp(value, "true") == 0){ + gGeneral_config.always_show_gridlines = 1; + } + else { + gGeneral_config.always_show_gridlines = 0; + } + } + else if (strcmp(setting, "landscape_smoothing") == 0){ + if (strcmp(value, "true") == 0){ + gGeneral_config.landscape_smoothing = 1; + } + else { + gGeneral_config.landscape_smoothing = 0; + } + } + else if (strcmp(setting, "show_height_as_units") == 0){ + if (strcmp(value, "true") == 0){ + gGeneral_config.show_height_as_units = 1; + } + else { + gGeneral_config.show_height_as_units = 0; + } + } + else if (strcmp(setting, "save_plugin_data") == 0){ + if (strcmp(value, "true") == 0){ + gGeneral_config.save_plugin_data = 1; + } + else { + gGeneral_config.save_plugin_data = 0; + } + } } /** @@ -588,25 +775,6 @@ static int config_parse_section(FILE *fp, char *setting, char *value){ return 1; } -static const struct { char *key; int value; } _currencyLookupTable[] = { - { "GBP", CURRENCY_POUNDS }, - { "USD", CURRENCY_DOLLARS }, - { "FRF", CURRENCY_FRANC }, - { "DEM", CURRENCY_DEUTSCHMARK }, - { "YEN", CURRENCY_YEN }, - { "ESP", CURRENCY_PESETA }, - { "ITL", CURRENCY_LIRA }, - { "NLG", CURRENCY_GUILDERS }, - { "NOK", CURRENCY_KRONA }, - { "SEK", CURRENCY_KRONA }, - { "DEK", CURRENCY_KRONA }, - { "EUR", CURRENCY_EUROS }, - - { "£", CURRENCY_POUNDS }, - { "$", CURRENCY_DOLLARS }, - { "€", CURRENCY_EUROS } -}; - static int config_parse_currency(char *currency) { int i; diff --git a/src/config.h b/src/config.h index eb86ab5da2..6e43a04b4e 100644 --- a/src/config.h +++ b/src/config.h @@ -136,9 +136,31 @@ typedef struct general_configuration { sint8 currency_format; sint8 construction_marker_colour; sint8 edge_scrolling; - + sint8 always_show_gridlines; + sint8 landscape_smoothing; + sint8 show_height_as_units; + sint8 save_plugin_data; } general_configuration_t; +static const struct { char *key; int value; } _currencyLookupTable[] = { + { "GBP", CURRENCY_POUNDS }, + { "USD", CURRENCY_DOLLARS }, + { "FRF", CURRENCY_FRANC }, + { "DEM", CURRENCY_DEUTSCHMARK }, + { "YEN", CURRENCY_YEN }, + { "ESP", CURRENCY_PESETA }, + { "ITL", CURRENCY_LIRA }, + { "NLG", CURRENCY_GUILDERS }, + { "NOK", CURRENCY_KRONA }, + { "SEK", CURRENCY_KRONA }, + { "DEK", CURRENCY_KRONA }, + { "EUR", CURRENCY_EUROS }, + + { "£", CURRENCY_POUNDS }, + { "$", CURRENCY_DOLLARS }, + { "€", CURRENCY_EUROS } +}; + //typedef struct hotkey_configuration{ //}; diff --git a/src/finance.c b/src/finance.c index f61def04c4..a900c9ec82 100644 --- a/src/finance.c +++ b/src/finance.c @@ -137,6 +137,15 @@ void finance_pay_ride_upkeep() } } +void finance_reset_history() +{ + int i; + for (i = 0; i < 128; i++) { + RCT2_ADDRESS(RCT2_ADDRESS_BALANCE_HISTORY, money32)[i] = MONEY32_UNDEFINED; + RCT2_ADDRESS(RCT2_ADDRESS_WEEKLY_PROFIT_HISTORY, money32)[i] = MONEY32_UNDEFINED; + RCT2_ADDRESS(RCT2_ADDRESS_PARK_VALUE_HISTORY, money32)[i] = MONEY32_UNDEFINED; + } +} /** * diff --git a/src/finance.h b/src/finance.h index fb63ae127f..ace3b157ae 100644 --- a/src/finance.h +++ b/src/finance.h @@ -38,6 +38,7 @@ void finance_pay_wages(); void finance_pay_research(); void finance_pay_interest(); void finance_pay_ride_upkeep(); +void finance_reset_history(); void finance_init(); void sub_69E869(); diff --git a/src/game.c b/src/game.c index 0a9e82f4ab..ac83922df2 100644 --- a/src/game.c +++ b/src/game.c @@ -59,10 +59,47 @@ void game_create_windows() RCT2_CALLPROC_EBPSAFE(0x0066B905); } +/** + * + * rct2: 0x006838BD + */ +void update_water_animation() +{ + RCT2_CALLPROC_EBPSAFE(0x006838BD); +} + +/** + * + * rct2: 0x00684218 + */ +void update_rain_animation() +{ + if (RCT2_GLOBAL(0x009ABDF2, uint8) == 0) + return; + + // Draw picked-up peep + if (RCT2_GLOBAL(0x009DE550, uint32) != 0xFFFFFFFF) { + gfx_draw_sprite( + (rct_drawpixelinfo*)RCT2_ADDRESS_SCREEN_DPI, + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32), + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_Y, sint16) + ); + } + + // Get rain draw function and draw rain + uint32 eax = RCT2_ADDRESS(0x009AC058, uint32)[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RAIN_LEVEL, uint8)]; + if (eax != 0xFFFFFFFF && !(RCT2_GLOBAL(0x009DEA6F, uint8) & 1)) + RCT2_CALLPROC_X(0x00684266, eax, 0, 0, 0, 0, 0, 0); +} + void game_update() { int eax, tmp; + // Handles picked-up peep and rain redraw + RCT2_CALLPROC_EBPSAFE(0x006843DC); + // 0x006E3AEC // screen_game_process_mouse_input(); // RCT2_CALLPROC_EBPSAFE(0x006E3AEC); // screen_game_process_keyboard_input(); screenshot_check(); @@ -124,8 +161,8 @@ void game_update() RCT2_GLOBAL(0x0141F568, uint8) = RCT2_GLOBAL(0x0013CA740, uint8); game_handle_input(); - RCT2_CALLPROC_EBPSAFE(0x006838BD); - RCT2_CALLPROC_EBPSAFE(0x00684218); + update_water_animation(); + update_rain_animation(); if (RCT2_GLOBAL(0x009AAC73, uint8) != 255) { RCT2_GLOBAL(0x009AAC73, uint8)++; @@ -160,7 +197,7 @@ void game_logic_update() RCT2_CALLPROC_EBPSAFE(0x0068AFAD); RCT2_CALLPROC_EBPSAFE(0x006BBC6B); // vehicle and scream sounds peep_update_crowd_noise(); - RCT2_CALLPROC_EBPSAFE(0x006BCB91); // weather sound effects + climate_update_sound(); news_item_update_current(); RCT2_CALLPROC_EBPSAFE(0x0067009A); // scenario editor opening of windows for a phase @@ -617,6 +654,37 @@ static void input_mouseover_widget_flatbutton_invalidate() widget_invalidate(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber)); } +static void RCT2_CALLPROC_WE_MOUSE_DOWN(int address, int widgetIndex, rct_window*w, rct_widget* widget ) +{ +#ifdef _MSC_VER + __asm { + push address + push widget + push w + push widgetIndex + mov edi, widget + mov edx, widgetIndex + mov esi, w + call[esp + 12] + add esp, 16 + } +#else + __asm__("\ + push %[address]\n\ + mov edi, %[widget] \n\ + mov eax, %[w] \n\ + mov edx, %[widgetIndex] \n\ + push edi \n\ + push eax \n\ + push edx \n\ + mov esi, %[w] \n\ + call [esp+12] \n\ + add esp, 16 \n\ + " :[address] "+m" (address), [w] "+m" (w), [widget] "+m" (widget), [widgetIndex] "+m" (widgetIndex): : "eax", "esi", "edx", "edi" + ); +#endif +} + /** * * rct2: 0x006E95F9 @@ -766,7 +834,7 @@ static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex) RCT2_GLOBAL(0x009DE528, uint16) = 1; widget_invalidate(windowClass, windowNumber, widgetIndex); - RCT2_CALLPROC_X(w->event_handlers[WE_MOUSE_DOWN], 0, 0, 0, widgetIndex, (int)w, (int)widget, 0); + RCT2_CALLPROC_WE_MOUSE_DOWN(w->event_handlers[WE_MOUSE_DOWN], widgetIndex, w, widget); break; } } @@ -1030,7 +1098,7 @@ void handle_shortcut_command(int shortcutIndex) RCT2_CALLPROC_EBPSAFE(0x006B3CFF); window = window_find_by_id(WC_CONSTRUCT_RIDE, 0); if (window != NULL) - window_event_helper(window, 10, WE_MOUSE_DOWN); + RCT2_CALLPROC_WE_MOUSE_DOWN(window->event_handlers[WE_MOUSE_DOWN], 10, window, NULL); } break; case SHORTCUT_SHOW_RIDES_LIST: @@ -1597,6 +1665,35 @@ static void load_game() } } +char save_game() +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + RCT2_CALLFUNC_X(0x006750E9, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + if (eax == 0) { + // user pressed "cancel" + gfx_invalidate_screen(); + return 0; + } + + char *src = (char*)0x0141EF67; + do { + src++; + } while (*src != '.' && *src != '\0'); + strcpy(src, ".SV6"); + strcpy((char*) RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*) 0x0141EF68); + + eax = 0; + if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & 8) + eax |= 1; + RCT2_CALLPROC_X(0x006754F5, eax, 0, 0, 0, 0, 0, 0); + // check success? + + game_do_command(0, 1047, 0, -1, 0, 0, 0); + gfx_invalidate_screen(); + + return 1; +} + /** * * rct2: 0x006E3879 diff --git a/src/game.h b/src/game.h index 8619d04526..4b1bd42d4c 100644 --- a/src/game.h +++ b/src/game.h @@ -29,5 +29,6 @@ int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int eb void game_load_or_quit_no_save_prompt(); int game_load_save(); +char save_game(); #endif diff --git a/src/gfx.c b/src/gfx.c index c5e64c3222..62bc70faf0 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -373,7 +373,7 @@ void gfx_fill_rect(rct_drawpixelinfo *dpi, int left, int top, int right, int bot } else { // 00678B7E 00678C83 - if (dpi->pad_0E < 1) { + if (dpi->zoom_level < 1) { // Location in screen buffer? uint8* pixel = top_ * (dpi->width + dpi->pitch) + left_ + dpi->bits; @@ -391,10 +391,10 @@ void gfx_fill_rect(rct_drawpixelinfo *dpi, int left, int top, int right, int bot } pixel += length; } - } else if (dpi->pad_0E > 1) { + } else if (dpi->zoom_level > 1) { // 00678C8A 00678D57 right_ = right; - } else if (dpi->pad_0E == 1) { + } else if (dpi->zoom_level == 1) { // 00678C88 00678CEE right = right; } @@ -953,15 +953,15 @@ void gfx_draw_sprite_palette_set(rct_drawpixelinfo *dpi, int image_id, int x, in int image_type = (image_id & 0xE0000000) >> 28; rct_g1_element* g1_source = &((rct_g1_element*)RCT2_ADDRESS_G1_ELEMENTS)[image_element]; - rct_g1_element zoomed = gfx_sprite_zoom_image(g1_source, dpi->pad_0E); + rct_g1_element zoomed = gfx_sprite_zoom_image(g1_source, dpi->zoom_level); if (zoomed.offset != NULL)g1_source = &zoomed; - if (dpi->pad_0E >= 1){ //These have not been tested + if (dpi->zoom_level >= 1){ //These have not been tested //something to do with zooming - if (dpi->pad_0E == 1){ + if (dpi->zoom_level == 1){ RCT2_CALLPROC_X(0x0067BD81, 0, (int)g1_source, x, y, 0,(int) dpi, 0); return; } - if (dpi->pad_0E == 2){ + if (dpi->zoom_level == 2){ RCT2_CALLPROC_X(0x0067DADA, 0, (int)g1_source, x, y, 0, (int)dpi, 0); return; } @@ -1131,7 +1131,22 @@ void gfx_transpose_palette(int pal, unsigned char product) */ void gfx_draw_string_centred(rct_drawpixelinfo *dpi, int format, int x, int y, int colour, void *args) { - RCT2_CALLPROC_X(0x006C1D6C, colour, format, x, y, (int)args, (int)dpi, 0); + char* buffer; + short text_width; + + buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); + format_string(buffer, format, args); + + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 0xE0; + + // Measure text width + text_width = gfx_get_string_width(buffer); + + // Draw the text centred + if (text_width <= 0xFFF) { + x -= text_width / 2; + gfx_draw_string(dpi, buffer, colour, x, y); + } } /** @@ -1272,18 +1287,153 @@ void gfx_redraw_screen_rect(short left, short top, short right, short bottom) } /** - * + * Return the width of the string in buffer + * * rct2: 0x006C2321 * buffer (esi) */ -int gfx_get_string_width(char *buffer) +int gfx_get_string_width(char* buffer) { - int eax, ebx, ecx, edx, esi, edi, ebp; + // Current font sprites + uint16* current_font_sprite_base; + // Width of string + int width; - esi = (int)buffer; - RCT2_CALLFUNC_X(0x006C2321, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + current_font_sprite_base = RCT2_ADDRESS(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16); + width = 0; - return ecx & 0xFFFF; + for (char* curr_char = buffer; *curr_char != NULL; curr_char++) { + + if (*curr_char >= 0x20) { + width += RCT2_ADDRESS(0x0141E9E8, uint8)[*current_font_sprite_base + (*curr_char-0x20)]; + continue; + } + switch(*curr_char) { + case 1: + width = *curr_char; + curr_char++; + break; + case 2: + case 3: + case 4: + curr_char++; + break; + case 7: + *current_font_sprite_base = 0x1C0; + break; + case 8: + *current_font_sprite_base = 0x2A0; + break; + case 9: + *current_font_sprite_base = 0x0E0; + break; + case 0x0A: + *current_font_sprite_base = 0; + break; + case 0x17: + width = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS + 4, uint16)[(*curr_char & 0x7FFFF) << 4]; + curr_char += 4; + *curr_char = 0; + break; + default: + if (*curr_char <= 0x10) { + continue; + } + curr_char += 2; + if (*curr_char <= 0x16) { + continue; + } + curr_char += 2; + break; + } + } + return width; +} + +/** + * Clip the text in buffer to width, add ellipsis and return the new width of the clipped string + * + * rct2: 0x006C2460 + * buffer (esi) + * width (edi) + */ +int gfx_clip_string(char* buffer, int width) +{ + // Location of font sprites + uint16* current_font_sprite_base; + // Width the string has to fit into + int max_width; + // Character to change to ellipsis + char* last_char; + // Width of the string, including ellipsis + int clipped_width; + + if (width < 6) { + *buffer = 0; + return 0; + } + + current_font_sprite_base = RCT2_ADDRESS(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16); + max_width = width - (3 * RCT2_ADDRESS(0x141E9F6, uint8)[*current_font_sprite_base]); + + clipped_width = 0; + last_char = buffer; + + for (char* curr_char = buffer; *curr_char != NULL; curr_char++) { + if (*curr_char < 0x20) { + switch(*curr_char) { + case 1: + width = *curr_char; + curr_char++; + continue; + case 2: + case 3: + case 4: + curr_char++; + continue; + case 7: + *current_font_sprite_base = 0x1C0; + break; + case 8: + *current_font_sprite_base = 0x2A0; + break; + case 9: + *current_font_sprite_base = 0x0E0; + break; + case 0x0A: + *current_font_sprite_base = 0; + break; + case 0x17: + clipped_width = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS + 4, uint16)[(*curr_char & 0x7FFFF) << 4]; + curr_char += 4; + *curr_char = 0; + continue; + default: + if (*curr_char <= 0x10) { + continue; + } + curr_char += 2; + if (*curr_char <= 0x16) { + continue; + } + curr_char += 2; + continue; + } + max_width = width - (3 * RCT2_ADDRESS(0x141E9F6, uint8)[*current_font_sprite_base]); + } + + clipped_width += RCT2_ADDRESS(0x0141E9E8, uint8)[*current_font_sprite_base + (*curr_char-0x20)]; + + if (clipped_width >= width) { + RCT2_GLOBAL(last_char, uint32) = 0x2E2E2E; + clipped_width = width; + return clipped_width; + } + if (clipped_width <= max_width) { + last_char = curr_char; + } + } + return clipped_width; } /** @@ -1300,15 +1450,19 @@ int gfx_get_string_width(char *buffer) */ void gfx_draw_string_left_clipped(rct_drawpixelinfo* dpi, int format, void* args, int colour, int x, int y, int width) { - RCT2_CALLPROC_X(0x006C1B83, colour, format, x, y, (int)args, (int)dpi, width); + // RCT2_CALLPROC_X(0x006C1B83, colour, format, x, y, (int)args, (int)dpi, width); - //char* buffer; + char* buffer; - //buffer = (char*)0x0141ED68; - //format_string(buffer, format, args); - //rctmem->current_font_sprite_base = 224; - //clip_text(buffer, width); - //gfx_draw_string(dpi, buffer, colour, x, y); + buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); + format_string(buffer, format, args); + + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 0xE0; + + // Clip text - return value is not needed + gfx_clip_string(buffer, width); + + gfx_draw_string(dpi, buffer, colour, x, y); } /** @@ -1325,19 +1479,22 @@ void gfx_draw_string_left_clipped(rct_drawpixelinfo* dpi, int format, void* args */ void gfx_draw_string_centred_clipped(rct_drawpixelinfo *dpi, int format, void *args, int colour, int x, int y, int width) { - RCT2_CALLPROC_X(0x006C1BBA, colour, format, x, y, (int)args, (int)dpi, width); + char* buffer; + short text_width; - //char* buffer; - //short text_width; + buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); + format_string(buffer, format, args); - //buffer = (char*)0x0141ED68; - //format_string(buffer, format, args); - //rctmem->current_font_sprite_base = 224; - //text_width = clip_text(buffer, width); + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 0xE0; - //// Draw the text centred - //x -= (text_width - 1) / 2; - //gfx_draw_string(dpi, buffer, colour, x, y); + // Clip text + text_width = gfx_clip_string(buffer, width); + + // Draw the text centred + if (text_width <= 0xFFF) { + x -= (text_width - 1) / 2; + gfx_draw_string(dpi, buffer, colour, x, y); + } } @@ -1356,7 +1513,7 @@ void gfx_draw_string_right(rct_drawpixelinfo* dpi, int format, void* args, int c char* buffer; short text_width; - buffer = (char*)0x0141ED68; + buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); format_string(buffer, format, args); // Measure text width @@ -1381,15 +1538,62 @@ void gfx_draw_string_right(rct_drawpixelinfo* dpi, int format, void* args, int c int gfx_draw_string_centred_wrapped(rct_drawpixelinfo *dpi, void *args, int x, int y, int width, int format, int colour) { int eax, ebx, ecx, edx, esi, edi, ebp; + // Location of font sprites + uint16* current_font_sprite_base; + // Location of font flags + uint16 current_font_flags; - eax = colour; - ebx = format; - ecx = x; - edx = y; - esi = (int)args; - edi = (int)dpi; - ebp = width; - RCT2_CALLFUNC_X(0x006C1E53, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + current_font_sprite_base = RCT2_ADDRESS(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16); + *current_font_sprite_base = 0xE0; + + char* buffer = RCT2_ADDRESS(0x009C383D, char); + + gfx_draw_string(dpi, buffer, colour, dpi->x, dpi->y); + + buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); + + format_string(buffer, format, args); + + *current_font_sprite_base = 0xE0; + + esi = buffer; + edi = width; + RCT2_CALLFUNC_X(0x006C21E2, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + ecx &= 0xFFFF; + edi &= 0xFFFF; + + RCT2_GLOBAL(0x00F43938, uint16) = 0x0A; + + if (ebx > 0xE0) { + RCT2_GLOBAL(0x00F43938, uint16) = 6; + if (ebx != 0x1C0) { + RCT2_GLOBAL(0x00F43938, uint16) = 0x12; + } + } + + if (*buffer == 0x0B) { + RCT2_GLOBAL(0x00F43938, uint16) = RCT2_GLOBAL(0x00F43938, uint16) + 1; + } + + ebx = (RCT2_GLOBAL(0x00F43938, uint16) / 2) * edi; + edx = y - ebx; + + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_FLAGS, uint16) = 0; + + buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); + + do { + int new_width = gfx_get_string_width(buffer); + new_width /= 2; + gfx_draw_string(dpi, buffer, 0xFE, x - new_width, edx); + + buffer += strlen(buffer) + 1; + + edx += RCT2_GLOBAL(0x00F43938, uint16); + eax = (RCT2_GLOBAL(0x00F43938, uint16) / 2) * edi; + ebx -= eax; + + } while (ebx > 0); return (sint16)(edx & 0xFFFF) - y; } @@ -1408,17 +1612,78 @@ int gfx_draw_string_centred_wrapped(rct_drawpixelinfo *dpi, void *args, int x, i int gfx_draw_string_left_wrapped(rct_drawpixelinfo *dpi, void *args, int x, int y, int width, int format, int colour) { int eax, ebx, ecx, edx, esi, edi, ebp; + + // eax = colour; + // ebx = format; + // ecx = x; + // edx = y; + // esi = (int)args; + // edi = (int)dpi; + // ebp = width; + // RCT2_CALLFUNC_X(0x006C2105, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + // return (sint16)(edx & 0xFFFF) - y; - eax = colour; - ebx = format; - ecx = x; - edx = y; - esi = (int)args; - edi = (int)dpi; - ebp = width; - RCT2_CALLFUNC_X(0x006C2105, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + // Location of font sprites + uint16* current_font_sprite_base; + // Location of font flags + uint16 current_font_flags; + + current_font_sprite_base = RCT2_ADDRESS(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16); + *current_font_sprite_base = 0xE0; + + char* buffer = RCT2_ADDRESS(0x009C383D, char); + + gfx_draw_string(dpi, buffer, colour, dpi->x, dpi->y); + + buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); + + format_string(buffer, format, args); + + buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); + + *current_font_sprite_base = 0xE0; + + // Add line breaks? Adds \0 rather than \n + // not working for strings with colour code? + esi = buffer; + edi = width; + RCT2_CALLFUNC_X(0x006C21E2, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + ecx &= 0xFFFF; + edi &= 0xFFFF; + + // Font height? + RCT2_GLOBAL(0x00F43938, uint16) = 0x0A; + + if (ebx > 0xE0) { + RCT2_GLOBAL(0x00F43938, uint16) = 6; + if (ebx != 0x1C0) { + RCT2_GLOBAL(0x00F43938, uint16) = 0x12; + } + } + + // Number of lines? + ebx = (RCT2_GLOBAL(0x00F43938, uint16) / 2) * edi; + + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_FLAGS, uint16) = 0; + + buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); + esi = buffer; + + edx = y; + + do { + gfx_draw_string(dpi, buffer, 0xFE, x, edx); + + buffer += strlen(buffer) + 1; + + edx += RCT2_GLOBAL(0x00F43938, uint16); + eax = (RCT2_GLOBAL(0x00F43938, uint16) / 2); + ebx -= eax; + + } while (ebx >= 0); return (sint16)(edx & 0xFFFF) - y; + } /** @@ -1435,179 +1700,361 @@ void gfx_draw_string_left(rct_drawpixelinfo *dpi, int format, void *args, int co { char* buffer; - buffer = (char*)0x0141ED68; + buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); format_string(buffer, format, args); gfx_draw_string(dpi, buffer, colour, x, y); } + +void colour_char(int al, uint16* current_font_flags) { + + int eax; + + rct_g1_element* g1_element = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[0x1332]); + eax = g1_element->offset[(al & 0xFF) * 4]; + + if (!(*current_font_flags & 2)) { + eax = eax & 0x0FF0000FF; + } + // Store current colour? + RCT2_GLOBAL(0x009ABE05, uint32) = eax; + RCT2_GLOBAL(0x009ABDA4, uint32) = 0x009ABE04; +} + + +void sub_682AC7(int ebp, uint16* current_font_flags) { + + int eax; + + // loc_682AC7 + eax = RCT2_ADDRESS(0x0141FD45, uint8)[ebp * 8]; + if (*current_font_flags & 2) { + eax |= 0x0A0A00; + } + //Store current colour? + RCT2_GLOBAL(0x009ABE05, uint32) = eax; + RCT2_GLOBAL(0x009ABDA4, uint32) = 0x009ABE04; + eax = 0; + // jmp loc_682842 + +} + + /** * * rct2: 0x00682702 * dpi (edi) - * format (esi) + * buffer (esi) * colour (al) * x (cx) * y (dx) */ -void gfx_draw_string(rct_drawpixelinfo *dpi, char *format, int colour, int x, int y) +void gfx_draw_string(rct_drawpixelinfo *dpi, char *buffer, int colour, int x, int y) { int eax, ebx, ecx, edx, esi, edi, ebp; + rct_g1_element* g1_element; - eax = colour; - ebx = 0; - ecx = x; - edx = y; - esi = (int)format; - edi = (int)dpi; - ebp = 0; - //RCT2_CALLFUNC_X(0x00682702, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + // Maximum length/height of string + int max_x = x; + int max_y = y; - gLastDrawStringX = ecx; - gLastDrawStringY = edx; + // Store original x, y + RCT2_GLOBAL(0x00EDF840, uint16) = x; + RCT2_GLOBAL(0x00EDF842, uint16) = y; - RCT2_GLOBAL(0xEDF840, uint16) = ecx; - RCT2_GLOBAL(0xEDF842, uint16) = edx; - RCT2_GLOBAL(0x9E3CDC, uint32) = 0; + // + uint16* current_font_flags = RCT2_ADDRESS(RCT2_ADDRESS_CURRENT_FONT_FLAGS, uint16); + uint16* current_font_sprite_base = RCT2_ADDRESS(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16); - if ((eax & 0xFF) == 0xFE){ - goto mov0x682853; - //jmp 0x682853 - } + // Flag for skipping non-printing characters + int skip_char = 0; - ebx = dpi->x; - ebx += dpi->width; - if (ecx >= ebx){ - return; - } - ebx = ecx; - ebx += 0x280; - if (ebx <= dpi->x){ - return; - } - ebx = dpi->y; - ebx += dpi->height; - if (edx >= ebx){ - return; - } - ebx = edx; - ebx += 0x5A; - if (ebx <= dpi->y){ - return; - } - if ((eax & 0xff) == 0xff){ - goto mov0x682853; - //jmp 0x682853 - } + if (colour != 0xFE) { - RCT2_GLOBAL(0x13CE9A2, uint16) = 0; - if (RCT2_GLOBAL(0x13CE950, sint16) < 0){ - RCT2_GLOBAL(0x13CE9A2, uint16) |= 0x4; - if (RCT2_GLOBAL(0x13CE950, uint16)!=0xFFFF){ - RCT2_GLOBAL(0x13CE9A2, uint16) |= 0x8; - } - RCT2_GLOBAL(0x13CE950, uint16) = 0xE0; - } - if (eax&(1 << 5)){ - RCT2_GLOBAL(0x13CE9A2, uint16) |= 0x2; - } - eax &= ~(1 << 5); - if (!(eax & 0x40)){ - RCT2_CALLPROC_X(0x00682702, colour, 0, x, y, (int)format, (int)dpi, 0); - return; - //jmp 0x682aa9 - } - RCT2_GLOBAL(0x13CE9A2, uint16) |= 0x1; - eax &= 0x1F; + if (x >= dpi->x + dpi->width) + return; + + if (x + 0x280 <= dpi->x) + return; - ebp = eax; - if (!(RCT2_GLOBAL(0x13CE9A2, uint16) & 0x4)){ - eax = RCT2_GLOBAL(0x141FC4A + ebp * 8,uint8); - eax <<= 0x10; - eax |= RCT2_GLOBAL(0x141FC48 + ebp * 8, uint8); - } - else if (!(RCT2_GLOBAL(0x13CE9A2, uint16) & 0x8)){ - eax = RCT2_GLOBAL(0x141FC49 + ebp * 8, uint8); - eax <<= 0x10; - eax |= RCT2_GLOBAL(0x141FC47 + ebp * 8, uint8); + if (y >= dpi->y + dpi->height) + return; - } - else{ - eax = RCT2_GLOBAL(0x141FC48 + ebp * 8, uint8); - eax <<= 0x10; - eax |= RCT2_GLOBAL(0x141FC46 + ebp * 8, uint8); - } - RCT2_GLOBAL(0x9abe05, uint32) = eax; - RCT2_GLOBAL(0x9abda4, uint32) = 0x9abe04; - eax = 0; - if (0){ -add0x682818: - if (!(RCT2_GLOBAL(0x13CE9A2, uint16) & 0x1)){ - eax &= 0xFF; - ebp = RCT2_GLOBAL(0x9ff048, uint32); - eax = *((uint32*)(eax * 4 + ebp)); - if (!(RCT2_GLOBAL(0x13CE9A2, uint16) & 0x2)){ - eax &= 0xff0000ff; - } - RCT2_GLOBAL(0x9abe05, uint32) = eax; - RCT2_GLOBAL(0x9abda4, uint32) = 0x9abe04; - eax = 0; - } - } -mov0x682853: - eax = edx; - eax += 0x13; - if ( eax <= dpi->y){ - //jmp 0x682B63 - RCT2_CALLPROC_X(0x00682702, colour, 0, x, y, (int)format, (int)dpi, 0); - return; - } - eax = dpi->y; - eax += dpi->height; - if (eax <= edx){ - //jmp 0x682B63 - RCT2_CALLPROC_X(0x00682702, colour, 0, x, y, (int)format, (int)dpi, 0); - return; - } - eax = *((uint8*)esi); - esi++; - if (!eax)return; - if ((uint32)eax < 0x9c){ - if((uint32)eax >= 0x8e){ - //jmp 0x682a2d - RCT2_CALLPROC_X(0x00682702, colour, 0, x, y, (int)format, (int)dpi, 0); + if (y + 0x5A <= dpi->y) { return; } - } - eax -= 0x20; - if (eax<0){ - //jmp 0x6828f5 - RCT2_CALLPROC_X(0x00682702, colour, 0, x, y, (int)format, (int)dpi, 0); - return; - } - ebx = dpi->x; - ebx += dpi->width; - if (ecx>=ebx){ - //jmp 0x682b63 - RCT2_CALLPROC_X(0x00682702, colour, 0, x, y, (int)format, (int)dpi, 0); - return; - } - ebx = ecx; - ebx += 0x1a; - if (ebxx){ - //jmp 0x6828e0 - RCT2_CALLPROC_X(0x00682702, colour, 0, x, y, (int)format, (int)dpi, 0); - return; - } - - ebx = eax; - ebx += RCT2_GLOBAL(0x13CE950,uint16); - eax = *((uint32*)(ebx+0x141E9e8)); - ebx += 0xf15; - RCT2_GLOBAL(0xEDF81C,uint32) = 0x20000000; - gfx_draw_sprite_palette_set(dpi, ebx, ecx, edx, RCT2_GLOBAL(0x9ABDA4, uint8*), RCT2_GLOBAL(0x9E3CDC, uint8*)); - - //0x68288a - RCT2_CALLPROC_X(0x00682702, colour, 0, x, y, (int)format, (int)dpi, 0); - return; + if (colour != 0xFF) { + + // switch_colour: + *current_font_flags = 0; + if (*current_font_sprite_base < 0) { + *current_font_flags |= 4; + if (*current_font_sprite_base != 0xFFFF) { + *current_font_flags |= 8; + } + *current_font_sprite_base = 0xE0; + } + if (colour & (1 << 5)) { + *current_font_flags |= 2; + } + colour &= ~(1 << 5); + + if (!(colour & 0x40)) { + ebp = colour; + if (*current_font_flags & 1) { + if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) { + skip_char = 1; + } else { + skip_char = 0; + } + } else { + sub_682AC7(ebp, current_font_flags); + } + } else { + *current_font_flags |= 1; + colour &= 0x1F; + + if (*current_font_flags & 4) { + if (*current_font_flags & 8) { + eax = RCT2_ADDRESS(0x0141FC48, uint8)[colour * 8]; + eax = eax << 10; + eax = eax | RCT2_ADDRESS(0x0141FC46, uint8)[colour * 8]; + } else { + eax = RCT2_ADDRESS(0x0141FC49, uint8)[colour * 8]; + eax = eax << 10; + eax = eax | RCT2_ADDRESS(0x0141FC47, uint8)[colour * 8]; + } + } else { + eax = RCT2_ADDRESS(0x0141FC4A, uint8)[colour * 8]; + eax = eax << 10; + eax = eax | RCT2_ADDRESS(0x0141FC48, uint8)[colour * 8]; + } + // Store current colour? ; + RCT2_GLOBAL(0x009ABE05, uint32) = eax; + RCT2_GLOBAL(0x009ABDA4, uint32) = 0x009ABE04; + eax = 0; + } + } + } + + if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) { + skip_char = 1; + } + + for (uint8 al = *buffer; al > 0; ++buffer, al = *buffer) { + + // Skip to the next printing character + if (skip_char) { + if (al < 0x20) { + // Control codes + skip_char = 0; + } else if (al >= 0x8E && al < 0x9C) { + // Colour codes + al -= 0x8E; + if (*current_font_flags == 1) { + if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) { + skip_char = 1; + } else { + skip_char = 0; + } + continue; + } + colour_char(al, current_font_flags); + continue; + } else { + continue; + } + } + + if ((al >= 0x8E) && (al < 0x9C)){ + // Colour codes + al -= 0x8E; + if (*current_font_flags == 1) { + if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) { + skip_char = 1; + } else { + skip_char = 0; + } + continue; + } + colour_char(al, current_font_flags); + continue; + } else { + if (al < 0x20) { + // Control codes + al -= 0x20; + switch (al) { + case 0x0E5: + max_x = RCT2_GLOBAL(0x0EDF840, uint16); + max_y += 0x0A; + if (*current_font_sprite_base <= 0x0E) { + break; + } + max_y -= 4; + if (*current_font_sprite_base == 0x1C0) { + break; + } + max_y -= 0xFFF4; + break; + case 0x0E6: + max_x = RCT2_GLOBAL(0x0EDF840, uint16); + max_y += 5; + if (*current_font_sprite_base <= 0x0E) { + break; + } + max_y -= 2; + if (*current_font_sprite_base == 0x1C0) { + break; + } + max_y -= 0xFFFA; + break; + case 0x0E1: + al = *buffer; + buffer++; + max_x = RCT2_GLOBAL(0x0EDF840, uint16); + max_x += al; + break; + case 0x0F1: + eax = *((uint16*)buffer); + buffer += 2; + max_x = RCT2_GLOBAL(0x0EDF840, uint16); + max_x += (eax & 0xFF); + max_y = RCT2_GLOBAL(0x0EDF842, uint16); + max_y += (eax & 0xFF00) >> 8; + break; + case 0x0E7: + *current_font_sprite_base = 0x1C0; + break; + case 0x0E8: + *current_font_sprite_base = 0x2A0; + break; + case 0x0E9: + *current_font_sprite_base = 0xE0; + break; + case 0x0EA: + *current_font_sprite_base = 0; + break; + case 0x0EB: + *current_font_flags |= 2; + break; + case 0x0EC: + *current_font_flags &= 0x0FFFD; + break; + case 0x0ED: + ebp = RCT2_GLOBAL(0x0141F740, uint8); + if (*current_font_flags & 1) { + if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) { + skip_char = 1; + } else { + skip_char = 0; + } + break; + } + sub_682AC7(ebp, current_font_flags); + break; + case 0x0EE: + ebp = RCT2_GLOBAL(0x0141F741, uint8); + if (*current_font_flags & 1) { + if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) { + skip_char = 1; + } else { + skip_char = 0; + } + break; + } + sub_682AC7(ebp, current_font_flags); + break; + case 0x0EF: + ebp = RCT2_GLOBAL(0x0141F742, uint8); + if (*current_font_flags & 1) { + if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) { + skip_char = 1; + } else { + skip_char = 0; + } + break; + } + sub_682AC7(ebp, current_font_flags); + break; + case 0x0E2: + al = *buffer; + buffer++; + if (*current_font_flags & 1) { + if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) { + skip_char = 1; + break; + } + } + + eax = RCT2_ADDRESS(0x097FCBC, uint32)[al*4]; + g1_element = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[eax]); + ebx = g1_element->offset[0xF9] + (1 << 8); + + if (!(*current_font_flags & 2)) { + ebx = ebx & 0xFF; + } + RCT2_GLOBAL(0x09ABE05, uint16) = ebx; + ebx = g1_element->offset[0xF7]; + RCT2_GLOBAL(0x09ABE07, uint16) = ebx; + ebx = g1_element->offset[0xFA]; + RCT2_GLOBAL(0x09ABE09, uint16) = ebx; + + RCT2_GLOBAL(0x09ABDA4, uint32) = RCT2_GLOBAL(0x09ABE04, uint32); + if ((y + 0x13 <= dpi->y) || (dpi->y + dpi->height <= y)) { + skip_char = 1; + } + break; + case 0x0F7: + buffer += 4; + if (max_x >= dpi->x + dpi->width) { + skip_char = 1; + break; + } + ebx = *(buffer - 4); + eax = ebx & 0x7FFFF; + g1_element = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS + 4, rct_g1_element)[eax]); + + gfx_draw_sprite(dpi, ebx, max_x, max_y); + + max_x = max_x + g1_element->offset; + break; + } + + } else { + al -= 0x20; + if (max_x >= dpi->x + dpi->width) { + skip_char = 1; + } + if (max_x + 0x1A < dpi->x) { + ebx = al; + ebx += *current_font_sprite_base; + max_x = max_x + (RCT2_ADDRESS(0x0141E9E8, uint8)[ebx] & 0xFF); + continue; + } + ebx = al + *current_font_sprite_base; + + ecx = max_x; + + max_x = max_x + (RCT2_ADDRESS(0x0141E9E8, uint8)[ebx] & 0xFF); + + eax = (int)al; + ebx += 0xF15; + + edx = max_y; + esi = (int)buffer; + edi = (int)dpi; + ebp = 0; + + RCT2_GLOBAL(0x00EDF81C, uint32) = 0x20000000; + + RCT2_CALLPROC_X(0x067A46E, eax, ebx, ecx, edx, esi, edi, ebp); + + continue; + } + } + } + + gLastDrawStringX = max_x; + gLastDrawStringY = max_y; } diff --git a/src/gfx.h b/src/gfx.h index ad686e12d2..a627bffb72 100644 --- a/src/gfx.h +++ b/src/gfx.h @@ -31,7 +31,7 @@ typedef struct { short width; // 0x08 short height; // 0x0A short pitch; // 0x0C note: this is actually (pitch - width) - uint8 pad_0E; // 0x0E + uint8 zoom_level; // 0x0E char var_0F; // 0x0F } rct_drawpixelinfo; diff --git a/src/map.c b/src/map.c index 935f059ee0..5f157b1ab7 100644 --- a/src/map.c +++ b/src/map.c @@ -328,4 +328,40 @@ void sub_68B089() } while (mapElement->base_height == 255); mapElement++; RCT2_GLOBAL(0x0140E9A4, rct_map_element*) = mapElement; -} \ No newline at end of file +} + + +/** + * Checks if the tile at coordinate at height counts as connected. + * @return 1 if connected, 0 otherwisei + */ +int map_coord_is_connected(uint16 tile_idx, uint8 height, uint8 face_direction) +{ + rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; + + do { + rct_map_element_path_properties props = tile->properties.path; + uint8 path_type = props.type >> 2, path_dir = props.type & 3; + uint8 element_type = tile->type & MAP_ELEMENT_TYPE_MASK; + + if (element_type != PATH_ROAD) + continue; + + if (path_type & 1) { + if (path_dir == face_direction) { + if (height == tile->base_height + 2) + return 1; + } + else if ((path_dir ^ 2) == face_direction && height == tile->base_height) { + return 1; + } + } else { + if (height == tile->base_height) + return 1; + } + + } while (!(tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) && tile++); + + return 0; +} + diff --git a/src/map.h b/src/map.h index 355767bc81..069c0d52c9 100644 --- a/src/map.h +++ b/src/map.h @@ -195,5 +195,7 @@ void map_init(); void map_update_tile_pointers(); int map_element_height(int x, int y); void sub_68B089(); +int map_coord_is_connected(uint16 coordinate, uint8 height, uint8 face_direction); + #endif diff --git a/src/park.c b/src/park.c index e007cb335c..e897bf3eb4 100644 --- a/src/park.c +++ b/src/park.c @@ -104,7 +104,9 @@ void park_init() RCT2_GLOBAL(0x01358772, uint16) = 400; RCT2_GLOBAL(0x01358774, uint16) = 0; RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) = PARK_FLAGS_11 | PARK_FLAGS_SHOW_REAL_GUEST_NAMES; - park_reset_awards_and_history(); + park_reset_history(); + finance_reset_history(); + award_reset(); rct_s6_info *info = (rct_s6_info*)0x0141F570; info->name[0] = '\0'; @@ -115,26 +117,13 @@ void park_init() * * rct2: 0x0066729F */ -void park_reset_awards_and_history() +void park_reset_history() { int i; - - // Reset park rating and guests in park history for (i = 0; i < 32; i++) { RCT2_ADDRESS(RCT2_ADDRESS_PARK_RATING_HISTORY, uint8)[i] = 255; RCT2_ADDRESS(RCT2_ADDRESS_GUESTS_IN_PARK_HISTORY, uint8)[i] = 255; } - - // Reset finance history - for (i = 0; i < 128; i++) { - RCT2_ADDRESS(RCT2_ADDRESS_BALANCE_HISTORY, money32)[i] = MONEY32_UNDEFINED; - RCT2_ADDRESS(RCT2_ADDRESS_WEEKLY_PROFIT_HISTORY, money32)[i] = MONEY32_UNDEFINED; - RCT2_ADDRESS(RCT2_ADDRESS_PARK_VALUE_HISTORY, money32)[i] = MONEY32_UNDEFINED; - } - - // Reset awards - for (i = 0; i < 4; i++) - RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award)[i].time = 0; } /** diff --git a/src/park.h b/src/park.h index 8908e4a31f..12808a50c3 100644 --- a/src/park.h +++ b/src/park.h @@ -45,7 +45,7 @@ enum { int park_is_open(); void park_init(); -void park_reset_awards_and_history(); +void park_reset_history(); int park_calculate_size(); int calculate_park_rating(); diff --git a/src/peep.c b/src/peep.c index cde8015f4e..7042c04c5d 100644 --- a/src/peep.c +++ b/src/peep.c @@ -28,6 +28,8 @@ #include "sprite.h" #include "window.h" +static void peep_update(rct_peep *peep); + int peep_get_staff_count() { uint16 spriteIndex; @@ -60,17 +62,94 @@ void peep_update_all() spriteIndex = peep->next; if ((i & 0x7F) != (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x7F)) { - RCT2_CALLPROC_X(0x0068FC1E, 0, 0, 0, 0, (int)peep, 0, 0); + peep_update(peep); } else { RCT2_CALLPROC_X(0x0068F41A, 0, 0, 0, i, (int)peep, 0, 0); if (peep->var_08 == 4) - RCT2_CALLPROC_X(0x0068FC1E, 0, 0, 0, 0, (int)peep, 0, 0); + peep_update(peep); } i++; } } +/** + * + * rct2: 0x0068FC1E + */ +static void peep_update(rct_peep *peep) +{ + // RCT2_CALLPROC_X(0x0068FC1E, 0, 0, 0, 0, (int)peep, 0, 0); return; + + int i, j; + + if (peep->type == PEEP_TYPE_GUEST) { + if (peep->var_AD != 255) + if (++peep->var_AE < 720) + peep->var_AD = 255; + + // Update thoughts + i = 0; + int ebp = 0; + int edi = -1; + for (i = 0; i < PEEP_MAX_THOUGHTS; i++) { + if (peep->thoughts[i].type == PEEP_THOUGHT_TYPE_NONE) + break; + + if (peep->thoughts[i].var_2 == 1) { + ebp++; + if (++peep->thoughts[i].var_3 >= 220) { + peep->thoughts[i].var_3 = 0; + peep->thoughts[i].var_2++; + ebp--; + } + } else if (peep->thoughts[i].var_2 >= 0) { + if (++peep->thoughts[i].var_3 > 255) { + if (++peep->thoughts[i].var_3 >= 28) { + peep->var_45 |= 1; + + // Clear top thought, push others up + for (j = i; j < PEEP_MAX_THOUGHTS - 1; j++) + peep->thoughts[j].type = peep->thoughts[j + 1].type; + peep->thoughts[PEEP_MAX_THOUGHTS - 1].type = PEEP_THOUGHT_TYPE_NONE; + } + } + } else { + edi = i; + } + } + if (ebp == 0 && edi != -1) { + peep->thoughts[edi].var_2 = 1; + peep->var_45 |= 1; + } + } + + // Walking speed logic + unsigned int stepsToTake = peep->energy; + if (stepsToTake < 95 && peep->state == PEEP_STATE_QUEUING) + stepsToTake = 95; + if ((peep->flags & PEEP_FLAGS_SLOW_WALK) && peep->state != PEEP_STATE_QUEUING) + stepsToTake /= 2; + if (peep->var_71 == 255 && (RCT2_GLOBAL((int)peep + 0x29, uint8) & 4)) { + stepsToTake /= 2; + if (peep->state == PEEP_STATE_QUEUING) + stepsToTake += stepsToTake / 2; + } + + unsigned int carryCheck = peep->var_73 + stepsToTake; + peep->var_73 = carryCheck; + if (carryCheck <= 255) { + // loc_68FD3A + RCT2_CALLPROC_X(0x0068FD3A, 0, 0, 0, 0, (int)peep, 0, 0); + } else { + // loc_68FD2F + RCT2_CALLPROC_X(0x0068FD2F, 0, 0, 0, 0, (int)peep, 0, 0); + switch (peep->state) { + + } + } +} + /** * @@ -89,7 +168,7 @@ void peep_problem_warnings_update() RCT2_GLOBAL(RCT2_ADDRESS_RIDE_COUNT, sint16) = ride_get_count(); // refactor this to somewhere else FOR_ALL_GUESTS(spriteIndex, peep) { - if (peep->var_2A != 0 || peep->thoughts[0].pad_3 > 5) + if (peep->var_2A != 0 || peep->thoughts[0].var_2 > 5) continue; switch (peep->thoughts[0].type) { diff --git a/src/peep.h b/src/peep.h index 2bac8ed735..74dfd3f6b8 100644 --- a/src/peep.h +++ b/src/peep.h @@ -307,8 +307,8 @@ enum PEEP_ITEM { typedef struct { uint8 type; uint8 item; - uint8 pad_3; - uint8 pad_4; + uint8 var_2; + uint8 var_3; } rct_peep_thought; typedef struct { @@ -376,7 +376,8 @@ typedef struct { uint8 var_70; uint8 var_71; uint8 var_72; - uint8 pad_73[3]; + uint8 var_73; + uint16 pad_74; uint8 var_76; uint8 pad_77; uint8 var_78; @@ -387,7 +388,8 @@ typedef struct { money32 cash_spent; // 0xA4 uint8 pad_A8; sint32 time_in_park; // 0xA9 - uint8 pad_AD[0x3]; + uint8 var_AD; + uint16 var_AE; rct_peep_thought thoughts[PEEP_MAX_THOUGHTS]; // 0xB0 uint8 pad_C4; uint8 var_C5; diff --git a/src/ride.c b/src/ride.c index 56149ba2a9..c7746e91f9 100644 --- a/src/ride.c +++ b/src/ride.c @@ -20,6 +20,9 @@ #include #include "addresses.h" +#include "map.h" +#include "news_item.h" +#include "sprite.h" #include "ride.h" #include "sprite.h" #include "peep.h" @@ -191,3 +194,152 @@ void ride_update_favourited_stat() window_invalidate_by_id(WC_RIDE_LIST, 0); } + + + +/** + * rct2: 0x006B7C59 + * @return 1 if the coordinate is reachable or has no entrance, 0 otw + */ +int ride_entrance_exit_is_reachable(uint16 coordinate, rct_ride* ride, int index) { + int x = ((coordinate >> 8) & 0xFF) << 5, // cx + y = (coordinate & 0xFF) << 5; // ax + uint8 station_height = ride->station_heights[index]; + int tile_idx = ((x << 8) | y) >> 5; + rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; + + while(1) { + uint8 element_type = tile->type & MAP_ELEMENT_TYPE_MASK; + if (element_type == MAP_ELEMENT_TYPE_ENTRANCE && station_height == tile->base_height) { + break; + } else if (tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) { + return 1; + } + tile++; + } + + uint8 face_direction = tile->type & 3; + y -= RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2]; + x -= RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2]; + tile_idx = ((x << 8) | y) >> 5; + + return map_coord_is_connected(tile_idx, station_height, face_direction); +} + + +void ride_entrance_exit_connected(rct_ride* ride, int ride_idx) +{ + for (int i = 0; i < 4; ++i) { + uint16 station_start = ride->station_starts[i], + entrance = ride->entrances[i], + exit = ride->exits[i]; + + if (station_start == -1 ) + continue; + if (entrance != -1 && !ride_entrance_exit_is_reachable(entrance, ride, i)) { + // name of ride is parameter of the format string + RCT2_GLOBAL(0x013CE952, uint16) = ride->var_04A; + RCT2_GLOBAL(0x013CE954, uint32) = ride->var_04C; + news_item_add_to_queue(1, STR_ENTRANCE_NOT_CONNECTED, ride_idx); + ride->connected_message_throttle = 3; + } + + if (exit != -1 && !ride_entrance_exit_is_reachable(exit, ride, i)) { + // name of ride is parameter of the format string + RCT2_GLOBAL(0x013CE952, uint16) = ride->var_04A; + RCT2_GLOBAL(0x013CE954, uint32) = ride->var_04C; + news_item_add_to_queue(1, STR_EXIT_NOT_CONNECTED, ride_idx); + ride->connected_message_throttle = 3; + } + + } +} + + +void ride_shop_connected(rct_ride* ride, int ride_idx) +{ + uint16 coordinate = ride->station_starts[0]; + if (coordinate == 0xFFFF) + return; + + int x = ((coordinate >> 8) & 0xFF) << 5, // cx + y = (coordinate & 0xFF) << 5; // ax + uint16 entrance_directions = 0; + int tile_idx = ((x << 8) | y) >> 5, count = 0; + rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; + + + while (1) { + uint8 element_type = tile->type & MAP_ELEMENT_TYPE_MASK; + if(element_type == MAP_ELEMENT_TYPE_TRACK && tile->properties.track.ride_index == ride_idx) + break; + + if(tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) + return; + tile++; + } + + uint8 track_type = tile->properties.track.type; + ride = GET_RIDE(tile->properties.track.ride_index); + if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x80000) { + entrance_directions = RCT2_ADDRESS(0x0099CA64, uint8)[track_type * 16]; + } else { + entrance_directions = RCT2_ADDRESS(0x0099BA64, uint8)[track_type * 16]; + } + + + uint8 tile_direction = tile->type & MAP_ELEMENT_DIRECTION_MASK; + entrance_directions <<= tile_direction; + entrance_directions = ((entrance_directions >> 12) | entrance_directions) & 0xF; + + // now each bit in entrance_directions stands for an entrance direction to check + if (entrance_directions == 0) + return; + + for (int count = 0; entrance_directions != 0; ++count) { + if (!(entrance_directions & 1)) { + entrance_directions >>= 1; + continue; + } + entrance_directions >>= 1; + + uint8 face_direction = count ^ 2; // flip direction north<->south, east<->west + y -= RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2]; + x -= RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2]; + tile_idx = ((x << 8) | y) >> 5; + + if (map_coord_is_connected(tile_idx, tile->base_height, face_direction)) + return; + } + + // name of ride is parameter of the format string + RCT2_GLOBAL(0x013CE952, uint16) = ride->var_04A; + RCT2_GLOBAL(0x013CE954, uint32) = ride->var_04C; + news_item_add_to_queue(1, STR_ENTRANCE_NOT_CONNECTED, ride_idx); + + ride->connected_message_throttle = 3; +} + + + +/** + * rct2: 0x006B7A5E + **/ +void ride_check_all_reachable() +{ + rct_ride *ride; + int i; + + FOR_ALL_RIDES(i, ride) { + if (ride->connected_message_throttle != 0) + ride->connected_message_throttle--; + if (ride->status != RIDE_STATUS_OPEN || ride->connected_message_throttle != 0) + continue; + + if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x20000) + ride_shop_connected(ride, i); + else + ride_entrance_exit_connected(ride, i); + } +} + diff --git a/src/ride.h b/src/ride.h index 9d53d72864..bcbc0c86dd 100644 --- a/src/ride.h +++ b/src/ride.h @@ -56,7 +56,8 @@ typedef struct { uint32 var_04C; uint16 overall_view; // 0x050 uint16 station_starts[4]; // 0x052 - uint8 pad_05A[0x10]; + uint8 station_heights[4]; // 0x05A + uint8 pad_05E[0xC]; uint16 entrances[4]; // 0x06A uint16 exits[4]; // 0x072 uint8 pad_07A[0x0C]; @@ -111,8 +112,9 @@ typedef struct { uint8 var_199; uint8 pad_19A[0x14]; uint8 var_1AE; - uint8 pad_1AF[0x05]; - money32 profit; // 0x1B4 + uint8 connected_message_throttle; + uint32 pad_1B0; + sint32 profit; // 0x1B4 uint8 queue_time[4]; // 0x1B8 uint8 var_1BC; uint8 pad_1BD[0x10]; @@ -343,5 +345,6 @@ int ride_get_max_queue_time(rct_ride *ride); void ride_init_all(); void reset_all_ride_build_dates(); void ride_update_favourited_stat(); +void ride_check_all_reachable(); #endif diff --git a/src/scenario.c b/src/scenario.c index dbdd382f1e..6dc29fa1bf 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -279,7 +279,9 @@ void scenario_load_and_play(const rct_scenario_basic *scenario) RCT2_GLOBAL(RCT2_ADDRESS_INCOME_FROM_ADMISSIONS, uint32) = 0; RCT2_GLOBAL(0x013587D8, uint16) = 63; sub_69E869(); // (loan related, called above already) - park_reset_awards_and_history(); + park_reset_history(); + finance_reset_history(); + award_reset(); reset_all_ride_build_dates(); date_reset(); RCT2_CALLPROC_EBPSAFE(0x00674576); @@ -590,7 +592,7 @@ void scenario_update() finance_pay_interest(); marketing_update(); peep_problem_warnings_update(); - RCT2_CALLPROC_EBPSAFE(0x006B7A5E); // check ride reachability + ride_check_all_reachable(); ride_update_favourited_stat(); if (month <= 1 && RCT2_GLOBAL(0x009ADAE0, sint32) != -1 && RCT2_GLOBAL(0x009ADAE0 + 14, uint16) & 1) { diff --git a/src/scenario.h b/src/scenario.h index cb3822c147..4ab1e2d2b2 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -83,6 +83,283 @@ typedef struct { char completed_by[64]; // 0x0270 } rct_scenario_basic; +/* This will be useful for backwards compatibility +typedef struct { + // SC6[0] + rct_s6_header header; + + // SC6[1] + rct_s6_info info; + + // SC6[2] + // packed objects + + // SC6[3] + rct_object_entry objects[721]; + + // SC6[4] + uint16 elapsed_months; + uint16 current_day; + uint32 dword_F663AC; + uint32 scenario_srand_0; + uint32 scenario_srand_1; + + // SC6[5] + rct_map_element map_elements[0x30000]; + + // SC6[6] + uint32 dword_010E63B8; + rct_sprite sprites[10000]; + uint16 sprites_next_index; + uint16 sprites_start_vehicle; + uint16 sprites_start_peep; + uint16 sprites_start_textfx; + uint16 sprites_start_litter; + uint8 pad_013573C6[2]; + uint16 word_013573C8; + uint8 pad_013573CA[4]; + uint16 word_013573CE; + uint16 word_013573D0; + uint8 pad_013573D2[2]; + uint16 word_013573D4; + uint8 pad_013573D6[4]; + uint32 dword_013573D8; + uint32 dword_013573DC; + money32 current_loan; + uint32 park_flags; + money16 park_entrance_fee; + uint16 word_013573EA; + uint16 word_013573EC; + uint8 pad_013573EE[16]; + uint8 byte_013573F0; + uint8 pad_013573F1[2]; + rct2_peep_spawn peep_spawns[2]; + uint8 guest_count_change_modifier; + uint8 byte_013573FF; + uint8 pad_01357400[4]; + uint32 dword_01357404; + uint32 dword_01357408; + uint32 dword_0135740C; + uint32 dword_01357410[5]; + uint32 dword_01357424[8]; + uint32 dword_01357444[128]; + uint32 dword_01357644[128]; + + // SC6[7] + uint16 guests_in_park; + uint16 guests_heading_for_park; + + // Ignored in scenario + money32 expenditure_table[14]; + uint32 dword_01357880[5]; + uint32 dword_01357894; + uint32 dword_01357898; + uint32 dword_0135789C; + uint32 dword_013578A0; + uint32 dword_013578A4[201]; + + // SC6[8] + uint16 last_guests_in_park; + uint8 pad_01357BCA[3]; + uint8 handyman_colour; + uint8 mechanic_colour; + uint8 security_colour; + + // Ignored in scenario + uint32 dword_01357BD0[56]; + + // SC6[9] + uint16 park_rating; + + // Ignored in scenario + uint8 park_rating_history[32]; + uint8 guests_in_park_history[32]; + + // SC6[10] + uint16 word_01357CF2; + uint32 word_01357CF4; + uint8 byte_01357CF8[1000]; + uint32 dword_013580E0[32]; + uint16 word_013580E4[16]; + uint8 byte_013580E6; + uint8 byte_013580E7; + uint8 byte_013580E8; + uint8 byte_013580E9; + uint16 park_size; + uint16 guest_generation_probability; + uint16 total_ride_value; + uint32 dword_013580F0; + uint16 dword_013580F4; + uint8 dword_013580F6; + uint8 dword_013580F7; + uint8 objective_type; + uint8 objective_year; + uint8 pad_013580FA[4]; + money32 objective_currency; + uint16 objective_guests; + uint8 campaign_weeks_left[20]; + uint8 campaign_ride_index[22]; + + // Ignored in scenario + money32 balance_history[128]; + + // SC6[11] + uint32 dword_0135832C; + uint32 current_profit; + uint32 dword_01358334; + uint16 word_01358338; + uint8 pad_0135833A[2]; + + // Ignored in scenario + uint8 pad_0135833C[2]; + money32 park_value; + money32 park_value_history[128]; + + // SC6[12] + money32 completed_company_value; + uint32 total_admissions; + money32 income_from_admissions; + money32 company_value; + uint8 byte_01358750[16]; + rct_award awards[4]; + uint16 word_01358770; + uint16 word_01358772; + uint16 word_01358774; + uint8 pad_01358776[4]; + uint32 dword_01358778[17]; + uint32 dword_013587BC; + uint32 dword_013587C0; + uint32 dword_013587C4; + uint16 dword_013587C8; + uint8 pad_013587CA[16]; + uint32 dword_013587D0; + uint8 pad_013587D4[8]; + uint16 word_013587D8[16]; + money32 cash; + uint8 pad_013587FC[50]; + uint16 word_0135882E; + uint16 word_01358830; + uint16 word_01358832; + uint16 map_size; + uint16 word_01358836; + uint32 word_01358838; + uint16 suggested_max_guests; + uint16 word_0135883E; + uint8 word_01358840; + uint8 word_01358841; + uint8 pad_01358842[4]; + uint32 dword_01358844; + uint8 pad_01358848; + uint32 dword_01358849; + uint8 pad_0135884D[2]; + uint8 dword_0135884E[622]; + uint8 pad_01359206[2]; + uint16 word_01359208; + char scenario_name[64]; + char scenario_description[255]; + uint8 byte_01359349; + uint8 byte_0135934A; + uint8 pad_0135934B[3]; + uint32 dword_0135934C; + uint16 park_entrance_x[4]; + uint16 park_entrance_y[4]; + uint16 park_entrance_z[4]; + uint8 byte_01359368; + uint8 pad_01359369[3]; + uint8 byte_0135936C[256]; + uint8 byte_0135946C[3256]; + uint8 byte_0135A124; + uint8 byte_0135A125; + uint16 word_0135A126; + uint8 byte_0135A128; + uint8 byte_0135A129; + uint8 byte_0135A12A; + uint8 byte_0135A12B[793]; + uint8 byte_0135A444[1200]; + char custom_strings[0x8000]; + uint32 game_ticks_1; + rct_ride rides[255]; + uint16 word_01388698; + uint16 saved_view_x; + uint16 saved_view_y; + uint16 saved_view_zoom_and_rotation; + uint8 byte_013886A0[6000]; + uint8 byte_01389E10[6000]; + uint16 word_0138B580; + uint8 pad_0138B580[2]; + uint16 word_0138B584; + uint16 word_0138B586; + uint16 word_0138B588; + uint16 word_0138B58A; + uint16 word_0138B58C; + uint16 word_0138B58E; + uint8 byte_0138B590; + uint8 byte_0138B591; + uint8 byte_0138B592; + uint8 byte_0138B593; + uint16 word_0138B594; + uint16 word_0138B596; + uint16 word_0138B598; + uint16 word_0138B59A; + uint16 word_0138B59C; + uint16 word_0138B59E; + uint16 word_0138B5A0; + uint16 word_0138B5A2; + uint16 word_0138B5A4; + uint16 word_0138B5A6; + uint16 word_0138B5A8; + uint16 word_0138B5AA; + uint16 word_0138B5AC; + uint16 word_0138B5AE; + uint16 word_0138B5B0; + uint16 word_0138B5B2; + uint16 word_0138B5B4; + uint16 word_0138B5B6; + uint16 word_0138B5B8; + uint16 word_0138B5BA; + uint16 word_0138B5BC; + uint16 word_0138B5BE; + uint16 word_0138B5C0; + uint16 word_0138B5C2; + uint16 word_0138B5C4; + uint16 word_0138B5C6; + uint16 word_0138B5C8; + uint16 word_0138B5CA; + uint16 word_0138B5CC; + uint16 word_0138B5CE[31]; + uint8 ride_measurements[0x25860]; + uint32 dword_13B0E6C; + uint16 word_13B0E70; + uint32 dword_13B0E72[0x6600]; + uint8 byte_13CA672[116]; + uint8 byte_13CA6E6[84]; + uint8 byte_13CA73A[4]; + uint8 unk_13CA73E; + uint8 pad_13CA73E; + uint8 byte_13CA740; + uint8 byte_13CA741; + uint8 byte_13CA7424[4]; + uint8 climate; + uint8 pad_013CA747; + uint16 climate_update_timer; + uint8 current_weather; + uint8 next_weather; + uint8 temperature; + uint8 next_temperature; + uint8 current_weather_effect; + uint8 next_weather_effect; + uint8 current_weather_gloom; + uint8 next_weather_gloom; + uint8 current_rain_level; + uint8 next_rain_level; + rct_news_item news_items[61]; + uint8 byte_13CE730[64]; + uint32 dword_13CE770; + uint16 word_13CE774; + uint16 word_13CE776[217]; +} rct_s6_data; +*/ + enum { SCENARIO_FLAGS_VISIBLE = (1 << 0), SCENARIO_FLAGS_COMPLETED = (1 << 1), diff --git a/src/string_ids.c b/src/string_ids.c index e18f7e6bc8..2ce1f8085e 100644 --- a/src/string_ids.c +++ b/src/string_ids.c @@ -1085,12 +1085,16 @@ void format_integer(char **dest, int value) *dest = dst; - // Right to left - while (value > 0) { - digit = value % 10; - value /= 10; + if (value == 0) { + *dst++ = '0'; + } else { + // Right to left + while (value > 0) { + digit = value % 10; + value /= 10; - *dst++ = '0' + digit; + *dst++ = '0' + digit; + } } finish = dst; @@ -1121,20 +1125,24 @@ void format_comma_separated_integer(char **dest, int value) *dest = dst; - // Groups of three digits, right to left - groupIndex = 0; - while (value > 0) { - // Append group seperator - if (groupIndex == 3) { - groupIndex = 0; - *dst++ = ','; + if (value == 0) { + *dst++ = '0'; + } else { + // Groups of three digits, right to left + groupIndex = 0; + while (value > 0) { + // Append group seperator + if (groupIndex == 3) { + groupIndex = 0; + *dst++ = ','; + } + + digit = value % 10; + value /= 10; + + *dst++ = '0' + digit; + groupIndex++; } - - digit = value % 10; - value /= 10; - - *dst++ = '0' + digit; - groupIndex++; } finish = dst; @@ -1225,20 +1233,25 @@ void format_currency(char **dest, int value) *dest = dst; - // Groups of three digits, right to left - groupIndex = 0; - while (value > 0) { - // Append group seperator - if (groupIndex == 3) { - groupIndex = 0; - *dst++ = ','; + value /= 10; + if (value == 0) { + *dst++ = '0'; + } else { + // Groups of three digits, right to left + groupIndex = 0; + while (value > 0) { + // Append group seperator + if (groupIndex == 3) { + groupIndex = 0; + *dst++ = ','; + } + + digit = value % 10; + value /= 10; + + *dst++ = '0' + digit; + groupIndex++; } - - digit = value % 10; - value /= 10; - - *dst++ = '0' + digit; - groupIndex++; } finish = dst; @@ -1273,9 +1286,7 @@ void format_currency_2dp(char **dest, int value) *dest = dst; // Two decimal places - digit = value % 10; - value /= 10; - *dst++ = '0' + digit; + *dst++ = '0'; digit = value % 10; value /= 10; *dst++ = '0' + digit; @@ -1375,6 +1386,7 @@ void format_string_code(unsigned char format_code, char **dest, char **args) *args += 2; format_string_part(dest, value, args); + (*dest)--; break; case FORMAT_STRING: // Pop argument @@ -1389,11 +1401,12 @@ void format_string_code(unsigned char format_code, char **dest, char **args) value = *((uint16*)*args); *args += 2; - uint16 dateArgs[] = { date_get_year(value), date_get_month(value) }; + uint16 dateArgs[] = { date_get_month(value), date_get_year(value) + 1 }; + uint16 *dateArgs2 = dateArgs; char formatString[] = "?, Year ?"; formatString[0] = FORMAT_MONTH; formatString[8] = FORMAT_COMMA16; - format_string_part_from_raw(dest, formatString, (char**)&dateArgs); + format_string_part_from_raw(dest, formatString, (char**)&dateArgs2); break; case FORMAT_MONTH: // Pop argument @@ -1525,6 +1538,7 @@ void format_string_part(char **dest, rct_string_id format, char **args) // args += (format & 0xC00) >> 9; format &= ~0xC00; strcpy(*dest, RCT2_ADDRESS(0x135A8F4 + (format * 32), char)); + *dest = strchr(*dest, 0) + 1; } else if (format < 0xE000) { // Real name format -= -0xA000; @@ -1532,6 +1546,7 @@ void format_string_part(char **dest, rct_string_id format, char **args) real_names[format % countof(real_names)], real_name_initials[(format >> 10) % countof(real_name_initials)] ); + *dest = strchr(*dest, 0) + 1; } else { // ? RCT2_CALLPROC_EBPSAFE(RCT2_ADDRESS(0x0095AFB8, uint32)[format]); diff --git a/src/string_ids.h b/src/string_ids.h index 6812f33eeb..5db27533b3 100644 --- a/src/string_ids.h +++ b/src/string_ids.h @@ -567,6 +567,9 @@ enum { STR_NO_RECENT_AWARDS = 2848, + STR_ENTRANCE_NOT_CONNECTED = 2854, + STR_EXIT_NOT_CONNECTED = 2855, + STR_TUTORIAL = 2856, STR_PRESS_KEY_OR_MOUSE_BUTTON_FOR_CONTROL = 2857, diff --git a/src/window_banner.c b/src/window_banner.c index 10564eb994..7b27b8fbe2 100644 --- a/src/window_banner.c +++ b/src/window_banner.c @@ -55,7 +55,7 @@ rct_widget window_banner_widgets[] = { static void window_banner_emptysub() { } static void window_banner_mouseup(); -static void window_banner_mousedown(); +static void window_banner_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_banner_dropdown(); static void window_banner_textinput(); static void window_banner_invalidate(); @@ -182,14 +182,14 @@ static void window_banner_mouseup() } } -static void window_banner_mousedown() +static void window_banner_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { - short widgetIndex; + //short widgetIndex; #ifdef _MSC_VER - __asm mov widgetIndex, dx + //__asm mov widgetIndex, dx #else - __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); +// __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); #endif diff --git a/src/window_footpath.c b/src/window_footpath.c index 0b764ec02f..ab2b8c979a 100644 --- a/src/window_footpath.c +++ b/src/window_footpath.c @@ -111,7 +111,7 @@ static rct_widget window_footpath_widgets[] = { static void window_footpath_emptysub() { } static void window_footpath_close(); static void window_footpath_mouseup(); -static void window_footpath_mousedown(); +static void window_footpath_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_footpath_dropdown(); static void window_footpath_update(rct_window *w); static void window_footpath_toolupdate(); @@ -307,31 +307,8 @@ static void window_footpath_mouseup() * * rct2: 0x006A7EC5 */ -static void window_footpath_mousedown() +static void window_footpath_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { - short widgetIndex; - rct_window *w; - rct_widget *widget; - - #ifdef _MSC_VER - __asm mov widgetIndex, dx - #else - __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); - #endif - - #ifdef _MSC_VER - __asm mov w, esi - #else - __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); - #endif - - #ifdef _MSC_VER - __asm mov widget, edi - #else - __asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) ); - #endif - - switch (widgetIndex) { case WIDX_FOOTPATH_TYPE: window_footpath_show_footpath_types_dialog(w, widget, 0); diff --git a/src/window_game_top_toolbar.c b/src/window_game_top_toolbar.c index 5346a67b6f..8a78975390 100644 --- a/src/window_game_top_toolbar.c +++ b/src/window_game_top_toolbar.c @@ -78,7 +78,7 @@ static rct_widget window_game_top_toolbar_widgets[] = { static void window_game_top_toolbar_emptysub() { } static void window_game_top_toolbar_mouseup(); -static void window_game_top_toolbar_mousedown(); +static void window_game_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_game_top_toolbar_dropdown(); static void window_game_top_toolbar_invalidate(); static void window_game_top_toolbar_paint(); @@ -166,6 +166,11 @@ static void window_game_top_toolbar_mouseup() game_do_command(0, 1, 0, 0, 2, 0, 0); break; case WIDX_FASTFORWARD: + // This is an excellent place to add in debugging statements and + // print routines, that will be triggered when you press the + // button in the game. Use "git update-index --skip-worktree + // src/window_game_top_toolbar" to avoid committing these changes to + // version control. window_cheats_open(); break; @@ -254,32 +259,10 @@ static void window_game_top_toolbar_mouseup() * * rct2: 0x0066CA3B */ -static void window_game_top_toolbar_mousedown() +static void window_game_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { - short widgetIndex; - rct_window *w; - rct_widget *widget; rct_viewport *mainViewport; - #ifdef _MSC_VER - __asm mov widgetIndex, dx - #else - __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); - #endif - - #ifdef _MSC_VER - __asm mov w, esi - #else - __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); - #endif - - #ifdef _MSC_VER - __asm mov widget, edi - #else - __asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) ); - #endif - - if (widgetIndex == WIDX_FILE_MENU) { gDropdownItemsFormat[0] = 882; gDropdownItemsFormat[1] = 883; @@ -384,30 +367,7 @@ static void window_game_top_toolbar_dropdown() break; case 1: // save game tool_cancel(); - { - int eax, ebx, ecx, edx, esi, edi, ebp; - RCT2_CALLFUNC_X(0x006750E9, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - if (eax == 0) { - gfx_invalidate_screen(); - break; - } - - char *src = (char*)0x0141EF67; - do { - src++; - } while (*src != '.' && *src != '\0'); - strcpy(src, ".SV6"); - strcpy((char*) RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*) 0x0141EF68); - - eax = 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & 8) - eax |= 1; - RCT2_CALLPROC_X(0x006754F5, eax, 0, 0, 0, 0, 0, 0); - // check success? - - game_do_command(0, 1047, 0, -1, 0, 0, 0); - gfx_invalidate_screen(); - } + save_game(); break; case 3: // about window_about_open(); diff --git a/src/window_guest_list.c b/src/window_guest_list.c index 95284c0b88..14fe8d13a7 100644 --- a/src/window_guest_list.c +++ b/src/window_guest_list.c @@ -73,7 +73,7 @@ static rct_widget window_guest_list_widgets[] = { static void window_guest_list_emptysub() { } static void window_guest_list_mouseup(); static void window_guest_list_resize(); -static void window_guest_list_mousedown(); +static void window_guest_list_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_guest_list_dropdown(); static void window_guest_list_update(rct_window *w); static void window_guest_list_scrollgetsize(); @@ -241,32 +241,9 @@ static void window_guest_list_resize() * * rct2: 0x00699AC4 */ -static void window_guest_list_mousedown() +static void window_guest_list_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { int i; - short widgetIndex; - rct_window *w; - rct_widget *widget; - - #ifdef _MSC_VER - __asm mov widgetIndex, dx - #else - __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); - #endif - - #ifdef _MSC_VER - __asm mov w, esi - #else - __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); - #endif - - #ifdef _MSC_VER - __asm mov widget, edi - #else - __asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) ); - #endif - - switch (widgetIndex) { case WIDX_TAB_1: case WIDX_TAB_2: @@ -754,9 +731,9 @@ static void window_guest_list_scrollpaint() thought = &peep->thoughts[j]; if (thought->type == PEEP_THOUGHT_TYPE_NONE) break; - if (thought->pad_3 == 0) + if (thought->var_2 == 0) continue; - if (thought->pad_3 > 5) + if (thought->var_2 > 5) break; ebx = thought->type; @@ -860,7 +837,7 @@ static int sub_69B7EA(rct_peep *peep, int *outEAX) *outEAX = eax; return ebx & 0xFFFF; case VIEW_THOUGHTS: - if (peep->thoughts[0].pad_3 <= 5) { + if (peep->thoughts[0].var_2 <= 5) { eax = peep->thoughts[0].item; ebx = peep->thoughts[0].type; if (peep->thoughts[0].type != PEEP_THOUGHT_TYPE_NONE) { diff --git a/src/window_land.c b/src/window_land.c index 0e092a771b..823c2f3011 100644 --- a/src/window_land.c +++ b/src/window_land.c @@ -52,7 +52,7 @@ static rct_widget window_land_widgets[] = { static void window_land_emptysub() { } static void window_land_close(); static void window_land_mouseup(); -static void window_land_mousedown(); +static void window_land_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_land_dropdown(); static void window_land_update(rct_window *w); static void window_land_invalidate(); @@ -217,31 +217,9 @@ static void window_land_mouseup() * * rct2: 0x0066407B */ -static void window_land_mousedown() +static void window_land_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { int i; - short widgetIndex; - rct_window *w; - rct_widget *widget; - - #ifdef _MSC_VER - __asm mov widgetIndex, dx - #else - __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); - #endif - - #ifdef _MSC_VER - __asm mov w, esi - #else - __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); - #endif - - #ifdef _MSC_VER - __asm mov widget, edi - #else - __asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) ); - #endif - switch (widgetIndex) { case WIDX_FLOOR: diff --git a/src/window_map.c b/src/window_map.c index 4c14fb8dd2..84cfd99af1 100644 --- a/src/window_map.c +++ b/src/window_map.c @@ -77,7 +77,7 @@ static rct_widget window_map_widgets[] = { static void window_map_emptysub() { } static void window_map_close(); static void window_map_mouseup(); -static void window_map_mousedown(); +static void window_map_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_map_update(rct_window *w); static void window_map_scrollgetsize(); static void window_map_scrollmousedown(); @@ -228,7 +228,7 @@ static void window_map_mouseup() * * rct2: 0x0068D040 */ -static void window_map_mousedown() +static void window_map_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { RCT2_CALLPROC_EBPSAFE(0x0068D040); } diff --git a/src/window_options.c b/src/window_options.c index edc4730f25..d370b185c5 100644 --- a/src/window_options.c +++ b/src/window_options.c @@ -105,7 +105,7 @@ static rct_widget window_options_widgets[] = { static void window_options_emptysub() { } static void window_options_mouseup(); -static void window_options_mousedown(); +static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_options_dropdown(); static void window_options_update(rct_window *w); static void window_options_paint(); @@ -223,6 +223,7 @@ static void window_options_mouseup() break; case WIDX_SCREEN_EDGE_SCROLLING: RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_EDGE_SCROLLING, uint8) ^= 1; + gGeneral_config.edge_scrolling ^= 1; config_save(); window_invalidate(w); break; @@ -248,11 +249,15 @@ static void window_options_mouseup() break; case WIDX_TILE_SMOOTHING_CHECKBOX: RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) ^= CONFIG_FLAG_DISABLE_SMOOTH_LANDSCAPE; + gGeneral_config.landscape_smoothing = !(RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) + & CONFIG_FLAG_DISABLE_SMOOTH_LANDSCAPE); config_save(); gfx_invalidate_screen(); break; case WIDX_GRIDLINES_CHECKBOX: RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) ^= CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES; + gGeneral_config.always_show_gridlines = RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) + & CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES; config_save(); gfx_invalidate_screen(); @@ -265,12 +270,15 @@ static void window_options_mouseup() break; case WIDX_SAVE_PLUGIN_DATA_CHECKBOX: RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) ^= CONFIG_FLAG_SAVE_PLUGIN_DATA; + gGeneral_config.save_plugin_data = !(RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) + & CONFIG_FLAG_SAVE_PLUGIN_DATA); config_save(); window_invalidate(w); break; case WIDX_SOUND_SW_BUFFER_CHECKBOX: pause_sounds(); RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint8) ^= 1; + gSound_config.forced_software_buffering ^= 1; config_save(); unpause_sounds(); window_invalidate(w); @@ -282,25 +290,9 @@ static void window_options_mouseup() * * rct2: 0x006BB01B */ -static void window_options_mousedown() +static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { int num_items, i; - short widgetIndex; - rct_window *w; - rct_widget *widget; - - #ifdef _MSC_VER - __asm mov widgetIndex, dx - #else - __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); - #endif - - #ifdef _MSC_VER - __asm mov w, esi - #else - __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); - #endif - widget = &w->widgets[widgetIndex - 1]; @@ -445,9 +437,12 @@ static void window_options_dropdown() case WIDX_HEIGHT_LABELS_DROPDOWN: // reset flag and set it to 1 if height as units is selected RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) &= ~CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS; + gGeneral_config.show_height_as_units = 0; - if (dropdownIndex == 0) - RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS; + if (dropdownIndex == 0) { + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS; + gGeneral_config.show_height_as_units = 1; + } window_options_update_height_markers(); break; @@ -463,17 +458,20 @@ static void window_options_dropdown() // TODO: no clue what this does (and if it's correct) RCT2_GLOBAL(0x009AAC75, uint8) = RCT2_GLOBAL(0x009AF601 + dropdownIndex, uint8); RCT2_GLOBAL(0x009AAC76, uint8) = RCT2_GLOBAL(0x009AF604 + dropdownIndex, uint8); - + gSound_config.sound_quality = (sint8)dropdownIndex; config_save(); window_invalidate(w); break; case WIDX_CURRENCY_DROPDOWN: RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_CURRENCY, uint8) = dropdownIndex | 0xC0; + gGeneral_config.currency_format = (sint8)dropdownIndex; config_save(); gfx_invalidate_screen(); break; case WIDX_DISTANCE_DROPDOWN: RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, uint8) = (uint8)dropdownIndex; + gGeneral_config.measurement_format = (sint8)dropdownIndex; + config_save(); window_options_update_height_markers(); break; case WIDX_RESOLUTION_DROPDOWN: @@ -488,6 +486,7 @@ static void window_options_dropdown() case WIDX_TEMPERATURE_DROPDOWN: if (dropdownIndex != RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_TEMPERATURE, uint8)) { RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_TEMPERATURE, uint8) = (uint8)dropdownIndex; + gGeneral_config.temperature_format = (sint8)dropdownIndex; config_save(); gfx_invalidate_screen(); } diff --git a/src/window_park.c b/src/window_park.c index d2057e99ad..d47358c7fd 100644 --- a/src/window_park.c +++ b/src/window_park.c @@ -218,7 +218,7 @@ static void window_park_emptysub() { } static void window_park_entrance_close(); static void window_park_entrance_mouseup(); static void window_park_entrance_resize(); -static void window_park_entrance_mousedown(); +static void window_park_entrance_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_park_entrance_dropdown(); static void window_park_entrance_update(rct_window *w); static void window_park_entrance_toolupdate(); @@ -243,7 +243,7 @@ static void window_park_guests_paint(); static void window_park_price_mouseup(); static void window_park_price_resize(); -static void window_park_price_mousedown(); +static void window_park_price_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_park_price_update(rct_window *w); static void window_park_price_invalidate(); static void window_park_price_paint(); @@ -731,31 +731,8 @@ static void window_park_entrance_resize() * * rct2: 0x006681BF */ -static void window_park_entrance_mousedown() +static void window_park_entrance_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { - short widgetIndex; - rct_window *w; - rct_widget *widget; - - #ifdef _MSC_VER - __asm mov widgetIndex, dx - #else - __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); - #endif - - #ifdef _MSC_VER - __asm mov w, esi - #else - __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); - #endif - - #ifdef _MSC_VER - __asm mov widget, edi - #else - __asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) ); - #endif - - if (widgetIndex == WIDX_OPEN_OR_CLOSE) { gDropdownItemsFormat[0] = 1142; gDropdownItemsFormat[1] = 1142; @@ -1617,24 +1594,9 @@ static void window_park_price_resize() * * rct2: 0x0066902C */ -static void window_park_price_mousedown() +static void window_park_price_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { int newFee; - short widgetIndex; - rct_window *w; - - #ifdef _MSC_VER - __asm mov widgetIndex, dx - #else - __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); - #endif - - #ifdef _MSC_VER - __asm mov w, esi - #else - __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); - #endif - switch (widgetIndex) { case WIDX_CLOSE: @@ -2259,13 +2221,13 @@ static void window_park_awards_paint() y = w->y + window_park_awards_widgets[WIDX_PAGE_BACKGROUND].top + 4; count = 0; - for (i = 0; i < 4; i++) { + for (i = 0; i < MAX_AWARDS; i++) { award = &RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award)[i]; if (award->time == 0) continue; gfx_draw_sprite(dpi, SPR_AWARD_MOST_UNTIDY + award->type, x, y); - gfx_draw_string_left_wrapped(dpi, NULL, x + 34, y + 6, 180, STR_AWARD_MOST_UNTIDY, 0); + gfx_draw_string_left_wrapped(dpi, NULL, x + 34, y + 6, 180, STR_AWARD_MOST_UNTIDY + award->type, 0); y += 32; count++; diff --git a/src/window_ride_list.c b/src/window_ride_list.c index 4d0f29da66..8dff8e2433 100644 --- a/src/window_ride_list.c +++ b/src/window_ride_list.c @@ -68,7 +68,7 @@ static rct_widget window_ride_list_widgets[] = { static void window_ride_list_emptysub() { } static void window_ride_list_mouseup(); static void window_ride_list_resize(); -static void window_ride_list_mousedown(); +static void window_ride_list_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_ride_list_dropdown(); static void window_ride_list_update(rct_window *w); static void window_ride_list_scrollgetsize(); @@ -248,31 +248,9 @@ static void window_ride_list_resize() * * rct2: 0x006B3532 */ -static void window_ride_list_mousedown() +static void window_ride_list_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { int numItems, i; - short widgetIndex; - rct_window *w; - rct_widget *widget; - - #ifdef _MSC_VER - __asm mov widgetIndex, dx - #else - __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); - #endif - - #ifdef _MSC_VER - __asm mov w, esi - #else - __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); - #endif - - #ifdef _MSC_VER - __asm mov widget, edi - #else - __asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) ); - #endif - if (widgetIndex == WIDX_OPEN_CLOSE_ALL) { gDropdownItemsFormat[0] = STR_CLOSE_ALL; diff --git a/src/window_save_prompt.c b/src/window_save_prompt.c index a941875889..52413e3cd5 100644 --- a/src/window_save_prompt.c +++ b/src/window_save_prompt.c @@ -257,11 +257,12 @@ static void window_save_prompt_mouseup() } else { switch (widgetIndex) { case WIDX_SAVE: - // TODO to avoid data loss, treat SAVE as CANCEL - RCT2_ERROR("TODO"); - window_close(w); - window_save_prompt_close(); - return; + if (!save_game()) { + // user pressed cancel + window_close(w); + window_save_prompt_close(); + return; + } break; case WIDX_DONT_SAVE: break; diff --git a/src/window_title_menu.c b/src/window_title_menu.c index 087b6cd41e..8e2e5aab45 100644 --- a/src/window_title_menu.c +++ b/src/window_title_menu.c @@ -45,7 +45,7 @@ static rct_widget window_title_menu_widgets[] = { static void window_title_menu_emptysub() { } static void window_title_menu_mouseup(); -static void window_title_menu_mousedown(); +static void window_title_menu_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_title_menu_dropdown(); static void window_title_menu_unknown17(); static void window_title_menu_paint(); @@ -122,31 +122,8 @@ static void window_title_menu_mouseup() } } -static void window_title_menu_mousedown() +static void window_title_menu_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { - short widgetIndex; - rct_window *w; - rct_widget *widget; - - #ifdef _MSC_VER - __asm mov widgetIndex, dx - #else - __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); - #endif - - #ifdef _MSC_VER - __asm mov w, esi - #else - __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); - #endif - - #ifdef _MSC_VER - __asm mov widget, edi - #else - __asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) ); - #endif - - if (widgetIndex == WIDX_SHOW_TUTORIAL) { gDropdownItemsFormat[0] = STR_TUTORIAL_BEGINNERS; gDropdownItemsFormat[1] = STR_TUTORIAL_CUSTOM_RIDES; diff --git a/src/window_title_scenarioselect.c b/src/window_title_scenarioselect.c index caecf96013..09d185238f 100644 --- a/src/window_title_scenarioselect.c +++ b/src/window_title_scenarioselect.c @@ -59,7 +59,7 @@ static void window_scenarioselect_init_tabs(); static void window_scenarioselect_emptysub() { } static void window_scenarioselect_mouseup(); -static void window_scenarioselect_mousedown(); +static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); static void window_scenarioselect_scrollgetsize(); static void window_scenarioselect_scrollmousedown(); static void window_scenarioselect_scrollmouseover(); @@ -190,24 +190,8 @@ static void window_scenarioselect_mouseup() window_close(w); } -static void window_scenarioselect_mousedown() +static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { - short widgetIndex; - rct_window *w; - - #ifdef _MSC_VER - __asm mov widgetIndex, dx - #else - __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); - #endif - - #ifdef _MSC_VER - __asm mov w, esi - #else - __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); - #endif - - if (widgetIndex >= WIDX_TAB1 && widgetIndex <= WIDX_TAB5) { w->selected_tab = widgetIndex - 4; w->var_494 = 0;