1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-22 07:13:07 +01:00

add ability to change language

This commit is contained in:
IntelOrca
2014-08-14 23:46:36 +01:00
parent b306e1e28c
commit e66b686f75
13 changed files with 3729 additions and 132 deletions

View File

@@ -2774,9 +2774,9 @@ STR_2772 :Hogere spelsnelheid
STR_2773 :??? STR_2773 :???
STR_2774 :??? STR_2774 :???
STR_2775 :??? STR_2775 :???
STR_2776 :??? STR_2776 :Language
STR_2777 :??? STR_2777 :{MOVE_X}{SMALLFONT}{STRING}
STR_2778 :??? STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING}
STR_2779 :??? STR_2779 :???
STR_2780 :??? STR_2780 :???
STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID}{STRINGID} STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID}{STRINGID}

3447
data/language/english_uk.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2774,9 +2774,9 @@ STR_2772 :Faster Gamespeed
STR_2773 :??? STR_2773 :???
STR_2774 :??? STR_2774 :???
STR_2775 :??? STR_2775 :???
STR_2776 :??? STR_2776 :Language
STR_2777 :??? STR_2777 :{MOVE_X}{SMALLFONT}{STRING}
STR_2778 :??? STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING}
STR_2779 :??? STR_2779 :???
STR_2780 :??? STR_2780 :???
STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID}{STRINGID} STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID}{STRINGID}

View File

@@ -29,6 +29,7 @@
<ClInclude Include="..\src\gfx.h" /> <ClInclude Include="..\src\gfx.h" />
<ClInclude Include="..\src\graph.h" /> <ClInclude Include="..\src\graph.h" />
<ClInclude Include="..\src\intro.h" /> <ClInclude Include="..\src\intro.h" />
<ClInclude Include="..\src\language.h" />
<ClInclude Include="..\src\map.h" /> <ClInclude Include="..\src\map.h" />
<ClInclude Include="..\src\marketing.h" /> <ClInclude Include="..\src\marketing.h" />
<ClInclude Include="..\src\news_item.h" /> <ClInclude Include="..\src\news_item.h" />
@@ -73,6 +74,7 @@
<ClCompile Include="..\src\gfx.c" /> <ClCompile Include="..\src\gfx.c" />
<ClCompile Include="..\src\graph.c" /> <ClCompile Include="..\src\graph.c" />
<ClCompile Include="..\src\intro.c" /> <ClCompile Include="..\src\intro.c" />
<ClCompile Include="..\src\language.c" />
<ClCompile Include="..\src\map.c" /> <ClCompile Include="..\src\map.c" />
<ClCompile Include="..\src\marketing.c" /> <ClCompile Include="..\src\marketing.c" />
<ClCompile Include="..\src\news_item.c" /> <ClCompile Include="..\src\news_item.c" />

View File

@@ -153,6 +153,9 @@
<ClInclude Include="..\src\graph.h"> <ClInclude Include="..\src\graph.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\src\language.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\src\game.c"> <ClCompile Include="..\src\game.c">
@@ -359,6 +362,9 @@
<ClCompile Include="..\src\window_new_campaign.c"> <ClCompile Include="..\src\window_new_campaign.c">
<Filter>Windows</Filter> <Filter>Windows</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\language.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\openrct2.exe"> <None Include="..\openrct2.exe">

View File

@@ -23,6 +23,7 @@
#include <ctype.h> #include <ctype.h>
#include "addresses.h" #include "addresses.h"
#include "config.h" #include "config.h"
#include "language.h"
#include "rct2.h" #include "rct2.h"
@@ -90,6 +91,7 @@ general_configuration_t gGeneral_config_default = {
0, // show_height_as_units 0, // show_height_as_units
1, // save_plugin_data 1, // save_plugin_data
0, // fullscreen mode (default: windowed) 0, // fullscreen mode (default: windowed)
LANGUAGE_ENGLISH_UK
}; };
sound_configuration_t gSound_config; sound_configuration_t gSound_config;
@@ -381,6 +383,8 @@ void config_write_ini_general(FILE *fp)
fprintf(fp, "fullscreen_mode = fullscreen\n"); fprintf(fp, "fullscreen_mode = fullscreen\n");
else else
fprintf(fp, "fullscreen_mode = borderless_fullscreen\n"); fprintf(fp, "fullscreen_mode = borderless_fullscreen\n");
fprintf(fp, "language = %d\n", gGeneral_config.language);
} }
/** /**
@@ -621,6 +625,9 @@ static void config_general(char *setting, char *value){
else else
gGeneral_config.fullscreen_mode = 2; gGeneral_config.fullscreen_mode = 2;
} }
else if (strcmp(setting, "language") == 0) {
gGeneral_config.language = atoi(value);
}
} }
/** /**

View File

@@ -130,6 +130,7 @@ typedef struct general_configuration {
//new //new
uint8 fullscreen_mode; uint8 fullscreen_mode;
uint16 language;
} general_configuration_t; } general_configuration_t;
static const struct { char *key; int value; } _currencyLookupTable[] = { static const struct { char *key; int value; } _currencyLookupTable[] = {

165
src/language.c Normal file
View File

@@ -0,0 +1,165 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include <stdio.h>
#include "addresses.h"
#include "language.h"
#include "string_ids.h"
const char *language_names[LANGUAGE_COUNT] = {
"", // LANGUAGE_UNDEFINED
"English (UK)", // LANGUAGE_ENGLISH_UK
"English (US)", // LANGUAGE_ENGLISH_US
"Nederlands" // LANGUAGE_DUTCH
};
const char *language_filenames[LANGUAGE_COUNT] = {
"", // LANGUAGE_UNDEFINED
"english_uk", // LANGUAGE_ENGLISH_UK
"english_us", // LANGUAGE_ENGLISH_US
"dutch" // LANGUAGE_DUTCH
};
int gCurrentLanguage = LANGUAGE_UNDEFINED;
// Buffer storing all the string data
long language_buffer_size = 0;
char *language_buffer = NULL;
// List of string pointers into the string data
int language_num_strings = 0;
char **language_strings = NULL;
static int language_open_file(const char *filename);
const char *language_get_string(rct_string_id id)
{
const char *rct = RCT2_ADDRESS(0x009BF2D4, const char*)[id];
const char *openrct = language_strings == NULL ? NULL : language_strings[id];
const char *str = (openrct == NULL || strlen(openrct) == 0 ? rct : openrct);
return str == NULL ? "" : str;
}
int language_open(int id)
{
char filename[_MAX_PATH];
language_close();
if (id == LANGUAGE_UNDEFINED)
return 1;
sprintf(filename, "data/language/%s.txt", language_filenames[id]);
if (language_open_file(filename)) {
gCurrentLanguage = id;
return 1;
}
return 0;
}
/**
* Partial support to open a uncompiled language file which parses tokens and converts them to the corresponding character
* code. Due to resource strings (strings in scenarios and objects) being written to the original game's string table,
* get_string will use those if the same entry in the loaded language is empty.
*
* Unsure at how the original game decides which entries to write resource strings to, but this could affect adding new
* strings for the time being. Further investigation is required.
*
* Also note that all strings are currently still ASCII. It probably can't be converted to UTF-8 until all game functions that
* read / write strings in some way is decompiled. The original game used a DIY extended 8-bit extended ASCII set for special
* characters, format codes and accents.
*
* In terms of reading the language files, the STR_XXXX part is completely ignored at the moment. It just parses each line from
* the colon and thus not allowing gaps in the string indices.
*/
static int language_open_file(const char *filename)
{
FILE *f = fopen(filename, "rb");
if (f == NULL)
return 0;
fseek(f, 0, SEEK_END);
language_buffer_size = ftell(f);
language_buffer = calloc(1, language_buffer_size);
fseek(f, 0, SEEK_SET);
fread(language_buffer, language_buffer_size, 1, f);
fclose(f);
language_strings = calloc(STR_COUNT, sizeof(char*));
char *dst, *token;
char tokenBuffer[64];
int i, stringIndex = 0, mode = 0;
for (i = 0; i < language_buffer_size; i++) {
char *src = &language_buffer[i];
switch (mode) {
case 0:
// Search for colon
if (*src == ':') {
dst = src + 1;
language_strings[stringIndex++] = dst;
mode = 1;
}
break;
case 1:
// Copy string over, stop at line break
if (*src == '{') {
token = src + 1;
mode = 2;
} else if (*src == '\n' || *src == '\r') {
*dst = 0;
mode = 0;
} else {
*dst++ = *src;
}
break;
case 2:
// Read token, convert to code
if (*src == '}') {
int tokenLength = min(src - token, sizeof(tokenBuffer) - 1);
memcpy(tokenBuffer, token, tokenLength);
tokenBuffer[tokenLength] = 0;
char code = format_get_code(tokenBuffer);
if (code == 0)
code = atoi(tokenBuffer);
*dst++ = code;
mode = 1;
}
break;
}
}
language_num_strings = stringIndex;
return 1;
}
void language_close()
{
if (language_buffer != NULL)
free(language_buffer);
language_buffer_size = 0;
if (language_strings != NULL)
free(language_strings);
language_num_strings = 0;
gCurrentLanguage = LANGUAGE_UNDEFINED;
}

42
src/language.h Normal file
View File

@@ -0,0 +1,42 @@
/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#ifndef _LANGUAGE_H_
#define _LANGUAGE_H_
#include "rct2.h"
#include "string_ids.h"
enum {
LANGUAGE_UNDEFINED,
LANGUAGE_ENGLISH_UK,
LANGUAGE_ENGLISH_US,
LANGUAGE_DUTCH,
LANGUAGE_COUNT
};
extern const char *language_names[LANGUAGE_COUNT];
extern int gCurrentLanguage;
const char *language_get_string(rct_string_id id);
int language_open(int id);
void language_close();
#endif

View File

@@ -37,6 +37,7 @@
#include "game.h" #include "game.h"
#include "gfx.h" #include "gfx.h"
#include "intro.h" #include "intro.h"
#include "language.h"
#include "map.h" #include "map.h"
#include "news_item.h" #include "news_item.h"
#include "object.h" #include "object.h"
@@ -76,9 +77,6 @@ __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInsta
{ {
print_launch_information(); print_launch_information();
// OpenRCT2 initialisation
language_open("data/language/english.txt");
// Begin RCT2 // Begin RCT2
RCT2_GLOBAL(RCT2_ADDRESS_HINSTANCE, HINSTANCE) = hInstance; RCT2_GLOBAL(RCT2_ADDRESS_HINSTANCE, HINSTANCE) = hInstance;
RCT2_GLOBAL(RCT2_ADDRESS_CMDLINE, LPSTR) = lpCmdLine; RCT2_GLOBAL(RCT2_ADDRESS_CMDLINE, LPSTR) = lpCmdLine;
@@ -88,6 +86,7 @@ __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInsta
audio_get_devices(); audio_get_devices();
RCT2_CALLPROC(0x0040502E); // get_dsound_devices() RCT2_CALLPROC(0x0040502E); // get_dsound_devices()
config_init(); config_init();
language_open(gGeneral_config.language);
rct2_init(); rct2_init();
rct2_loop(); rct2_loop();
osinterface_free(); osinterface_free();

View File

@@ -25,6 +25,7 @@
#include "currency.h" #include "currency.h"
#include "game.h" #include "game.h"
#include "date.h" #include "date.h"
#include "language.h"
#include "rct2.h" #include "rct2.h"
#include "string_ids.h" #include "string_ids.h"
#include "util.h" #include "util.h"
@@ -1471,7 +1472,7 @@ void format_string_code(unsigned char format_code, char **dest, char **args)
value = *((uint16*)*args); value = *((uint16*)*args);
*args += 2; *args += 2;
strcpy(*dest, get_string(STR_MONTH_MARCH + date_get_month(value))); strcpy(*dest, language_get_string(STR_MONTH_MARCH + date_get_month(value)));
*dest += strlen(*dest); *dest += strlen(*dest);
break; break;
case FORMAT_VELOCITY: case FORMAT_VELOCITY:
@@ -1591,7 +1592,7 @@ void format_string_part(char **dest, rct_string_id format, char **args)
{ {
if (format < 0x8000) { if (format < 0x8000) {
// Language string // Language string
format_string_part_from_raw(dest, get_string(format), args); format_string_part_from_raw(dest, language_get_string(format), args);
} else if (format < 0x9000) { } else if (format < 0x9000) {
// Custom string // Custom string
format -= 0x8000; format -= 0x8000;
@@ -1691,107 +1692,3 @@ void reset_saved_strings() {
RCT2_ADDRESS(0x135A8F4, uint8)[i * 32] = 0; RCT2_ADDRESS(0x135A8F4, uint8)[i * 32] = 0;
} }
} }
// Buffer storing all the string data
long language_buffer_size = 0;
char *language_buffer = NULL;
// List of string pointers into the string data
int language_num_strings = 0;
char **language_strings = NULL;
const char *get_string(rct_string_id id)
{
const char *rct = RCT2_ADDRESS(0x009BF2D4, const char*)[id];
const char *openrct = language_strings == NULL ? NULL : language_strings[id];
const char *str = (openrct == NULL || strlen(openrct) == 0 ? rct : openrct);
return str == NULL ? "" : str;
}
/**
* Partial support to open a uncompiled language file which parses tokens and converts them to the corresponding character
* code. Due to resource strings (strings in scenarios and objects) being written to the original game's string table,
* get_string will use those if the same entry in the loaded language is empty.
*
* Unsure at how the original game decides which entries to write resource strings to, but this could affect adding new
* strings for the time being. Further investigation is required.
*
* Also note that all strings are currently still ASCII. It probably can't be converted to UTF-8 until all game functions that
* read / write strings in some way is decompiled. The original game used a DIY extended 8-bit extended ASCII set for special
* characters, format codes and accents.
*
* In terms of reading the language files, the STR_XXXX part is completely ignored at the moment. It just parses each line from
* the colon and thus not allowing gaps in the string indices.
*/
int language_open(const char *filename)
{
FILE *f = fopen(filename, "rb");
if (f == NULL)
return 0;
fseek(f, 0, SEEK_END);
language_buffer_size = ftell(f);
language_buffer = calloc(1, language_buffer_size);
fseek(f, 0, SEEK_SET);
fread(language_buffer, language_buffer_size, 1, f);
fclose(f);
language_strings = calloc(STR_COUNT, sizeof(char*));
char *dst, *token;
char tokenBuffer[64];
int i, stringIndex = 0, mode = 0;
for (i = 0; i < language_buffer_size; i++) {
char *src = &language_buffer[i];
switch (mode) {
case 0:
// Search for colon
if (*src == ':') {
dst = src + 1;
language_strings[stringIndex++] = dst;
mode = 1;
}
break;
case 1:
// Copy string over, stop at line break
if (*src == '{') {
token = src + 1;
mode = 2;
} else if (*src == '\n' || *src == '\r') {
*dst = 0;
mode = 0;
} else {
*dst++ = *src;
}
break;
case 2:
// Read token, convert to code
if (*src == '}') {
int tokenLength = min(src - token, sizeof(tokenBuffer) - 1);
memcpy(tokenBuffer, token, tokenLength);
tokenBuffer[tokenLength] = 0;
char code = format_get_code(tokenBuffer);
if (code == 0)
code = atoi(tokenBuffer);
*dst++ = code;
mode = 1;
}
break;
}
}
language_num_strings = stringIndex;
return 1;
}
void language_close()
{
if (language_buffer != NULL)
free(language_buffer);
language_buffer_size = 0;
if (language_strings != NULL)
free(language_strings);
language_num_strings = 0;
}

View File

@@ -28,9 +28,8 @@ void generate_string_file();
void reset_saved_strings(); void reset_saved_strings();
void error_string_quit(int error, rct_string_id format); void error_string_quit(int error, rct_string_id format);
const char *get_string(rct_string_id id); char format_get_code(const char *token);
int language_open(const char *filename); const char *format_get_token(char code);
void language_close();
enum { enum {
// Font format codes // Font format codes

View File

@@ -22,6 +22,7 @@
#include "audio.h" #include "audio.h"
#include "config.h" #include "config.h"
#include "gfx.h" #include "gfx.h"
#include "language.h"
#include "osinterface.h" #include "osinterface.h"
#include "string_ids.h" #include "string_ids.h"
#include "viewport.h" #include "viewport.h"
@@ -67,11 +68,14 @@ enum WINDOW_OPTIONS_WIDGET_IDX {
WIDX_HOTKEY_DROPDOWN, WIDX_HOTKEY_DROPDOWN,
WIDX_GENERAL_GROUP, WIDX_GENERAL_GROUP,
WIDX_REAL_NAME_CHECKBOX, WIDX_REAL_NAME_CHECKBOX,
WIDX_SAVE_PLUGIN_DATA_CHECKBOX WIDX_SAVE_PLUGIN_DATA_CHECKBOX,
WIDX_LANGUAGE_GROUP,
WIDX_LANGUAGE_DROPDOWN,
WIDX_LANGUAGE_DROPDOWN_BUTTON
}; };
#define WW 310 #define WW 310
#define WH 399 #define WH 437
static rct_widget window_options_widgets[] = { static rct_widget window_options_widgets[] = {
{ WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, STR_NONE, STR_NONE }, { WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, STR_NONE, STR_NONE },
@@ -110,6 +114,9 @@ static rct_widget window_options_widgets[] = {
{ WWT_GROUPBOX, 0, 3, 306, 344, 392, STR_GENERAL, STR_NONE }, { WWT_GROUPBOX, 0, 3, 306, 344, 392, STR_GENERAL, STR_NONE },
{ WWT_CHECKBOX, 2, 10, 299, 358, 369, STR_REAL_NAME, STR_REAL_NAME_TIP }, { WWT_CHECKBOX, 2, 10, 299, 358, 369, STR_REAL_NAME, STR_REAL_NAME_TIP },
{ WWT_CHECKBOX, 2, 10, 299, 372, 384, STR_SAVE_PLUGIN_DATA, STR_SAVE_PLUGIN_DATA_TIP }, { WWT_CHECKBOX, 2, 10, 299, 372, 384, STR_SAVE_PLUGIN_DATA, STR_SAVE_PLUGIN_DATA_TIP },
{ WWT_GROUPBOX, 0, 3, 306, 399, 430, 2776, STR_NONE },
{ WWT_DROPDOWN, 0, 10, 299, 413, 424, STR_NONE, STR_NONE }, // language
{ WWT_DROPDOWN_BUTTON, 0, 288, 298, 414, 423, 0x36C, STR_NONE },
{ WIDGETS_END }, { WIDGETS_END },
}; };
@@ -119,7 +126,7 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
static void window_options_dropdown(); static void window_options_dropdown();
static void window_options_invalidate(); static void window_options_invalidate();
static void window_options_paint(); static void window_options_paint();
static void window_options_draw_dropdown_box(rct_window *w, rct_widget *widget, int num_items); static void window_options_show_dropdown(rct_window *w, rct_widget *widget, int num_items);
static void window_options_update_height_markers(); static void window_options_update_height_markers();
static void* window_options_events[] = { static void* window_options_events[] = {
@@ -326,7 +333,7 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsArgs[i] = 1170 | ((uint64)(intptr_t)gAudioDevices[i].name << 16); gDropdownItemsArgs[i] = 1170 | ((uint64)(intptr_t)gAudioDevices[i].name << 16);
} }
window_options_draw_dropdown_box(w, widget, gAudioDeviceCount); window_options_show_dropdown(w, widget, gAudioDeviceCount);
gDropdownItemsChecked |= (1 << RCT2_GLOBAL(0x9AF280, uint32)); gDropdownItemsChecked |= (1 << RCT2_GLOBAL(0x9AF280, uint32));
break; break;
@@ -336,7 +343,7 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsArgs[0] = STR_UNITS; gDropdownItemsArgs[0] = STR_UNITS;
gDropdownItemsArgs[1] = STR_REAL_VALUES; gDropdownItemsArgs[1] = STR_REAL_VALUES;
window_options_draw_dropdown_box(w, widget, 2); window_options_show_dropdown(w, widget, 2);
gDropdownItemsChecked = gDropdownItemsChecked =
(RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) &
@@ -348,7 +355,7 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsArgs[0] = STR_OFF; gDropdownItemsArgs[0] = STR_OFF;
gDropdownItemsArgs[1] = STR_ON; gDropdownItemsArgs[1] = STR_ON;
window_options_draw_dropdown_box(w, widget, 2); window_options_show_dropdown(w, widget, 2);
gDropdownItemsChecked = 1 << RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8); gDropdownItemsChecked = 1 << RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8);
break; break;
@@ -360,7 +367,7 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsArgs[i] = STR_SOUND_LOW + i; // low, medium, high gDropdownItemsArgs[i] = STR_SOUND_LOW + i; // low, medium, high
} }
window_options_draw_dropdown_box(w, widget, num_items); window_options_show_dropdown(w, widget, num_items);
gDropdownItemsChecked = 1 << RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_QUALITY, uint8); gDropdownItemsChecked = 1 << RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_QUALITY, uint8);
break; break;
@@ -372,7 +379,7 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsArgs[i] = STR_POUNDS + i; // all different currencies gDropdownItemsArgs[i] = STR_POUNDS + i; // all different currencies
} }
window_options_draw_dropdown_box(w, widget, num_items); window_options_show_dropdown(w, widget, num_items);
gDropdownItemsChecked = 1 << (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_CURRENCY, uint8) & 0x3F); gDropdownItemsChecked = 1 << (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_CURRENCY, uint8) & 0x3F);
break; break;
@@ -382,7 +389,7 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsArgs[0] = STR_IMPERIAL; gDropdownItemsArgs[0] = STR_IMPERIAL;
gDropdownItemsArgs[1] = STR_METRIC; gDropdownItemsArgs[1] = STR_METRIC;
window_options_draw_dropdown_box(w, widget, 2); window_options_show_dropdown(w, widget, 2);
gDropdownItemsChecked = 1 << RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, uint8); gDropdownItemsChecked = 1 << RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, uint8);
break; break;
@@ -397,7 +404,7 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsArgs[1] = STR_FAHRENHEIT; gDropdownItemsArgs[1] = STR_FAHRENHEIT;
gDropdownItemsArgs[2] = STR_METRIC; gDropdownItemsArgs[2] = STR_METRIC;
window_options_draw_dropdown_box(w, widget, 3); window_options_show_dropdown(w, widget, 3);
gDropdownItemsChecked = 1 << gGeneral_config.fullscreen_mode; gDropdownItemsChecked = 1 << gGeneral_config.fullscreen_mode;
break; break;
@@ -407,7 +414,7 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsArgs[0] = STR_CELSIUS; gDropdownItemsArgs[0] = STR_CELSIUS;
gDropdownItemsArgs[1] = STR_FAHRENHEIT; gDropdownItemsArgs[1] = STR_FAHRENHEIT;
window_options_draw_dropdown_box(w, widget, 2); window_options_show_dropdown(w, widget, 2);
gDropdownItemsChecked = 1 << RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_TEMPERATURE, uint8); gDropdownItemsChecked = 1 << RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_TEMPERATURE, uint8);
break; break;
@@ -417,10 +424,18 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsArgs[0] = STR_WHITE; gDropdownItemsArgs[0] = STR_WHITE;
gDropdownItemsArgs[1] = STR_TRANSLUCENT; gDropdownItemsArgs[1] = STR_TRANSLUCENT;
window_options_draw_dropdown_box(w, widget, 2); window_options_show_dropdown(w, widget, 2);
gDropdownItemsChecked = 1 << RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_CONSTRUCTION_MARKER, uint8); gDropdownItemsChecked = 1 << RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_CONSTRUCTION_MARKER, uint8);
break; break;
case WIDX_LANGUAGE_DROPDOWN_BUTTON:
for (i = 1; i < LANGUAGE_COUNT; i++) {
gDropdownItemsFormat[i - 1] = 2777;
gDropdownItemsArgs[i - 1] = (sint64)language_names[i];
}
window_options_show_dropdown(w, widget, LANGUAGE_COUNT - 1);
gDropdownItemsChecked = 1 << (gCurrentLanguage - 1);
break;
} }
} }
@@ -544,6 +559,14 @@ static void window_options_dropdown()
gfx_invalidate_screen(); gfx_invalidate_screen();
} }
break; break;
case WIDX_LANGUAGE_DROPDOWN_BUTTON:
if (dropdownIndex != gCurrentLanguage - 1) {
language_open(dropdownIndex + 1);
gGeneral_config.language = dropdownIndex + 1;
config_save();
gfx_invalidate_screen();
}
break;
} }
} }
@@ -708,10 +731,19 @@ static void window_options_paint()
w->y + window_options_widgets[WIDX_MUSIC].top + 1); w->y + window_options_widgets[WIDX_MUSIC].top + 1);
gfx_draw_string_left(dpi, STR_SOUND_QUALITY, w, 0, w->x + 10, gfx_draw_string_left(dpi, STR_SOUND_QUALITY, w, 0, w->x + 10,
w->y + window_options_widgets[WIDX_SOUND_QUALITY].top + 1); w->y + window_options_widgets[WIDX_SOUND_QUALITY].top + 1);
// language
gfx_draw_string(
dpi,
(char*)language_names[gCurrentLanguage],
12,
w->x + window_options_widgets[WIDX_LANGUAGE_DROPDOWN].left + 1,
w->y + window_options_widgets[WIDX_LANGUAGE_DROPDOWN].top
);
} }
// helper function, all dropdown boxes have similar properties // helper function, all dropdown boxes have similar properties
static void window_options_draw_dropdown_box(rct_window *w, rct_widget *widget, int num_items) static void window_options_show_dropdown(rct_window *w, rct_widget *widget, int num_items)
{ {
window_dropdown_show_text_custom_width( window_dropdown_show_text_custom_width(
w->x + widget->left, w->x + widget->left,