Skip to content

Commit

Permalink
Support other Languages
Browse files Browse the repository at this point in the history
  • Loading branch information
Nopey committed Oct 27, 2024
1 parent e716e69 commit 3f8531d
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/game/gui/text_render.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void text_defaults(text_settings *settings) {

int text_render_char(const text_settings *settings, text_mode state, int x, int y, char ch) {
// Make sure code is valid
int code = ch - 32;
int code = (unsigned char)ch - 32;
surface **sur = NULL;
if(code < 0) {
return 0;
Expand Down
15 changes: 11 additions & 4 deletions src/game/gui/textselector.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,20 @@ const char *textselector_get_current_text(const component *c) {
static void textselector_render(component *c) {
textselector *tb = widget_get_obj(c);
char buf[100];
int buf_max = sizeof buf - 1;
buf[buf_max] = '\0';

// Only render if the selector has options
if(vector_size(&tb->options) > 0) {
if(vector_size(&tb->options) > 0 && tb->text[0] != '\0') {
// label & options
char **opt = vector_get(&tb->options, *tb->pos);
snprintf(buf, 100, "%s %s", tb->text, *opt);
snprintf(buf, buf_max, "%s %s", tb->text, *opt);
} else if(vector_size(&tb->options) > 0) {
// no label, just options
char **opt = vector_get(&tb->options, *tb->pos);
snprintf(buf, buf_max, "%s", *opt);
} else {
snprintf(buf, 100, "%s -", tb->text);
// no options, just label
snprintf(buf, buf_max, "%s -", tb->text);
}

// Render text
Expand Down
9 changes: 8 additions & 1 deletion src/game/scenes/mainmenu/menu_configuration.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "game/scenes/mainmenu/menu_configuration.h"
#include "game/scenes/mainmenu/menu_audio.h"
#include "game/scenes/mainmenu/menu_input.h"
#include "game/scenes/mainmenu/menu_language.h"
#include "game/scenes/mainmenu/menu_video.h"

#include "game/gui/gui.h"
Expand All @@ -11,6 +12,11 @@ void menu_config_done(component *c, void *u) {
m->finished = 1;
}

static void menu_enter_language(component *c, void *userdata) {
scene *s = userdata;
menu_set_submenu(c->parent, menu_language_create(s));
}

void menu_enter_input_1(component *c, void *userdata) {
scene *s = userdata;
menu_set_submenu(c->parent, menu_input_create(s, 1));
Expand Down Expand Up @@ -41,7 +47,8 @@ component *menu_configuration_create(scene *s) {
component *menu = menu_create(11);
menu_attach(menu, label_create(&tconf, "CONFIGURATION"));
menu_attach(menu, filler_create());
menu_attach(menu, filler_create());
menu_attach(menu,
textbutton_create(&tconf, "LANGUAGE", "Forstar du ikke engelsk?", COM_ENABLED, menu_enter_language, s));
menu_attach(menu,
textbutton_create(&tconf, "PLAYER 1 INPUT", "Choose the control for player 1: keyboard or joystick.",
COM_ENABLED, menu_enter_input_1, s));
Expand Down
136 changes: 136 additions & 0 deletions src/game/scenes/mainmenu/menu_language.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#include <stdio.h>

#include "game/scenes/mainmenu/menu_language.h"

#include "game/gui/gui.h"
#include "game/utils/settings.h"
#include "resources/languages.h"
#include "resources/pathmanager.h"
#include "utils/allocator.h"
#include "utils/list.h"
#include "utils/log.h"
#include "utils/scandir.h"

typedef struct {
char **language_filenames;
char **language_names;
int language_count;
int selected_language;
} language_menu_data;

void menu_language_done(component *c, void *u) {
language_menu_data *local = menu_get_userdata(c->parent);
settings_language *l = &settings_get()->language;

// Set menu as finished
menu *m = sizer_get_obj(c->parent);
m->finished = 1;

if(strcmp(l->language, local->language_filenames[local->selected_language]) != 0) {
omf_free(l->language);
l->language = local->language_filenames[local->selected_language];
local->language_filenames[local->selected_language] = NULL;

// reload language
lang_close();
lang_init();
}
}

void menu_language_free(component *c) {
language_menu_data *local = menu_get_userdata(c);
for(int l = 0; l < local->language_count; l++) {
omf_free(local->language_filenames[l]);
omf_free(local->language_names[l]);
}
omf_free(local->language_filenames);
omf_free(local->language_names);
omf_free(local);
menu_set_userdata(c, local);
}

void menu_language_submenu_done(component *c, component *submenu) {
menu *m = sizer_get_obj(c);
m->finished = 1;
}

component *menu_language_create(scene *s) {
// Menu userdata
language_menu_data *local = omf_calloc(1, sizeof(language_menu_data));

// Load settings etc.
settings *setting = settings_get();

// Find path to languages
const char *dirname = pm_get_local_path(RESOURCE_PATH);
if(dirname == NULL) {
PERROR("Could not find resources path for menu_language!");
return NULL;
}

list dirlist;
// Seek all files
list_create(&dirlist);
scan_directory(&dirlist, dirname);
local->language_filenames = omf_malloc(list_size(&dirlist) * sizeof(char *));
local->language_names = omf_malloc(list_size(&dirlist) * sizeof(char *));
local->language_count = 0;

iterator it;
list_iter_begin(&dirlist, &it);
char const *filename;
while((filename = (char *)list_iter_next(&it))) {
char *ext = NULL;

if(strcmp("ENGLISH.DAT", filename) != 0 && strcmp("GERMAN.DAT", filename) != 0 &&
((ext = strrchr(filename, '.')) == NULL || strcmp(".LNG", ext) != 0)) {
continue;
}

if(strcmp(setting->language.language, filename) == 0) {
local->selected_language = local->language_count;
}

int id = local->language_count++;

// strip .DAT or .LNG
size_t filename_len = strlen(filename);
size_t name_len = filename_len - 4;
local->language_names[id] = omf_malloc(name_len + 1);
memcpy(local->language_names[id], filename, name_len);
local->language_names[id][name_len] = '\0';

// move filename into language_filenames
list_node *now = it.vnow;
local->language_filenames[id] = now->data;
now->data = NULL;
}
list_free(&dirlist);

// Text config
text_settings tconf;
text_defaults(&tconf);
tconf.font = FONT_BIG;
tconf.halign = TEXT_CENTER;
tconf.cforeground = TEXT_MEDIUM_GREEN;

// Create menu and its header
component *menu = menu_create(11);
menu_attach(menu, label_create(&tconf, "LANGUAGE"));

menu_attach(menu,
textselector_create_bind_opts(&tconf, "", "Choose a Language.", NULL, NULL, &local->selected_language,
(char const **)local->language_names, local->language_count));

menu_attach(menu, filler_create());

// Done button
menu_attach(menu,
textbutton_create(&tconf, "DONE", "Return to the main menu.", COM_ENABLED, menu_language_done, s));

// Userdata & free function for it
menu_set_userdata(menu, local);
menu_set_free_cb(menu, menu_language_free);
menu_set_submenu_done_cb(menu, menu_language_submenu_done);
return menu;
}
9 changes: 9 additions & 0 deletions src/game/scenes/mainmenu/menu_language.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef MENU_LANGUAGE_H
#define MENU_LANGUAGE_H

#include "game/gui/component.h"
#include "game/protos/scene.h"

component *menu_language_create(scene *s);

#endif // MENU_LANGUAGE_H
5 changes: 5 additions & 0 deletions src/game/utils/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ typedef struct {
} struct_to_field;

// clang-format off
static const field f_language[] = {
F_STRING(settings_language, language, "ENGLISH.DAT"),
};

const field f_video[] = {
F_INT(settings_video, screen_w, 640),
F_INT(settings_video, screen_h, 400),
Expand Down Expand Up @@ -140,6 +144,7 @@ const field f_net[] = {

// Map struct to field
const struct_to_field struct_to_fields[] = {
S_2_F(&_settings.language, f_language),
S_2_F(&_settings.video, f_video),
S_2_F(&_settings.sound, f_sound),
S_2_F(&_settings.gameplay, f_gameplay),
Expand Down
5 changes: 5 additions & 0 deletions src/game/utils/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ typedef struct {
int music_vol;
} settings_sound;

typedef struct {
char *language;
} settings_language;

typedef struct {
int screen_w;
int screen_h;
Expand Down Expand Up @@ -111,6 +115,7 @@ typedef struct {
} settings_network;

typedef struct {
settings_language language;
settings_video video;
settings_sound sound;
settings_gameplay gameplay;
Expand Down
4 changes: 0 additions & 4 deletions src/resources/ids.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ const char *get_resource_file(unsigned int id) {
return "ARENA4.PSM";
case DAT_SOUNDS:
return "SOUNDS.DAT";
case DAT_ENGLISH:
return "ENGLISH.DAT";
case DAT_GRAPHCHR:
return "GRAPHCHR.DAT";
case DAT_CHARSMAL:
Expand Down Expand Up @@ -194,8 +192,6 @@ const char *get_resource_name(unsigned int id) {
return "PSM_ARENA4";
case DAT_SOUNDS:
return "DAT_SOUNDS";
case DAT_ENGLISH:
return "DAT_ENGLISH";
case DAT_GRAPHCHR:
return "DAT_GRAPHCHR";
case DAT_CHARSMAL:
Expand Down
1 change: 0 additions & 1 deletion src/resources/ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ typedef enum resource_id
PSM_ARENA3,
PSM_ARENA4,
DAT_SOUNDS,
DAT_ENGLISH,
DAT_GRAPHCHR,
DAT_CHARSMAL,
DAT_ALTPALS,
Expand Down
11 changes: 10 additions & 1 deletion src/resources/languages.c
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
#include "resources/languages.h"
#include "formats/error.h"
#include "formats/language.h"
#include "game/utils/settings.h"
#include "resources/pathmanager.h"
#include "utils/allocator.h"
#include "utils/log.h"
#include "utils/str.h"
#include <string.h>

static sd_language *language;

int lang_init(void) {
const char *filename = pm_get_resource_path(DAT_ENGLISH);
str filename_str;
const char *dirname = pm_get_local_path(RESOURCE_PATH);
const char *lang = settings_get()->language.language;
str_from_format(&filename_str, "%s%s", dirname, lang);
char const *filename = str_c(&filename_str);

// Load up language file
language = omf_calloc(1, sizeof(sd_language));
Expand Down Expand Up @@ -58,13 +64,16 @@ int lang_init(void) {

INFO("Loaded language file '%s'.", filename);

str_free(&filename_str);

// XXX we're wasting 32KB of memory on language->strings[...].description

return 0;

error_0:
sd_language_free(language);
omf_free(language);
str_free(&filename_str);
return 1;
}

Expand Down

0 comments on commit 3f8531d

Please sign in to comment.