From 7652f176b949b1ca403615b6c429e48e93c98a4a Mon Sep 17 00:00:00 2001
From: "p.kosyh"
Date: Sat, 5 Sep 2009 04:44:45 +0000
Subject: [PATCH] not tested version of locale-support code refactoring
---
Rules.make.standalone | 1 +
Rules.make.system | 5 +-
languages/Makefile | 8 +
languages/Makefile.windows | 7 +
languages/en.ini | 107 +++
languages/ru.ini | 108 +++
src/sdl-instead/Makefile | 4 +-
src/sdl-instead/config.c | 79 ++
src/sdl-instead/config.h | 24 +
src/sdl-instead/externals.h | 41 +
src/sdl-instead/game.c | 1446 +++--------------------------------
src/sdl-instead/game.h | 91 ++-
src/sdl-instead/graphics.c | 10 +-
src/sdl-instead/input.c | 6 +-
src/sdl-instead/instead.c | 15 +-
src/sdl-instead/internals.h | 10 +
src/sdl-instead/main.c | 21 +-
src/sdl-instead/menu.c | 615 +++++++++++++++
src/sdl-instead/menu.h | 134 +---
src/sdl-instead/sound.c | 20 +-
src/sdl-instead/sound.h | 3 +
src/sdl-instead/themes.c | 438 +++++++++++
src/sdl-instead/themes.h | 115 +++
src/sdl-instead/unix.c | 20 +-
src/sdl-instead/util.c | 218 ++++++
src/sdl-instead/util.h | 31 +
src/sdl-instead/windows.c | 14 +-
27 files changed, 2080 insertions(+), 1511 deletions(-)
create mode 100644 languages/Makefile
create mode 100644 languages/Makefile.windows
create mode 100644 languages/en.ini
create mode 100644 languages/ru.ini
create mode 100644 src/sdl-instead/config.c
create mode 100644 src/sdl-instead/config.h
create mode 100644 src/sdl-instead/externals.h
create mode 100644 src/sdl-instead/internals.h
create mode 100644 src/sdl-instead/menu.c
create mode 100644 src/sdl-instead/themes.c
create mode 100644 src/sdl-instead/themes.h
create mode 100644 src/sdl-instead/util.c
create mode 100644 src/sdl-instead/util.h
diff --git a/Rules.make.standalone b/Rules.make.standalone
index 344c055..e9b0c7c 100644
--- a/Rules.make.standalone
+++ b/Rules.make.standalone
@@ -6,6 +6,7 @@ STEADPATH=./stead
THEMESPATH=./themes
GAMESPATH=./games
ICONPATH=./icon
+LANGPATH=./languages
DOCPATH=
LUA_CFLAGS=$(shell pkg-config --cflags lua5.1)
diff --git a/Rules.make.system b/Rules.make.system
index c449db4..35c26e0 100644
--- a/Rules.make.system
+++ b/Rules.make.system
@@ -8,6 +8,7 @@ THEMESPATH=$(STEADPATH)/themes
GAMESPATH=$(STEADPATH)/games
ICONPATH=$(DESTDIR)$(PREFIX)/share/pixmaps
DOCPATH=$(DESTDIR)$(PREFIX)/share/doc/instead
+LANGPATH=$(STEADPATH)/languages
LUA_CFLAGS=$(shell pkg-config --cflags lua5.1)
LUA_LFLAGS=$(shell pkg-config --libs lua5.1)
@@ -23,8 +24,8 @@ SDL_LFLAGS=$(shell sdl-config --libs) -lSDL_ttf -lSDL_mixer -lSDL_image
CFLAGS += -Wall -D_HAVE_ICONV -DRUSSIAN
-INSTALLD=install -d -m 0775
-INSTALL=install -m 0775
+INSTALLD=install -d -m 0755
+INSTALL=install -m 0755
EXE=
PLATFORM=unix.c
RESOURCES=
diff --git a/languages/Makefile b/languages/Makefile
new file mode 100644
index 0000000..3191c69
--- /dev/null
+++ b/languages/Makefile
@@ -0,0 +1,8 @@
+include ../Rules.make
+clean:
+all:
+install:
+ install -d -m0755 $(LANGPATH)
+ for f in *.ini; do \
+ install -m0755 $$f $(LANGPATH)/$$f;\
+ done
diff --git a/languages/Makefile.windows b/languages/Makefile.windows
new file mode 100644
index 0000000..b0261f9
--- /dev/null
+++ b/languages/Makefile.windows
@@ -0,0 +1,7 @@
+include ../Rules.make
+
+clean:
+all:
+install:
+ if not exist ..\bin\languages mkdir ..\bin\languages
+ copy /Y *.ini ..\bin\languages
diff --git a/languages/en.ini b/languages/en.ini
new file mode 100644
index 0000000..b8a6fd4
--- /dev/null
+++ b/languages/en.ini
@@ -0,0 +1,107 @@
+;$Name:English$
+UNKNOWN_ERROR = Unknown error.
+ERROR_MENU = Error while loading game:\n\
+'%s'\n\
+\n\
+Ok
+
+WARNING_MENU = Error while processing game:\n\
+'%s'\n\
+\n\
+Ok
+
+SAVE_SLOT_EMPTY = empty
+SELECT_LOAD_MENU = Load game\n\n
+AUTOSAVE_SLOT = Autosave
+BROKEN_SLOT = error
+SELECT_SAVE_MENU = Save game\n\n
+
+MAIN_MENU = \
+Resume game\n\
+Select game\n\
+Select theme\n\
+Restart game\n\
+Load game\n\
+Save game\n\
+About\n\
+Settings\n\
+Quit
+
+ABOUT_MENU = \
+INSTEAD SDL - %s\n\
+\n\
+Written by Peter Kosyh '2009\n\
+Ported to Windows by Ilja Ryndin\n\
+\n\
+Homepage:\n\
+http://instead.googlecode.com\n\
+\n\
+Back
+
+BACK_MENU = Back
+ON = on
+OFF = off
+
+SELECT_GAME_MENU = Select game to play\n\n
+SELECT_THEME_MENU = Select theme\n\n
+
+SETTINGS_MENU = \
+Volume\n\
+<<< %d%% >>>\n\
+\n\
+Quality\n\
+<< %dHz >>\n\
+\n\
+Music: %s\n\
+Click sound: %s\n\
+\n\
+Full Screen: %s\n\
+Font scaling: <<%d>>\n\
+Refs highlighting: %s\n\
+Motion mode: %s\n\
+Mouse filter: %s\n\
+\n\
+Language: <<%s>>\n\
+Custom game themes: %s\n\
+Аutosave: %s\n\
+\n\
+Apply
+
+OWN_THEME_MENU = \
+Warning!!!\n\
+\n\
+Current game have custom theme.\n\
+So, changes will be ignored.\n\
+\n\
+You can disable custom themes\n\
+in settings menu.\n\
+\n\
+Ok
+
+CUSTOM_THEME_MENU = \
+Warning!!!\n\
+\n\
+This game have custom theme, but custom theme setting is disabled. \
+Game may look differ than author's design.\n\
+\n\
+You can enable custom theme support in settings menu.\n\
+\n\
+Ok
+
+QUIT_MENU = \
+Really quit?\n\
+\n\
+Yes | No
+
+SAVED_MENU = \
+Current Game saved!\n\
+\n\
+Ok
+
+NOGAMES_MENU = \
+No games found. \n\
+Please, put any game in the this directory:\n'%s'
+
+NOTHEMES_MENU = \
+No themes found.\n\
+Please, write any theme in this directory:\n'%s'
diff --git a/languages/ru.ini b/languages/ru.ini
new file mode 100644
index 0000000..b2ff8c7
--- /dev/null
+++ b/languages/ru.ini
@@ -0,0 +1,108 @@
+;$Name:Русский$
+
+UNKNOWN_ERROR = Неизвестная ошибка.
+ERROR_MENU = Во время инициализации игры произошла ошибка:\n\
+'%s'\n\
+\n\
+Да
+
+WARNING_MENU = Во время работы игры произошла ошибка:\n\
+'%s'\n\
+\n\
+Да
+
+SAVE_SLOT_EMPTY = пусто
+SELECT_LOAD_MENU = Загрузите игру\n\n
+AUTOSAVE_SLOT = Автосохранение
+BROKEN_SLOT = ошибка
+SELECT_SAVE_MENU = Сохраните игру\n\n
+
+MAIN_MENU = \
+Вернуться в игру\n\
+Выбор игры\n\
+Выбор темы\n\
+Начать заново\n\
+Загрузить игру\n\
+Сохранить игру\n\
+Информация\n\
+Настройки\n\
+Выход
+
+ABOUT_MENU = \
+INSTEAD SDL - %s\n\
+\n\
+Интерпретатор простых\n\
+текстовых приключений:\n\
+Косых П.А. '2009\n\
+\n\
+Адаптация для Windows:\n\
+Рындин И.В. '2009\n\
+\n\
+Сайт проекта:\n\
+http://instead.googlecode.com\n\
+\n\
+Назад
+
+BACK_MENU = Назад
+ON = Да
+OFF = Нет
+
+SETTINGS_MENU = \
+Громкость\n\
+<<< %d%% >>>\n\
+\n\
+Качество звука\n<< %dГц >>\n\
+\n\
+Музыка: %s\n\
+Звук щелчка: %s\n\
+\n\
+Полный экран: %s\n\
+Масштаб шрифта: <<%d>>\n\
+Подсветка ссылок: %s\n\
+Режим прокрутки: %s\n\
+Фильтр мышки: %s\n\
+\n\
+Язык интерфейса: <<%s>>\n\
+Собственные темы игр: %s\n\
+Автосохранение: %s\n\
+\n\
+Применить
+
+CUSTOM_THEME_MENU = \
+Внимание!!!\n\
+\n\
+Игра содержит собственную тему, но поддержка собственных тем отключена в настройках. \
+Игра может выглядеть не так, как задумывал ее автор.\n\
+\n\
+Вы можете разрешить возможность переопределения тем в настройках.\n\
+\n\
+Да
+
+OWN_THEME_MENU = \
+Внимание!!!\n\
+\n\
+Выбранная игра переопределяет тему. Изменения не вступят в силу.\n\
+\n\
+Вы можете запретить возможность переопределения тем в настройках.\n\
+\n\
+Да
+
+QUIT_MENU = \
+На самом деле выйти?\n\
+\n\
+Да | Нет
+
+SELECT_GAME_MENU = Выбор игры\n\n
+SELECT_THEME_MENU = Выбор темы\n\n
+SAVED_MENU = \
+Игра сохранена!\n\
+\n\
+Да
+
+NOGAMES_MENU = \
+Не найдена ни одна игра.\n\
+Пожалуйста, скопируйте хотя бы одну игру в каталог:\n'%s'
+
+NOTHEMES_MENU = \
+Не найдена ни одна тема.\n\
+Пожалуйста, скопируйте хотя бы одну тему в каталог:\n'%s'
diff --git a/src/sdl-instead/Makefile b/src/sdl-instead/Makefile
index d756552..1a5f69e 100644
--- a/src/sdl-instead/Makefile
+++ b/src/sdl-instead/Makefile
@@ -1,10 +1,10 @@
include ../../Rules.make
-CFLAGS += $(SDL_CFLAGS) $(LUA_CFLAGS) -DSTEAD_PATH=\"${STEADPATH}/\" -DGAMES_PATH=\"${GAMESPATH}/\" -DTHEMES_PATH=\"${THEMESPATH}/\" -DVERSION=$(VERSION) -DICON_PATH=\"${ICONPATH}/\"
+CFLAGS += $(SDL_CFLAGS) $(LUA_CFLAGS) -DLANG_PATH=\"${LANGPATH}/\" -DSTEAD_PATH=\"${STEADPATH}/\" -DGAMES_PATH=\"${GAMESPATH}/\" -DTHEMES_PATH=\"${THEMESPATH}/\" -DVERSION=$(VERSION) -DICON_PATH=\"${ICONPATH}/\"
LDFLAGS += $(SDL_LFLAGS) $(LUA_LFLAGS)
-SRC := graphics.c input.c game.c main.c instead.c sound.c SDL_rotozoom.c $(PLATFORM)
+SRC := graphics.c input.c game.c main.c instead.c sound.c SDL_rotozoom.c config.c themes.c menu.c util.c $(PLATFORM)
OBJ := $(patsubst %.c, %.o, $(SRC))
diff --git a/src/sdl-instead/config.c b/src/sdl-instead/config.c
new file mode 100644
index 0000000..ee504ae
--- /dev/null
+++ b/src/sdl-instead/config.c
@@ -0,0 +1,79 @@
+#include "externals.h"
+#include "internals.h"
+
+int opt_fsize = 0;
+#ifndef MAEMO
+int opt_fs = 0;
+int opt_owntheme = 1;
+int opt_hl = 1;
+#else
+int opt_fs = 1;
+int opt_owntheme = 0;
+int opt_hl = 0;
+#endif
+int opt_hz = 22050;
+int opt_vol = 127;
+int opt_motion = 1;
+int opt_click = 1;
+int opt_music = 1;
+int opt_autosave = 1;
+int opt_filter = 1;
+
+char *opt_game = NULL;
+char *opt_theme = NULL;
+char *opt_lang = NULL;
+
+static struct parser cfg_parser[] = {
+ { "hz", parse_int, &opt_hz },
+ { "fs", parse_int, &opt_fs },
+ { "vol", parse_int, &opt_vol },
+ { "hl", parse_int, &opt_hl },
+ { "game", parse_string, &opt_game },
+ { "theme", parse_string, &opt_theme },
+ { "autosave", parse_int, &opt_autosave },
+ { "motion", parse_int, &opt_motion },
+ { "click", parse_int, &opt_click },
+ { "music", parse_int, &opt_music },
+ { "fscale", parse_int, &opt_fsize },
+ { "filter", parse_int, &opt_filter },
+ { "owntheme", parse_int, &opt_owntheme },
+ { "lang", parse_string, &opt_lang },
+ { NULL, },
+};
+
+static int cfg_parse(const char *path)
+{
+ return parse_ini(path, cfg_parser);
+}
+
+int cfg_load(void)
+{
+ char *p = game_cfg_path();
+ if (!p)
+ return -1;
+ if (access(p, R_OK))
+ return 0;
+ return cfg_parse(p);
+}
+
+int cfg_save(void)
+{
+ FILE *fp;
+ char *p = game_cfg_path();
+ if (!p)
+ return -1;
+ fp = fopen(p, "w");
+ if (!fp)
+ return -1;
+ fprintf(fp, "fs = %d\nhl = %d\nhz = %d\nvol = %d\nautosave = %d\n\
+game = %s\nfscale = %d\nmotion = %d\n\
+click = %d\nmusic = %d\ntheme = %s\n\
+filter = %d\nowntheme = %d\nlang = %s",
+ opt_fs, opt_hl, opt_hz, opt_vol, opt_autosave,
+ curgame_dir?curgame_dir:"", opt_fsize, opt_motion,
+ opt_click, opt_music, curtheme_dir?curtheme_dir:DEFAULT_THEME,
+ opt_filter, opt_owntheme, opt_lang);
+ fclose(fp);
+ return 0;
+}
+
diff --git a/src/sdl-instead/config.h b/src/sdl-instead/config.h
new file mode 100644
index 0000000..03a0c3b
--- /dev/null
+++ b/src/sdl-instead/config.h
@@ -0,0 +1,24 @@
+#ifndef __CONFIG_H_INCLUDED
+#define __CONFIG_H_INCLUDED
+
+#define FONT_SZ(v) ((v) * (1.0f + ((0.1f * opt_fsize))))
+
+extern int opt_fsize;
+extern int opt_fs;
+extern int opt_owntheme;
+extern int opt_hl;
+extern int opt_hz;
+extern int opt_vol;
+extern int opt_motion;
+extern int opt_click;
+extern int opt_music;
+extern int opt_autosave;
+extern int opt_filter;
+extern char *opt_game;
+extern char *opt_theme;
+extern char *opt_lang;
+
+extern int cfg_load(void);
+extern int cfg_save(void);
+
+#endif
\ No newline at end of file
diff --git a/src/sdl-instead/externals.h b/src/sdl-instead/externals.h
new file mode 100644
index 0000000..b06c563
--- /dev/null
+++ b/src/sdl-instead/externals.h
@@ -0,0 +1,41 @@
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+// #include
+#include
+#ifdef _HAVE_ICONV
+#include
+#endif
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
diff --git a/src/sdl-instead/game.c b/src/sdl-instead/game.c
index cf35d67..b1d9f63 100644
--- a/src/sdl-instead/game.c
+++ b/src/sdl-instead/game.c
@@ -1,51 +1,12 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "graphics.h"
-#include "sound.h"
-#include "game.h"
-#include "input.h"
-#include "instead.h"
-
-#ifdef RUSSIAN
-#include "menu.h"
-#else
-#include "menu-en.h"
-#endif
-
-int opt_fsize = 0;
-#ifndef MAEMO
-int opt_fs = 0;
-int opt_owntheme = 1;
-int opt_hl = 1;
-#else
-int opt_fs = 1;
-int opt_owntheme = 0;
-int opt_hl = 0;
-#endif
-int opt_hz = 22050;
-int opt_vol = 127;
-int opt_motion = 1;
-int opt_click = 1;
-int opt_music = 1;
-int opt_autosave = 1;
-int opt_filter = 1;
-char *opt_game = NULL;
-char *opt_theme = NULL;
+#include "externals.h"
+#include "internals.h"
char *err_msg = NULL;
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
#define ERR_MSG_MAX 512
+char game_cwd[PATH_MAX];
+char *curgame_dir = NULL;
+
+int game_own_theme = 0;
void game_err_msg(const char *s)
{
@@ -61,593 +22,6 @@ void game_err_msg(const char *s)
err_msg = NULL;
}
-char game_cwd[PATH_MAX];
-char *curgame = NULL;
-char *curgame_dir = NULL;
-static int own_theme = 0;
-char *curtheme = NULL;
-char *curtheme_dir = NULL;
-int cfg_parse(const char *path);
-
-extern char *game_cfg_path(void);
-extern char *game_save_path(int rc, int nr);
-
-int game_save(int nr);
-
-int cfg_load(void)
-{
- char *p = game_cfg_path();
- if (!p)
- return -1;
- if (access(p, R_OK))
- return 0;
- return cfg_parse(p);
-}
-
-int cfg_save(void)
-{
- FILE *fp;
- char *p = game_cfg_path();
- if (!p)
- return -1;
- fp = fopen(p, "w");
- if (!fp)
- return -1;
- fprintf(fp, "fs = %d\nhl = %d\nhz = %d\nvol = %d\nautosave = %d\n\
-game = %s\nfscale = %d\nmotion = %d\n\
-click = %d\nmusic = %d\ntheme = %s\n\
-filter = %d\nowntheme = %d",
- opt_fs, opt_hl, opt_hz, opt_vol, opt_autosave,
- curgame_dir?curgame_dir:"", opt_fsize, opt_motion,
- opt_click, opt_music, curtheme_dir?curtheme_dir:DEFAULT_THEME,
- opt_filter, opt_owntheme);
- fclose(fp);
- return 0;
-}
-
-void game_menu_box(int show, const char *txt);
-
-void game_cursor(int on);
-
-#define GFX_MODE_FLOAT 0
-#define GFX_MODE_FIXED 1
-#define GFX_MODE_EMBEDDED 2
-
-#define INV_MODE_VERT 0
-#define INV_MODE_HORIZ 1
-
-struct game_theme {
- int w;
- int h;
- color_t bgcol;
- char *bg_name;
- img_t bg;
- char *use_name;
- img_t use;
- int pad;
-
- int win_x;
- int win_y;
- int win_w;
- int win_h;
-
- char *font_name;
- int font_size;
- fnt_t font;
-
- int gfx_x;
- int gfx_y;
- int max_scene_w;
- int max_scene_h;
-
- char *a_up_name;
- char *a_down_name;
- img_t a_up;
- img_t a_down;
-
- color_t fgcol;
- color_t lcol;
- color_t acol;
-
- int inv_x;
- int inv_y;
- int inv_w;
- int inv_h;
-
- color_t icol;
- color_t ilcol;
- color_t iacol;
- char *inv_font_name;
- int inv_font_size;
- fnt_t inv_font;
-
- char *inv_a_up_name;
- char *inv_a_down_name;
- img_t inv_a_up;
- img_t inv_a_down;
-
-// int lstyle;
-// int ilstyle;
-
- color_t menu_bg;
- color_t menu_fg;
- color_t border_col;
- color_t menu_link;
- color_t menu_alink;
- int menu_alpha;
- int border_w;
- char *menu_font_name;
- int menu_font_size;
- fnt_t menu_font;
-
- char *menu_button_name;
- img_t menu_button;
- int menu_button_x;
- int menu_button_y;
- int gfx_mode;
- int inv_mode;
- char *click_name;
- void *click;
-} game_theme = {
- .w = 800,
- .h = 480,
- .bg_name = NULL,
- .bg = NULL,
- .use_name = NULL,
- .use = NULL,
- .font_name = NULL,
- .font = NULL,
- .a_up_name = NULL,
- .a_down_name = NULL,
- .a_up = NULL,
- .a_down = NULL,
- .inv_font_name = NULL,
- .inv_font = NULL,
- .inv_a_up_name = NULL,
- .inv_a_down_name = NULL,
- .inv_a_up = NULL,
- .inv_a_down = NULL,
- .menu_font_name = NULL,
- .menu_font = NULL,
- .menu_button_name = NULL,
- .menu_button = NULL,
- .gfx_mode = GFX_MODE_EMBEDDED,
- .inv_mode = INV_MODE_VERT,
- .click_name = NULL,
- .click = NULL,
-};
-
-#define FREE(v) do { if ((v)) free((v)); v = NULL; } while(0)
-
-void free_theme_strings()
-{
- struct game_theme *t = &game_theme;
- FREE(t->use_name);
- FREE(t->bg_name);
- FREE(t->inv_a_up_name);
- FREE(t->inv_a_down_name);
- FREE(t->a_down_name);
- FREE(t->a_up_name);
- FREE(t->font_name);
- FREE(t->inv_font_name);
- FREE(t->menu_font_name);
- FREE(t->menu_button_name);
-/* FREE(t->click_name); must be reloaded, ugly :(*/
-}
-
-int game_theme_free(void)
-{
- free_theme_strings();
-
- if (game_theme.font)
- fnt_free(game_theme.font);
- if (game_theme.inv_font)
- fnt_free(game_theme.inv_font);
- if (game_theme.menu_font)
- fnt_free(game_theme.menu_font);
-
- if (game_theme.a_up)
- gfx_free_image(game_theme.a_up);
- if (game_theme.a_down)
- gfx_free_image(game_theme.a_down);
- if (game_theme.inv_a_up)
- gfx_free_image(game_theme.inv_a_up);
- if (game_theme.inv_a_down)
- gfx_free_image(game_theme.inv_a_down);
-
- if (game_theme.use)
- gfx_free_image(game_theme.use);
-
- if (game_theme.bg)
- gfx_free_image(game_theme.bg);
-
- if (game_theme.menu_button)
- gfx_free_image(game_theme.menu_button);
-
- if (game_theme.click)
- snd_free_wav(game_theme.click);
-
- game_theme.font = game_theme.inv_font = game_theme.menu_font = NULL;
- game_theme.a_up = game_theme.a_down = game_theme.use = NULL;
- game_theme.inv_a_up = game_theme.inv_a_down = NULL;
- game_theme.menu_button = NULL;
- game_theme.bg = NULL;
- game_theme.click = NULL;
-// game_theme.slide = gfx_load_image("slide.png", 1);
- return 0;
-}
-
-#define FONT_SZ(v) ((v) * (1.0f + ((0.1f * opt_fsize))))
-
-int game_theme_init(void)
-{
- struct game_theme *t = &game_theme;
-
- if (t->font_name) {
- fnt_free(t->font);
- if (!(t->font = fnt_load(t->font_name, FONT_SZ(t->font_size))))
- goto err;
- }
-
- if (t->inv_font_name) {
- fnt_free(t->inv_font);
- if (!(t->inv_font = fnt_load(t->inv_font_name, FONT_SZ(t->inv_font_size))))
- goto err;
- }
-
-
- if (t->menu_font_name) {
- fnt_free(t->menu_font);
- if (!(t->menu_font = fnt_load(t->menu_font_name, t->menu_font_size))) /* do not scale menu!!! */
- goto err;
- }
-
-
- if (t->a_up_name) {
- gfx_free_image(t->a_up);
- if (!(t->a_up = gfx_load_image(t->a_up_name)))
- goto err;
- }
-
- if (t->a_down_name) {
- gfx_free_image(t->a_down);
- if (!(t->a_down = gfx_load_image(t->a_down_name)))
- goto err;
- }
-
- if (t->inv_a_up_name) {
- gfx_free_image(t->inv_a_up);
- if (!(t->inv_a_up = gfx_load_image(t->inv_a_up_name)))
- goto err;
- }
-
-
- if (t->inv_a_down_name) {
- gfx_free_image(t->inv_a_down);
- if (!(t->inv_a_down = gfx_load_image(t->inv_a_down_name)))
- goto err;
- }
-
- if (t->bg_name) {
- gfx_free_image(t->bg);
- t->bg = NULL;
- if (t->bg_name[0] && !(t->bg = gfx_load_image(t->bg_name)))
- goto err;
- }
-
- if (t->use_name) {
- gfx_free_image(t->use);
- if (!(t->use = gfx_load_image(t->use_name)))
- goto err;
- }
-
- if (t->menu_button_name) {
- gfx_free_image(t->menu_button);
- if (!(t->menu_button = gfx_load_image(t->menu_button_name)))
- goto err;
- }
-
- if (t->click_name) {
- snd_free_wav(t->click);
- t->click = snd_load_wav(t->click_name);
- }
-
- free_theme_strings();
-
- if (!t->use || !t->inv_a_up || !t->inv_a_down || !t->a_down || !t->a_up ||
- !t->font || !t->inv_font || !t->menu_font || !t->menu_button) {
- fprintf(stderr,"Can't init theme.\n");
- return -1;
- }
- return 0;
-err:
- fprintf(stderr, "Can not init theme!\n");
- game_theme_free();
- return -1;
-}
-
-typedef int (*parser_fn)(const char *v, void *data);
-
-int parse_string(const char *v, void *data)
-{
- char **p = ((char **)data);
- if (*p)
- free(*p);
- *p = strdup(v);
- if (!*p)
- return -1;
- return 0;
-}
-
-int parse_gfx_mode(const char *v, void *data)
-{
- int *i = (int *)data;
- if (!strcmp(v, "fixed"))
- *i = GFX_MODE_FIXED;
- else if (!strcmp(v, "embedded"))
- *i = GFX_MODE_EMBEDDED;
- else if (!strcmp(v, "float"))
- *i = GFX_MODE_FLOAT;
- else
- return -1;
- return 0;
-}
-
-int parse_inv_mode(const char *v, void *data)
-{
- int *i = (int *)data;
- if (!strcmp(v, "vertical") || !strcmp(v, "0"))
- *i = INV_MODE_VERT;
- else if (!strcmp(v, "horizontal") || !strcmp(v, "1"))
- *i = INV_MODE_HORIZ;
- else
- return -1;
- return 0;
-}
-
-int parse_full_path(const char *v, void *data)
-{
- char cwd[PATH_MAX];
- char **p = ((char **)data);
- if (*p)
- free(*p);
- getcwd(cwd, sizeof(cwd));
- *p = malloc(strlen(v) + strlen(cwd) + 2);
- if (!*p)
- return -1;
- strcpy(*p, cwd);
- strcat(*p,"/");
- strcat(*p, v);
- return 0;
-}
-
-int parse_int(const char *v, void *data)
-{
- int *i = (int *)data;
- char *eptr = NULL;
- *i = strtol(v, &eptr, 0);
- if (!eptr || *eptr)
- return -1;
- return 0;
-}
-
-int parse_color(const char *v, void *data)
-{
- color_t *c = (color_t *)data;
- return gfx_parse_color(v, c);
-}
-int game_theme_load(const char *name);
-int game_theme_select(const char *name);
-
-int parse_include(const char *v, void *data)
-{
- int rc;
- char cwd[PATH_MAX];
- if (!strcmp(v, DEFAULT_THEME))
- return 0;
- getcwd(cwd, sizeof(cwd));
- chdir(game_cwd);
- rc = game_theme_load(v);
-// if (!rc)
-// game_theme_select(v);
- chdir(cwd);
- return rc;
-}
-
-struct parser {
- const char *cmd;
- parser_fn fn;
- void *p;
-};
-
-struct parser cfg_parser[] = {
- { "hz", parse_int, &opt_hz },
- { "fs", parse_int, &opt_fs },
- { "vol", parse_int, &opt_vol },
- { "hl", parse_int, &opt_hl },
- { "game", parse_string, &opt_game },
- { "theme", parse_string, &opt_theme },
- { "autosave", parse_int, &opt_autosave },
- { "motion", parse_int, &opt_motion },
- { "click", parse_int, &opt_click },
- { "music", parse_int, &opt_music },
- { "fscale", parse_int, &opt_fsize },
- { "filter", parse_int, &opt_filter },
- { "owntheme", parse_int, &opt_owntheme },
- { NULL, },
-};
-
-struct parser cmd_parser[] = {
- { "scr.w", parse_int, &game_theme.w },
- { "scr.h", parse_int, &game_theme.h },
- { "scr.col.bg", parse_color, &game_theme.bgcol },
- { "scr.gfx.bg", parse_string, &game_theme.bg_name },
- { "scr.gfx.use", parse_string, &game_theme.use_name },
- { "scr.gfx.pad", parse_int, &game_theme.pad },
- { "scr.gfx.x", parse_int, &game_theme.gfx_x },
- { "scr.gfx.y", parse_int, &game_theme.gfx_y },
- { "scr.gfx.w", parse_int, &game_theme.max_scene_w },
- { "scr.gfx.h", parse_int, &game_theme.max_scene_h },
- { "scr.gfx.mode", parse_gfx_mode, &game_theme.gfx_mode },
-
- { "win.x", parse_int, &game_theme.win_x },
- { "win.y", parse_int, &game_theme.win_y },
- { "win.w", parse_int, &game_theme.win_w },
- { "win.h", parse_int, &game_theme.win_h },
- { "win.fnt.name", parse_string, &game_theme.font_name },
- { "win.fnt.size", parse_int, &game_theme.font_size },
-/* compat mode directive */
- { "win.gfx.h", parse_int, &game_theme.max_scene_h },
-/* here it was */
- { "win.gfx.up", parse_string, &game_theme.a_up_name },
- { "win.gfx.down", parse_string, &game_theme.a_down_name },
- { "win.col.fg", parse_color, &game_theme.fgcol },
- { "win.col.link", parse_color, &game_theme.lcol },
- { "win.col.alink", parse_color, &game_theme.acol },
-
- { "inv.x", parse_int, &game_theme.inv_x },
- { "inv.y", parse_int, &game_theme.inv_y },
- { "inv.w", parse_int, &game_theme.inv_w },
- { "inv.h", parse_int, &game_theme.inv_h },
- { "inv.mode", parse_inv_mode, &game_theme.inv_mode },
- { "inv.horiz", parse_inv_mode, &game_theme.inv_mode },
-
- { "inv.col.fg", parse_color, &game_theme.icol },
- { "inv.col.link", parse_color, &game_theme.ilcol },
- { "inv.col.alink", parse_color, &game_theme.iacol },
- { "inv.fnt.name", parse_string, &game_theme.inv_font_name },
- { "inv.fnt.size", parse_int, &game_theme.inv_font_size },
- { "inv.gfx.up", parse_string, &game_theme.inv_a_up_name },
- { "inv.gfx.down", parse_string, &game_theme.inv_a_down_name },
-
- { "menu.col.bg", parse_color, &game_theme.menu_bg },
- { "menu.col.fg", parse_color, &game_theme.menu_fg },
- { "menu.col.link", parse_color, &game_theme.menu_link },
- { "menu.col.alink", parse_color, &game_theme.menu_alink },
- { "menu.col.alpha", parse_int, &game_theme.menu_alpha },
- { "menu.col.border", parse_color, &game_theme.border_col },
- { "menu.bw", parse_int, &game_theme.border_w },
- { "menu.fnt.name", parse_string, &game_theme.menu_font_name },
- { "menu.fnt.size", parse_int, &game_theme.menu_font_size },
- { "menu.gfx.button", parse_string, &game_theme.menu_button_name },
- { "menu.button.x", parse_int, &game_theme.menu_button_x },
- { "menu.button.y", parse_int, &game_theme.menu_button_y },
-/* compat */
- { "menu.buttonx", parse_int, &game_theme.menu_button_x },
- { "menu.buttony", parse_int, &game_theme.menu_button_y },
-
- { "snd.click", parse_full_path, &game_theme.click_name },
- { "include", parse_include, NULL },
- { NULL, },
-};
-
-char *strip(char *s)
-{
- char *e;
- while (isspace(*s))
- s ++;
- if (!*s)
- return s;
- e = s + strlen(s) - 1;
- while (e != s && isspace(*e)) {
- *e = 0;
- e --;
- }
- return s;
-}
-
-int process_cmd(char *n, char *v, struct parser *cmd_parser)
-{
- int i;
- n = strip(n);
- v = strip(v);
- for (i = 0; cmd_parser[i].cmd; i++) {
- if (!strcmp(cmd_parser[i].cmd, n)) {
- return cmd_parser[i].fn(v, cmd_parser[i].p);
- }
- }
- return -1;
-}
-
-int parse_ini(const char *path, struct parser *cmd_parser)
-{
- int rc = 0;
- int line_nr = 0;
- FILE *fp;
- char line[1024];
- fp = fopen(path, "r");
- if (!fp)
- return -1;
- while (fgets(line, sizeof(line), fp)) {
- char *p = line;
- char *val;
- int len;
- line_nr ++;
- p += strspn(p, " \t");
- if (*p == ';')
- continue;
- len = strcspn(p, "=");
- if (p[len] != '=') /* just ignore it */
- continue;
- p[len] = 0;
- val = p + len + 1;
- len = strcspn(p, " \t");
- p[len] = 0;
-// printf("%s\n", p);
- val += strspn(val, " \t");
- val[strcspn(val, ";\n")] = 0;
- if (process_cmd(p, val, cmd_parser)) {
- rc = -1;
- fprintf(stderr, "Can't process cmd '%s' on line %d : %s\n", p, line_nr, strerror(errno));
- }
- }
- fclose(fp);
- return rc;
-}
-
-int theme_parse(const char *path)
-{
- if (parse_ini(path, cmd_parser)) {
- fprintf(stderr, "Theme parsed with errors!\n");
-// game_theme_free();
- return -1;
- }
- return 0;
-}
-
-int theme_load(const char *name)
-{
- if (theme_parse(name))
- return 0; /* no theme loaded if error in parsing */
- if (game_theme_init())
- return -1;
- return 0;
-}
-
-int cfg_parse(const char *path)
-{
- return parse_ini(path, cfg_parser);
-}
-
-char *getfilepath(const char *d, const char *n)
-{
- int i = strlen(d) + strlen(n) + 3;
- char *p = malloc(i);
- if (p) {
- strcpy(p, d);
- strcat(p, "/");
- strcat(p, n);
- }
- return p;
-}
-
-char *getpath(const char *d, const char *n)
-{
- char *p = getfilepath(d, n);
- strcat(p, "/");
- return p;
-}
-
static int is_game(const char *path, const char *n)
{
@@ -668,20 +42,15 @@ static int is_game(const char *path, const char *n)
return rc;
}
-struct game {
- char *path;
- char *name;
- char *dir;
-};
-
struct game *games = NULL;
int games_nr = 0;
-
-
+void free_last(void);
+
int game_select(const char *name)
{
int i;
+ free_last();
if (!name || !*name) {
if (games_nr == 1)
name = games[0].dir;
@@ -698,7 +67,6 @@ int game_select(const char *name)
return -1;
if (instead_load(MAIN_FILE))
return -1;
- curgame = games[i].name;
curgame_dir = games[i].dir;
return 0;
}
@@ -706,22 +74,6 @@ int game_select(const char *name)
return 0;
}
-static char *parse_tag(char *line, const char *tag, const char *comm, int *brk)
-{
- char *l = line;
- l += strspn(l, " \t");
- if (strncmp(l, comm, strlen(comm))) { /* non coment block */
- *brk = 1;
- return NULL;
- }
- l += strlen(comm); l += strspn(l, " \t");
- if (strncmp(l, tag, strlen(tag)))
- return NULL;
- l += strlen(tag);
- l += strspn(l, " \t");
- l[strcspn(l, "$\n\r")] = 0;
- return strdup(l);
-}
static char *game_name(const char *path, const char *d_name)
{
@@ -786,142 +138,6 @@ int games_lookup(const char *path)
return 0;
}
-struct theme *themes = NULL;
-int themes_nr = 0;
-
-struct theme {
- char *path;
- char *name;
- char *dir;
-};
-
-static int is_theme(const char *path, const char *n)
-{
- int rc = 0;
- char *p = getpath(path, n);
- char *pp;
- if (!p)
- return 0;
- pp = malloc(strlen(p) + strlen(THEME_FILE) + 1);
- if (pp) {
- strcpy(pp, p);
- strcat(pp, THEME_FILE);
- if (!access(pp, R_OK))
- rc = 1;
- free(pp);
- }
- free(p);
- return rc;
-}
-
-static char *theme_name(const char *path, const char *d_name)
-{
- int brk = 0;
- char *p = getfilepath(path, THEME_FILE);
- if (p) {
- char *l; char line[1024];
- FILE *fd = fopen(p, "r");
- free(p);
- if (!fd)
- goto err;
-
- while ((l = fgets(line, sizeof(line), fd)) && !brk) {
- l = parse_tag(l, "$Name:", ";", &brk);
- if (l)
- return l;
- }
- fclose(fd);
- }
-err:
- return strdup(d_name);
-}
-
-int themes_lookup(const char *path)
-{
- char *p;
- int n = 0, i = 0;
- DIR *d;
- struct dirent *de;
-
- if (!path)
- return 0;
-
- d = opendir(path);
- if (!d)
- return -1;
- while ((de = readdir(d))) {
- if (!is_theme(path, de->d_name))
- continue;
- n ++;
- }
-
- rewinddir(d);
- if (!n)
- return 0;
- themes = realloc(themes, sizeof(struct theme) * (n + themes_nr));
- while ((de = readdir(d)) && i < n) {
- /*if (de->d_type != DT_DIR)
- continue;*/
- if (!is_theme(path, de->d_name))
- continue;
- p = getpath(path, de->d_name);
- themes[themes_nr].path = p;
- themes[themes_nr].dir = strdup(de->d_name);
- themes[themes_nr].name = theme_name(p, de->d_name);
- themes_nr ++;
- i ++;
- }
- closedir(d);
- return 0;
-}
-
-int theme_load(const char *name);
-
-struct theme *theme_lookup(const char *name)
-{
- int i;
- if (!name || !*name) {
- if (themes_nr == 1)
- return &themes[0];
- }
- for (i = 0; ipath) || theme_load(THEME_FILE)) {
- chdir(cwd);
- return -1;
- }
- chdir(cwd);
- return 0;
-}
-
-int game_theme_select(const char *name)
-{
- struct theme *theme;
- theme = theme_lookup(name);
- if (!theme)
- return -1;
- curtheme = theme->name;
- curtheme_dir = theme->dir;
- return 0;
-}
-
-int game_default_theme(void)
-{
- return game_theme_load(DEFAULT_THEME);
-}
static int motion_mode = 0;
static int motion_id = 0;
@@ -933,28 +149,10 @@ static char *last_music = NULL;
static int mx, my;
static img_t menubg = NULL;
static img_t menu = NULL;
-static int cur_menu = 0;
+
static int menu_shown = 0;
-enum {
- menu_main = 0,
- menu_about,
- menu_settings,
- menu_quit,
- menu_askquit,
- menu_saved,
- menu_games,
- menu_themes,
- menu_own_theme,
- menu_custom_theme,
- menu_load,
- menu_save,
- menu_error,
- menu_warning,
-};
int game_cmd(char *cmd);
-int change_vol(int d, int val);
-
void game_clear(int x, int y, int w, int h)
{
if (game_theme.bg)
@@ -972,11 +170,8 @@ void game_clear(int x, int y, int w, int h)
}
}
-
-
void game_clear(int x, int y, int w, int h);
-
struct el {
int id;
int x;
@@ -1057,8 +252,7 @@ char *game_menu_gen(void);
void game_menu(int nr)
{
cur_menu = nr;
- menu_shown = 1;
- game_menu_box(menu_shown, game_menu_gen());
+ game_menu_box(1, game_menu_gen());
}
int game_error(const char *name)
@@ -1074,17 +268,10 @@ int game_error(const char *name)
void el_draw(int n);
-static void custom_theme_warn(void)
-{
- if (own_theme && !opt_owntheme) {
- game_menu(menu_custom_theme);
- }
-}
-
int window_sw = 0;
int fullscreen_sw = 0;
-static int game_load(int nr)
+int game_load(int nr)
{
char *s;
s = game_save_path(0, nr);
@@ -1100,6 +287,21 @@ static int game_load(int nr)
return -1;
}
+int game_save(int nr)
+{
+ char *s = game_save_path(1, nr);
+ char cmd[PATH_MAX];
+ char *p;
+ if (s) {
+ snprintf(cmd, sizeof(cmd) - 1, "save %s", s);
+ p = instead_cmd(cmd);
+ if (p)
+ free(p);
+ return 0;
+ }
+ return -1;
+}
+
int game_apply_theme(void)
{
layout_t lay;
@@ -1172,9 +374,83 @@ int game_apply_theme(void)
return 0;
}
+int game_restart(void)
+{
+ char *og = curgame_dir;
+ game_save(-1);
+ game_done();
+ if (game_init(og)) {
+ game_error(og);
+ return 0;
+ }
+ return 0;
+}
+int static cur_vol = 0;
+void free_last_music(void);
+
+void game_stop_mus(int ms)
+{
+ snd_stop_mus(ms);
+ free_last_music();
+}
+
+int game_change_vol(int d, int val)
+{
+ int v = snd_volume_mus(-1);
+ int pc = snd_vol_to_pcn(v);
+ int opc = pc;
+ if (d) {
+ pc += d;
+ if (pc < 0)
+ pc = 0;
+ if (pc > 100)
+ pc = 100;
+ while (snd_vol_to_pcn(v) != pc)
+ v += (d<0)?-1:1;
+ } else {
+ v = val;
+ pc = snd_vol_to_pcn(v);
+ }
+ if (!pc)
+ v = 0;
+ snd_volume_mus(v);
+ if (opc && !pc) {
+ game_stop_mus(0);
+ }
+ if (!opc && pc) {
+ game_music_player();
+ }
+ cur_vol = snd_volume_mus(-1);
+ opt_vol = cur_vol;
+ return 0;
+}
+
+int game_change_hz(int hz)
+{
+ if (!hz)
+ return -1;
+ snd_done();
+ free_last_music();
+ snd_init(hz);
+ snd_volume_mus(cur_vol);
+ snd_free_wav(game_theme.click);
+ game_theme.click = snd_load_wav(game_theme.click_name);
+ game_music_player();
+ opt_hz = snd_hz();
+ return 0;
+}
+
+
int game_init(const char *name)
{
getcwd(game_cwd, sizeof(game_cwd));
+
+ if (!opt_lang || !opt_lang[0])
+ opt_lang = game_locale();
+
+ if (menu_lang_select(opt_lang) && menu_lang_select(LANG_DEF))
+ return -1;
+
if (name)
game_err_msg(NULL);
@@ -1182,7 +458,7 @@ int game_init(const char *name)
return -1;
snd_init(opt_hz);
- change_vol(0, opt_vol);
+ game_change_vol(0, opt_vol);
if (game_default_theme()) {
fprintf(stderr, "Can't load default theme.\n");
@@ -1192,11 +468,11 @@ int game_init(const char *name)
if (game_select(name))
return -1;
- if (curgame && !access(THEME_FILE, R_OK)) {
- own_theme = 1;
+ if (curgame_dir && !access(THEME_FILE, R_OK)) {
+ game_own_theme = 1;
}
- if (own_theme && opt_owntheme) {
+ if (game_own_theme && opt_owntheme) {
if (theme_load(THEME_FILE))
return -1;
} else if (curtheme_dir && strcmp(DEFAULT_THEME, curtheme_dir)) {
@@ -1206,7 +482,7 @@ int game_init(const char *name)
if (game_apply_theme())
return -1;
- if (!curgame) {
+ if (!curgame_dir) {
game_menu(menu_games);
} else {
if (!game_load(-1)) /* tmp save */
@@ -1235,15 +511,14 @@ void free_last(void)
free(last_pict);
if (last_title)
free(last_title);
- free_last_music();
last_pict = last_title = NULL;
- snd_stop_mus(500);
+ game_stop_mus(500);
}
void game_done(void)
{
int i;
- if (opt_autosave && curgame)
+ if (opt_autosave && curgame_dir)
game_save(0);
chdir(game_cwd);
// cfg_save();
@@ -1284,9 +559,8 @@ void game_done(void)
snd_done();
instead_done();
gfx_done();
- curgame = NULL;
curgame_dir = NULL;
- own_theme = 0;
+ game_own_theme = 0;
// SDL_Quit();
}
@@ -1453,470 +727,6 @@ img_t game_pict_scale(img_t img, int ww, int hh)
}
-int vol_from_pcn(int v)
-{
- return (v * 127) / 100;
-}
-
-int vol_to_pcn(int v)
-{
- return (v * 100) / 127;
-}
-void music_player(void);
-
-int static old_vol = 0;
-int static cur_vol = 0;
-
-int change_vol(int d, int val)
-{
- int v = snd_volume_mus(-1);
- int pc = vol_to_pcn(v);
- int opc = pc;
- if (d) {
- pc += d;
- if (pc < 0)
- pc = 0;
- if (pc > 100)
- pc = 100;
- while (vol_to_pcn(v) != pc)
- v += (d<0)?-1:1;
- } else {
- v = val;
- pc = vol_to_pcn(v);
- }
- if (!pc)
- v = 0;
- snd_volume_mus(v);
- if (opc && !pc) {
- snd_stop_mus(0);
- free_last_music();
- }
- if (!opc && pc) {
- music_player();
- }
- cur_vol = snd_volume_mus(-1);
- opt_vol = cur_vol;
- return 0;
-}
-
-int change_hz(int hz)
-{
- if (!hz)
- return -1;
- snd_done();
- free_last_music();
- snd_init(hz);
- snd_volume_mus(cur_vol);
- snd_free_wav(game_theme.click);
- game_theme.click = snd_load_wav(game_theme.click_name);
- music_player();
- opt_hz = snd_hz();
- return 0;
-}
-static int games_menu_from = 0;
-
-static int themes_menu_from = 0;
-
-int game_save(int nr)
-{
- char *s = game_save_path(1, nr);
- char cmd[PATH_MAX];
- char *p;
- if (s) {
- snprintf(cmd, sizeof(cmd) - 1, "save %s", s);
- p = instead_cmd(cmd);
- if (p)
- free(p);
- return 0;
- }
- return -1;
-}
-static int restart_needed = 0;
-
-static int game_restart(void)
-{
- if (restart_needed) {
- restart_needed = 0;
- char *og = curgame_dir;
- game_save(-1);
- game_done();
- if (game_init(og)) {
- game_error(og);
- return 0;
- }
- }
- return 0;
-}
-
-int game_menu_act(const char *a)
-{
- if (!strcmp(a, "/autosave")) {
- opt_autosave ^= 1;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/owntheme")) {
- opt_owntheme ^= 1;
- if (own_theme)
- restart_needed = 1;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/motion")) {
- opt_motion ^= 1;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/filter")) {
- opt_filter ^= 1;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/click")) {
- opt_click ^= 1;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/fs--")) {
- opt_fsize --;
- if (FONT_SZ(game_theme.font_size) > FONT_MIN_SZ) {
- restart_needed = 1;
- } else
- opt_fsize ++;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/fs++")) {
- opt_fsize ++;
- if (FONT_SZ(game_theme.font_size) < FONT_MAX_SZ) {
- restart_needed = 1;
- } else
- opt_fsize --;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/hl")) {
- opt_hl ^= 1;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/fs")) {
- restart_needed = 1;
- opt_fs ^= 1;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/games_prev")) {
- games_menu_from -= MENU_GAMES_MAX;
- if (games_menu_from < 0)
- games_menu_from = 0;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/games_next")) {
- if (games_menu_from + MENU_GAMES_MAX < games_nr)
- games_menu_from += MENU_GAMES_MAX;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/themes_prev")) {
- themes_menu_from -= MENU_THEMES_MAX;
- if (themes_menu_from < 0)
- themes_menu_from = 0;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/themes_next")) {
- if (themes_menu_from + MENU_THEMES_MAX < themes_nr)
- themes_menu_from += MENU_THEMES_MAX;
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/select")) {
- game_menu(menu_games);
- } else if (!strcmp(a, "/themes")) {
- game_menu(menu_themes);
- } else if (!strcmp(a, "/save_menu")) {
- if (curgame)
- game_menu(menu_save);
- } else if (!strncmp(a, "/save", 5)) {
- if (!game_save(atoi(a + 5))) {
- game_menu(menu_saved);
- }
- } else if (!strcmp(a, "/load_menu")) {
- if (curgame)
- game_menu(menu_load);
- } else if (!strncmp(a, "/load", 5)) {
- int nr = atoi(a + 5);
- if (!curgame_dir)
- return 0;
-
- free_last();
- game_select(curgame_dir);
- menu_shown = 0;
- game_menu_box(0, NULL);
- game_load(nr);
- cur_menu = menu_main;
-// game_menu_box(0, NULL);
- } else if (!strcmp(a, "/new")) {
- char *s;
- if (!curgame_dir)
- return 0;
- free_last();
- game_select(curgame_dir);
- menu_shown = 0;
- game_menu_box(0, NULL);
- instead_eval("game:ini()");
- game_cmd("look");
- s = game_save_path(0, 0);
- if (s && !access(s, R_OK) && opt_autosave)
- unlink (s);
- custom_theme_warn();
- } else if (!strcmp(a,"/main")) {
- game_restart();
- game_menu(menu_main);
- } else if (!strcmp(a,"/ask_quit")) {
- game_menu(menu_askquit);
- } else if (!strcmp(a,"/about")) {
- game_menu(menu_about);
- } else if (!strcmp(a,"/mtoggle")) {
- if (!old_vol) {
- old_vol = snd_volume_mus(-1);
- change_vol(0, 0);
- } else {
- change_vol(0, old_vol);
- old_vol = 0;
- }
- } else if (!strcmp(a,"/music")) {
- opt_music ^= 1;
- if (!opt_music) {
- snd_stop_mus(0);
- free_last_music();
- } else
- music_player();
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a,"/resume")) {
- menu_shown = 0;
- cur_menu = menu_main;
- game_menu_box(0, NULL);
- } else if (!strcmp(a, "/settings")) {
- game_menu(menu_settings);
- } else if (!strcmp(a, "/vol--")) {
- change_vol(-10, 0);
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/vol++")) {
- change_vol(+10, 0);
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/vol-")) {
- change_vol(-1, 0);
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/vol+")) {
- change_vol(+1, 0);
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/hz-")) {
- int hz = snd_hz();
- if (hz == 48000)
- hz = 44100;
- else if (hz == 44100)
- hz = 22050;
- else if (hz == 22050)
- hz = 11025;
- else
- hz = 0;
- change_hz(hz);
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a, "/hz+")) {
- int hz = snd_hz();
- if (hz == 11025)
- hz = 22050;
- else if (hz == 22050)
- hz = 44100;
- else if (hz == 44100)
- hz = 48000;
- else
- hz = 0;
- change_hz(hz);
- game_menu_box(menu_shown, game_menu_gen());
- } else if (!strcmp(a,"/quit")) {
- return -1;
- } else if (cur_menu == menu_games) {
- char *p;
- p = strdup(a);
- if (p) {
- game_done();
- if (game_init(p)) {
- game_error(p);
- }
- free(p);
- }
- } else if (cur_menu == menu_themes) {
- char *p;
- p = strdup(a);
- if (p) {
- if (game_theme_select(p))
- fprintf(stderr, "Can't select theme:%s:%s\n", p, strerror(errno));
- char *og = curgame_dir;
- game_save(-1);
- game_done();
- if (game_init(og))
- game_error(og);
- else if (curgame && own_theme && opt_owntheme) {
- game_menu(menu_own_theme);
- }
- free(p);
- }
- }
- return 0;
-}
-
-char menu_buff[4096];
-
-char *slot_name(const char *path)
-{
- struct stat st;
- int brk = 0;
- char *l; char line[1024];
- FILE *fd = fopen(path, "r");
- if (!fd)
- return NULL;
-
- while ((l = fgets(line, sizeof(line), fd)) && !brk) {
- l = parse_tag(l, "$Name:", "--", &brk);
- if (l) {
- char *s = fromgame(l);
- free(l);
- return s;
- }
- }
- fclose(fd);
- if (stat(path, &st))
- return NULL;
- l = ctime(&st.st_ctime);
- if (!l)
- return NULL;
- l[strcspn(l,"\n")] = 0;
- return strdup(l);
-}
-
-void load_menu(void)
-{
- int i;
- *menu_buff = 0;
- sprintf(menu_buff, SELECT_LOAD_MENU);
- for (i = 0; i < MAX_SAVE_SLOTS; i ++) {
- char tmp[PATH_MAX];
- char *s = game_save_path(0, i);
- if (!s || access(s, R_OK)) {
- if (!i)
- continue;
- snprintf(tmp, sizeof(tmp), "%d - "SAVE_SLOT_EMPTY"\n", i);
- } else {
- char *name;
- if (!i)
- name = strdup(AUTOSAVE_SLOT);
- else
- name = slot_name(s);
- if (!name)
- snprintf(tmp, sizeof(tmp), "%d - "BROKEN_SLOT"\n", i);
- else {
- snprintf(tmp, sizeof(tmp), "%d - %s\n", i, i, name);
- free(name);
- }
- }
- strcat(menu_buff, tmp);
- }
- strcat(menu_buff,"\nОтмена");
-}
-
-void save_menu(void)
-{
- int i;
- *menu_buff = 0;
- sprintf(menu_buff, SELECT_SAVE_MENU);
- for (i = 1; i < MAX_SAVE_SLOTS; i ++) {
- char tmp[PATH_MAX];
- char *s = game_save_path(0, i);
- if (!s || access(s, R_OK))
- snprintf(tmp, sizeof(tmp), "%d - "SAVE_SLOT_EMPTY"\n", i, i);
- else {
- char *name;
- if (!i)
- name = strdup(AUTOSAVE_SLOT);
- else
- name = slot_name(s);
- if (!name)
- snprintf(tmp, sizeof(tmp), "%d - "BROKEN_SLOT"\n", i, i);
- else {
- snprintf(tmp, sizeof(tmp), "%d - %s\n", i, i, name);
- free(name);
- }
- }
- strcat(menu_buff, tmp);
- }
- strcat(menu_buff,"\nОтмена");
-}
-
-void games_menu(void)
-{
- int i;
- *menu_buff = 0;
- sprintf(menu_buff, SELECT_GAME_MENU);
- for (i = games_menu_from; i < games_nr && i - games_menu_from < MENU_GAMES_MAX; i ++) {
- char tmp[PATH_MAX];
- if (curgame && !strcmp(games[i].name, curgame))
- snprintf(tmp, sizeof(tmp), "%s\n", games[i].name);
- else
- snprintf(tmp, sizeof(tmp), "%s\n", games[i].dir, games[i].name);
- strcat(menu_buff, tmp);
- }
- if (!games_nr)
- sprintf(menu_buff, NOGAMES_MENU, GAMES_PATH);
- strcat(menu_buff,"\n");
- if (games_menu_from)
- strcat(menu_buff,"<< ");
- strcat(menu_buff, BACK_MENU);
- if (games_menu_from + MENU_GAMES_MAX < games_nr)
- strcat(menu_buff," >>");
-}
-
-void themes_menu(void)
-{
- int i;
- *menu_buff = 0;
- sprintf(menu_buff, SELECT_THEME_MENU);
- for (i = themes_menu_from; i < themes_nr && i - themes_menu_from < MENU_THEMES_MAX; i ++) {
- char tmp[PATH_MAX];
- if (curtheme && !strcmp(themes[i].name, curtheme))
- snprintf(tmp, sizeof(tmp), "%s\n", themes[i].name);
- else
- snprintf(tmp, sizeof(tmp), "%s\n", themes[i].dir, themes[i].name);
- strcat(menu_buff, tmp);
- }
- if (!themes_nr)
- sprintf(menu_buff, NOTHEMES_MENU, THEMES_PATH);
- strcat(menu_buff,"\n");
- if (themes_menu_from)
- strcat(menu_buff,"<< ");
- strcat(menu_buff, BACK_MENU);
- if (themes_menu_from + MENU_THEMES_MAX < themes_nr)
- strcat(menu_buff," >>");
-}
-
-char *game_menu_gen(void)
-{
- if (cur_menu == menu_main) {
- snprintf(menu_buff, sizeof(menu_buff), MAIN_MENU);
- } else if (cur_menu == menu_about) {
- snprintf(menu_buff, sizeof(menu_buff), ABOUT_MENU);
- } else if (cur_menu == menu_settings) {
- snprintf(menu_buff, sizeof(menu_buff), SETTINGS_MENU,
- vol_to_pcn(snd_volume_mus(-1)), snd_hz(), opt_music?ON:OFF, opt_click?ON:OFF,
- opt_fs?ON:OFF, opt_fsize, opt_hl?ON:OFF, opt_motion?ON:OFF, opt_filter?ON:OFF,
- opt_owntheme?ON:OFF, opt_autosave?ON:OFF);
- } else if (cur_menu == menu_askquit) {
- snprintf(menu_buff, sizeof(menu_buff), QUIT_MENU);
- } else if (cur_menu == menu_saved) {
- snprintf(menu_buff, sizeof(menu_buff),
- SAVED_MENU);
- } else if (cur_menu == menu_games) {
- games_menu();
- } else if (cur_menu == menu_themes) {
- themes_menu();
- } else if (cur_menu == menu_own_theme) {
- snprintf(menu_buff, sizeof(menu_buff),
- OWN_THEME_MENU);
- } else if (cur_menu == menu_custom_theme) {
- snprintf(menu_buff, sizeof(menu_buff),
- CUSTOM_THEME_MENU);
- } else if (cur_menu == menu_load) {
- load_menu();
- } else if (cur_menu == menu_save) {
- save_menu();
- } else if (cur_menu == menu_error) {
- snprintf(menu_buff, sizeof(menu_buff),
- ERROR_MENU, err_msg?err_msg:UNKNOWN_ERROR);
- game_err_msg(NULL);
- } else if (cur_menu == menu_warning) {
- snprintf(menu_buff, sizeof(menu_buff),
- WARNING_MENU, err_msg?err_msg:UNKNOWN_ERROR);
- game_err_msg(NULL);
- }
- return menu_buff;
-}
void game_menu_box(int show, const char *txt)
{
@@ -1926,6 +736,9 @@ void game_menu_box(int show, const char *txt)
int b = game_theme.border_w;
int pad = game_theme.pad;
layout_t lay;
+
+ menu_shown = show;
+
el(el_menu)->drawn = 0;
if (el_layout(el_menu)) {
txt_layout_free(el_layout(el_menu));
@@ -2042,7 +855,7 @@ void scene_scrollbar(void)
static void dec_music(void *data)
{
char *mus;
- if (!curgame)
+ if (!curgame_dir)
return;
mus = instead_eval("return dec_music_loop()");
if (!mus)
@@ -2057,20 +870,7 @@ void game_music_finished(void)
push_user_event(&dec_music, NULL);
}
-void unix_path(char *path)
-{
- char *p = path;
- if (!path)
- return;
- while (*p) { /* bad bad Windows!!! */
- if (*p == '\\')
- *p = '/';
- p ++;
- }
- return;
-}
-
-void music_player(void)
+void game_music_player(void)
{
int loop;
char *mus;
@@ -2097,18 +897,15 @@ void music_player(void)
if (!mus) {
if (last_music) {
- free(last_music);
- snd_stop_mus(500);
- last_music = NULL;
+ game_stop_mus(500);
}
} else if (!last_music && mus) {
+ game_stop_mus(500);
last_music = mus;
- snd_stop_mus(500);
snd_play_mus(mus, 0, loop - 1);
} else if (strcmp(last_music, mus)) {
- free(last_music);
+ game_stop_mus(500);
last_music = mus;
- snd_stop_mus(500);
snd_play_mus(mus, 0, loop - 1);
} else
free(mus);
@@ -2156,7 +953,7 @@ int game_cmd(char *cmd)
cmdstr = instead_cmd(cmd);
if (!cmdstr)
goto err;
- music_player();
+ game_music_player();
// sound_player(); /* TODO */
title = instead_eval("return get_title();");
unix_path(title);
@@ -2389,6 +1186,7 @@ void menu_update(struct el *elem)
// gfx_fill(x, y, w, h, game_theme.menu_bg);
}
+void game_cursor(int on);
int game_highlight(int x, int y, int on)
{
@@ -2464,10 +1262,11 @@ static void scroll_pdown(int id)
el_update(id);
}
-static unsigned int old_counter = 0;
extern unsigned int timer_counter;
+
int mouse_filter(void)
{
+ static unsigned int old_counter = 0;
if (!opt_filter)
return 0;
if (abs(old_counter - timer_counter) <= 4) /* 400 ms */
@@ -2674,11 +1473,12 @@ static void scroll_motion(int id, int off)
el_update(id);
}
-static int alt_pressed = 0;
int game_loop(void)
{
+ static int alt_pressed = 0;
static int x = 0, y = 0;
struct inp_event ev;
+ memset(&ev, 0, sizeof(struct inp_event));
while (1) {
int rc;
ev.x = -1;
diff --git a/src/sdl-instead/game.h b/src/sdl-instead/game.h
index a85ccab..4e63eb1 100644
--- a/src/sdl-instead/game.h
+++ b/src/sdl-instead/game.h
@@ -5,46 +5,61 @@
#define GAMES_PATH "./games"
#endif
-#define DEFAULT_THEME "default"
-#ifndef THEMES_PATH
-#define THEMES_PATH "./themes"
-#endif
-
#define MAIN_FILE "main.lua"
-#define THEME_FILE "theme.ini"
-
-#define MENU_GAMES_MAX 8
-#define MENU_THEMES_MAX 8
-
-#define FONT_MIN_SZ 8
-#define FONT_MAX_SZ 64
-
-#define MAX_SAVE_SLOTS 6
-extern char *game_local_games_path(void);
-extern char *game_local_themes_path(void);
-extern int cfg_load(void);
-extern int cfg_save(void);
-extern char *opt_game;
-
-extern int nosound_sw;
-extern int alsa_sw;
-extern int fullscreen_sw;
-extern int window_sw;
-
-extern int opt_fs;
-extern char *opt_theme;
-extern char *curtheme;
-extern int game_theme_select(const char *name);
-extern int game_load_theme(const char *path);
-extern int game_init(const char *game);
-extern void game_done(void);
-extern int game_loop(void);
+extern int nosound_sw;
+extern int alsa_sw;
+extern int fullscreen_sw;
+extern int window_sw;
+
+extern int game_own_theme; /* current game has own theme */
+extern char *err_msg; /* last error message */
+extern char game_cwd[]; /* current game cwd */
+extern char *curgame_dir;
+
+extern char *game_local_games_path(void);
+extern int game_theme_select(const char *name);
+
+extern int game_init(const char *game);
+extern int game_loop(void);
+extern void game_done(void);
+
+extern int game_load_theme(const char *path);
+
+extern void game_music_player(void);
+extern void game_stop_mus(int ms);
+
+extern int game_change_vol(int d, int val);
+extern int game_change_hz(int hz);
+
+extern int games_lookup(const char *path);
+
+extern void game_err_msg(const char *s);
+extern int game_error(const char *name);
+
+extern int game_restart(void);
+extern int game_select(const char *name);
+extern int game_cmd(char *cmd);
+
+extern void game_menu(int nr); /* select and show menu */
+extern void game_menu_box(int show, const char *txt); /* show menu */
+
+extern int game_load(int nr);
+extern int game_save(int nr);
+
+extern char *game_cfg_path(void);
+extern char *game_save_path(int rc, int nr);
+
+extern char *game_locale(void);
+
+struct game {
+ char *path;
+ char *name;
+ char *dir;
+};
+
+extern struct game *games;
+extern int games_nr;
-extern int games_lookup(const char *path);
-extern int themes_lookup(const char *path);
-extern void game_err_msg(const char *s);
-extern int game_error(const char *name);
#endif
-
diff --git a/src/sdl-instead/graphics.c b/src/sdl-instead/graphics.c
index fb5c13c..a17c33f 100644
--- a/src/sdl-instead/graphics.c
+++ b/src/sdl-instead/graphics.c
@@ -1,11 +1,5 @@
-#include
-#include
-#include
-#include
-#include "SDL_rotozoom.h"
-#include "input.h"
-#include "graphics.h"
-#include "math.h"
+#include "externals.h"
+#include "internals.h"
static SDL_Surface *screen;
diff --git a/src/sdl-instead/input.c b/src/sdl-instead/input.c
index 9dff92b..57dde21 100644
--- a/src/sdl-instead/input.c
+++ b/src/sdl-instead/input.c
@@ -1,7 +1,5 @@
-#include
-#include "input.h"
-#include
-#include
+#include "externals.h"
+#include "internals.h"
void push_user_event(void (*p) (void*), void *data)
{
diff --git a/src/sdl-instead/instead.c b/src/sdl-instead/instead.c
index e65346c..9e61ae7 100644
--- a/src/sdl-instead/instead.c
+++ b/src/sdl-instead/instead.c
@@ -2,20 +2,9 @@
#define STEAD_PATH "./stead"
#endif
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-// #include
-#include
#include "gui.h"
-#ifdef _HAVE_ICONV
-#include
-#endif
-#include "game.h"
+#include "externals.h"
+#include "internals.h"
/* the Lua interpreter */
char *fromgame(const char *s);
diff --git a/src/sdl-instead/internals.h b/src/sdl-instead/internals.h
new file mode 100644
index 0000000..c4e2a98
--- /dev/null
+++ b/src/sdl-instead/internals.h
@@ -0,0 +1,10 @@
+#include "graphics.h"
+#include "sound.h"
+#include "game.h"
+#include "themes.h"
+#include "menu.h"
+#include "config.h"
+#include "input.h"
+#include "util.h"
+#include "instead.h"
+#include "SDL_rotozoom.h"
diff --git a/src/sdl-instead/main.c b/src/sdl-instead/main.c
index 2910348..9485379 100644
--- a/src/sdl-instead/main.c
+++ b/src/sdl-instead/main.c
@@ -1,10 +1,5 @@
-#include
-#include
-#include "graphics.h"
-#include "game.h"
-#include
-#include
-#include
+#include "externals.h"
+#include "internals.h"
extern int debug_init(void);
extern void debug_done(void);
@@ -47,7 +42,6 @@ int main(int argc, char **argv)
}
-
if (debug_sw) {
debug_init();
}
@@ -56,7 +50,14 @@ int main(int argc, char **argv)
opt_fs = 0;
if (fullscreen_sw)
opt_fs = 1;
-
+
+ menu_langs_lookup(LANG_PATH);
+
+ if (!langs_nr) {
+ fprintf(stderr, "No languages found in: %s.\n", LANG_PATH);
+ exit(1);
+ }
+
if (games_sw)
games_lookup(games_sw);
@@ -79,7 +80,7 @@ int main(int argc, char **argv)
if (opt_theme)
game_theme_select(opt_theme);
- if (!curtheme)
+ if (!curtheme_dir)
game_theme_select(DEFAULT_THEME);
if (game_init(opt_game)) {
diff --git a/src/sdl-instead/menu.c b/src/sdl-instead/menu.c
new file mode 100644
index 0000000..368a270
--- /dev/null
+++ b/src/sdl-instead/menu.c
@@ -0,0 +1,615 @@
+#include "externals.h"
+#include "internals.h"
+
+#ifdef RUSSIAN
+//#include "menu-ru.h"
+#else
+//#include "menu-en.h"
+#endif
+
+static int restart_needed = 0;
+static int games_menu_from = 0;
+static int themes_menu_from = 0;
+
+static int cur_lang = 0;
+
+int cur_menu = 0;
+
+char *UNKNOWN_ERROR = NULL;
+char *ERROR_MENU = NULL;
+char *WARNING_MENU = NULL;
+char *SAVE_SLOT_EMPTY = NULL;
+char *SELECT_LOAD_MENU = NULL;
+char *AUTOSAVE_SLOT = NULL;
+char *BROKEN_SLOT = NULL;
+char *SELECT_SAVE_MENU = NULL;
+char *MAIN_MENU = NULL;
+char *ABOUT_MENU = NULL;
+char *BACK_MENU = NULL;
+char *SETTINGS_MENU = NULL;
+char *CUSTOM_THEME_MENU = NULL;
+char *OWN_THEME_MENU = NULL;
+char *SELECT_GAME_MENU = NULL;
+char *SELECT_THEME_MENU = NULL;
+char *SAVED_MENU = NULL;
+char *NOGAMES_MENU = NULL;
+char *NOTHEMES_MENU = NULL;
+char *QUIT_MENU = NULL;
+char *ON = NULL;
+char *OFF = NULL;
+
+static char menu_buff[4096];
+
+static char *slot_name(const char *path)
+{
+ struct stat st;
+ int brk = 0;
+ char *l; char line[1024];
+ FILE *fd = fopen(path, "r");
+ if (!fd)
+ return NULL;
+
+ while ((l = fgets(line, sizeof(line), fd)) && !brk) {
+ l = parse_tag(l, "$Name:", "--", &brk);
+ if (l) {
+ char *s = fromgame(l);
+ free(l);
+ return s;
+ }
+ }
+ fclose(fd);
+ if (stat(path, &st))
+ return NULL;
+ l = ctime(&st.st_ctime);
+ if (!l)
+ return NULL;
+ l[strcspn(l,"\n")] = 0;
+ return strdup(l);
+}
+
+static void load_menu(void)
+{
+ int i;
+ *menu_buff = 0;
+ sprintf(menu_buff, SELECT_LOAD_MENU);
+ for (i = 0; i < MAX_SAVE_SLOTS; i ++) {
+ char tmp[PATH_MAX];
+ char *s = game_save_path(0, i);
+ if (!s || access(s, R_OK)) {
+ if (!i)
+ continue;
+ snprintf(tmp, sizeof(tmp), "%d - %s\n", i, SAVE_SLOT_EMPTY);
+ } else {
+ char *name;
+ if (!i)
+ name = strdup(AUTOSAVE_SLOT);
+ else
+ name = slot_name(s);
+ if (!name)
+ snprintf(tmp, sizeof(tmp), "%d - %s\n", i, BROKEN_SLOT);
+ else {
+ snprintf(tmp, sizeof(tmp), "%d - %s\n", i, i, name);
+ free(name);
+ }
+ }
+ strcat(menu_buff, tmp);
+ }
+ strcat(menu_buff,"\nОтмена");
+}
+
+static void save_menu(void)
+{
+ int i;
+ *menu_buff = 0;
+ sprintf(menu_buff, SELECT_SAVE_MENU);
+ for (i = 1; i < MAX_SAVE_SLOTS; i ++) {
+ char tmp[PATH_MAX];
+ char *s = game_save_path(0, i);
+ if (!s || access(s, R_OK))
+ snprintf(tmp, sizeof(tmp), "%d - %s\n", i, i, SAVE_SLOT_EMPTY);
+ else {
+ char *name;
+ if (!i)
+ name = strdup(AUTOSAVE_SLOT);
+ else
+ name = slot_name(s);
+ if (!name)
+ snprintf(tmp, sizeof(tmp), "%d - %s\n", i, i, BROKEN_SLOT);
+ else {
+ snprintf(tmp, sizeof(tmp), "%d - %s\n", i, i, name);
+ free(name);
+ }
+ }
+ strcat(menu_buff, tmp);
+ }
+ strcat(menu_buff,"\nОтмена");
+}
+
+static void games_menu(void)
+{
+ int i;
+ *menu_buff = 0;
+ sprintf(menu_buff, SELECT_GAME_MENU);
+ for (i = games_menu_from; i < games_nr && i - games_menu_from < MENU_GAMES_MAX; i ++) {
+ char tmp[PATH_MAX];
+ if (curgame_dir && !strcmp(games[i].dir, curgame_dir))
+ snprintf(tmp, sizeof(tmp), "%s\n", games[i].name);
+ else
+ snprintf(tmp, sizeof(tmp), "%s\n", games[i].dir, games[i].name);
+ strcat(menu_buff, tmp);
+ }
+ if (!games_nr)
+ sprintf(menu_buff, NOGAMES_MENU, GAMES_PATH);
+ strcat(menu_buff,"\n");
+ if (games_menu_from)
+ strcat(menu_buff,"<< ");
+ strcat(menu_buff, BACK_MENU);
+ if (games_menu_from + MENU_GAMES_MAX < games_nr)
+ strcat(menu_buff," >>");
+}
+
+static void themes_menu(void)
+{
+ int i;
+ *menu_buff = 0;
+ sprintf(menu_buff, SELECT_THEME_MENU);
+ for (i = themes_menu_from; i < themes_nr && i - themes_menu_from < MENU_THEMES_MAX; i ++) {
+ char tmp[PATH_MAX];
+ if (curtheme_dir && !strcmp(themes[i].dir, curtheme_dir))
+ snprintf(tmp, sizeof(tmp), "%s\n", themes[i].name);
+ else
+ snprintf(tmp, sizeof(tmp), "%s\n", themes[i].dir, themes[i].name);
+ strcat(menu_buff, tmp);
+ }
+ if (!themes_nr)
+ sprintf(menu_buff, NOTHEMES_MENU, THEMES_PATH);
+ strcat(menu_buff,"\n");
+ if (themes_menu_from)
+ strcat(menu_buff,"<< ");
+ strcat(menu_buff, BACK_MENU);
+ if (themes_menu_from + MENU_THEMES_MAX < themes_nr)
+ strcat(menu_buff," >>");
+}
+
+char *game_menu_gen(void)
+{
+ if (cur_menu == menu_main) {
+ snprintf(menu_buff, sizeof(menu_buff), MAIN_MENU);
+ } else if (cur_menu == menu_about) {
+ snprintf(menu_buff, sizeof(menu_buff), ABOUT_MENU, VERSION);
+ } else if (cur_menu == menu_settings) {
+ snprintf(menu_buff, sizeof(menu_buff), SETTINGS_MENU,
+ snd_vol_to_pcn(snd_volume_mus(-1)), snd_hz(), opt_music?ON:OFF, opt_click?ON:OFF,
+ opt_fs?ON:OFF, opt_fsize, opt_hl?ON:OFF, opt_motion?ON:OFF, opt_filter?ON:OFF,
+ langs[cur_lang].name, opt_owntheme?ON:OFF, opt_autosave?ON:OFF);
+ } else if (cur_menu == menu_askquit) {
+ snprintf(menu_buff, sizeof(menu_buff), QUIT_MENU);
+ } else if (cur_menu == menu_saved) {
+ snprintf(menu_buff, sizeof(menu_buff),
+ SAVED_MENU);
+ } else if (cur_menu == menu_games) {
+ games_menu();
+ } else if (cur_menu == menu_themes) {
+ themes_menu();
+ } else if (cur_menu == menu_own_theme) {
+ snprintf(menu_buff, sizeof(menu_buff),
+ OWN_THEME_MENU);
+ } else if (cur_menu == menu_custom_theme) {
+ snprintf(menu_buff, sizeof(menu_buff),
+ CUSTOM_THEME_MENU);
+ } else if (cur_menu == menu_load) {
+ load_menu();
+ } else if (cur_menu == menu_save) {
+ save_menu();
+ } else if (cur_menu == menu_error) {
+ snprintf(menu_buff, sizeof(menu_buff),
+ ERROR_MENU, err_msg?err_msg:UNKNOWN_ERROR);
+ game_err_msg(NULL);
+ } else if (cur_menu == menu_warning) {
+ snprintf(menu_buff, sizeof(menu_buff),
+ WARNING_MENU, err_msg?err_msg:UNKNOWN_ERROR);
+ game_err_msg(NULL);
+ }
+ return menu_buff;
+}
+
+
+int game_menu_act(const char *a)
+{
+ int static old_vol = 0;
+
+ if (!strcmp(a, "/autosave")) {
+ opt_autosave ^= 1;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/owntheme")) {
+ opt_owntheme ^= 1;
+ if (game_own_theme)
+ restart_needed = 1;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/motion")) {
+ opt_motion ^= 1;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/filter")) {
+ opt_filter ^= 1;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/click")) {
+ opt_click ^= 1;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/fs--")) {
+ opt_fsize --;
+ if (FONT_SZ(game_theme.font_size) > FONT_MIN_SZ) {
+ restart_needed = 1;
+ } else
+ opt_fsize ++;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/fs++")) {
+ opt_fsize ++;
+ if (FONT_SZ(game_theme.font_size) < FONT_MAX_SZ) {
+ restart_needed = 1;
+ } else
+ opt_fsize --;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/hl")) {
+ opt_hl ^= 1;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/fs")) {
+ restart_needed = 1;
+ opt_fs ^= 1;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/games_prev")) {
+ games_menu_from -= MENU_GAMES_MAX;
+ if (games_menu_from < 0)
+ games_menu_from = 0;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/games_next")) {
+ if (games_menu_from + MENU_GAMES_MAX < games_nr)
+ games_menu_from += MENU_GAMES_MAX;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/themes_prev")) {
+ themes_menu_from -= MENU_THEMES_MAX;
+ if (themes_menu_from < 0)
+ themes_menu_from = 0;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/themes_next")) {
+ if (themes_menu_from + MENU_THEMES_MAX < themes_nr)
+ themes_menu_from += MENU_THEMES_MAX;
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/select")) {
+ game_menu(menu_games);
+ } else if (!strcmp(a, "/themes")) {
+ game_menu(menu_themes);
+ } else if (!strcmp(a, "/save_menu")) {
+ if (curgame_dir)
+ game_menu(menu_save);
+ } else if (!strncmp(a, "/save", 5)) {
+ if (!game_save(atoi(a + 5))) {
+ game_menu(menu_saved);
+ }
+ } else if (!strcmp(a, "/load_menu")) {
+ if (curgame_dir)
+ game_menu(menu_load);
+ } else if (!strncmp(a, "/load", 5)) {
+ int nr = atoi(a + 5);
+ if (!curgame_dir)
+ return 0;
+// free_last();
+ game_select(curgame_dir);
+ game_menu_box(0, NULL);
+ game_load(nr);
+ cur_menu = menu_main;
+// game_menu_box(0, NULL);
+ } else if (!strcmp(a, "/new")) {
+ char *s;
+ if (!curgame_dir)
+ return 0;
+// free_last();
+ game_select(curgame_dir);
+ game_menu_box(0, NULL);
+ instead_eval("game:ini()");
+ game_cmd("look");
+ s = game_save_path(0, 0);
+ if (s && !access(s, R_OK) && opt_autosave)
+ unlink (s);
+ custom_theme_warn();
+ } else if (!strcmp(a,"/main")) {
+ if (restart_needed) {
+ game_restart();
+ restart_needed = 0;
+ }
+ game_menu(menu_main);
+ } else if (!strcmp(a,"/ask_quit")) {
+ game_menu(menu_askquit);
+ } else if (!strcmp(a,"/about")) {
+ game_menu(menu_about);
+ } else if (!strcmp(a,"/mtoggle")) {
+ if (!old_vol) {
+ old_vol = snd_volume_mus(-1);
+ game_change_vol(0, 0);
+ } else {
+ game_change_vol(0, old_vol);
+ old_vol = 0;
+ }
+ } else if (!strcmp(a,"/music")) {
+ opt_music ^= 1;
+ if (!opt_music) {
+ game_stop_mus(0);
+ } else
+ game_music_player();
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a,"/resume")) {
+ cur_menu = menu_main;
+ game_menu_box(0, NULL);
+ } else if (!strcmp(a, "/settings")) {
+ game_menu(menu_settings);
+ } else if (!strcmp(a, "/vol--")) {
+ game_change_vol(-10, 0);
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/vol++")) {
+ game_change_vol(+10, 0);
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/vol-")) {
+ game_change_vol(-1, 0);
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/vol+")) {
+ game_change_vol(+1, 0);
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/hz-")) {
+ int hz = snd_hz();
+ if (hz == 48000)
+ hz = 44100;
+ else if (hz == 44100)
+ hz = 22050;
+ else if (hz == 22050)
+ hz = 11025;
+ else
+ hz = 0;
+ game_change_hz(hz);
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/hz+")) {
+ int hz = snd_hz();
+ if (hz == 11025)
+ hz = 22050;
+ else if (hz == 22050)
+ hz = 44100;
+ else if (hz == 44100)
+ hz = 48000;
+ else
+ hz = 0;
+ game_change_hz(hz);
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/lang++")) {
+ do {
+ cur_lang ++;
+ if (cur_lang >= langs_nr)
+ cur_lang = 0;
+ } while (menu_lang_select(langs[cur_lang].file));
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a, "/lang--")) {
+ do {
+ cur_lang --;
+ if (cur_lang < 0)
+ cur_lang = langs_nr - 1;
+ } while (menu_lang_select(langs[cur_lang].file));
+ game_menu_box(1, game_menu_gen());
+ } else if (!strcmp(a,"/quit")) {
+ return -1;
+ } else if (cur_menu == menu_games) {
+ char *p;
+ p = strdup(a);
+ if (p) {
+ game_done();
+ if (game_init(p)) {
+ game_error(p);
+ }
+ free(p);
+ }
+ } else if (cur_menu == menu_themes) {
+ char *p;
+ p = strdup(a);
+ if (p) {
+ if (game_theme_select(p))
+ fprintf(stderr, "Can't select theme:%s:%s\n", p, strerror(errno));
+ char *og = curgame_dir;
+ game_save(-1);
+ game_done();
+ if (game_init(og))
+ game_error(og);
+ else if (curgame_dir && game_own_theme && opt_owntheme) {
+ game_menu(menu_own_theme);
+ }
+ free(p);
+ }
+ }
+ return 0;
+}
+
+void custom_theme_warn(void)
+{
+ if (game_own_theme && !opt_owntheme) {
+ game_menu(menu_custom_theme);
+ }
+}
+
+
+
+struct lang *langs = NULL;
+int langs_nr = 0;
+
+
+static void lang_free(void)
+{
+ FREE(UNKNOWN_ERROR);
+ FREE(ERROR_MENU);
+ FREE(WARNING_MENU);
+ FREE(SAVE_SLOT_EMPTY);
+ FREE(SELECT_LOAD_MENU);
+ FREE(AUTOSAVE_SLOT);
+ FREE(BROKEN_SLOT);
+ FREE(SELECT_SAVE_MENU);
+ FREE(MAIN_MENU);
+ FREE(ABOUT_MENU);
+ FREE(BACK_MENU);
+ FREE(SETTINGS_MENU);
+ FREE(CUSTOM_THEME_MENU);
+ FREE(OWN_THEME_MENU);
+ FREE(SELECT_GAME_MENU);
+ FREE(SELECT_THEME_MENU);
+ FREE(SAVED_MENU);
+ FREE(NOGAMES_MENU);
+ FREE(NOTHEMES_MENU);
+ FREE(QUIT_MENU);
+ FREE(ON);
+ FREE(OFF);
+}
+
+static int lang_ok(void)
+{
+ if (UNKNOWN_ERROR && ERROR_MENU && WARNING_MENU && SAVE_SLOT_EMPTY &&
+ SELECT_LOAD_MENU && AUTOSAVE_SLOT && BROKEN_SLOT && SELECT_SAVE_MENU &&
+ MAIN_MENU && ABOUT_MENU && BACK_MENU && SETTINGS_MENU &&
+ CUSTOM_THEME_MENU && OWN_THEME_MENU && SELECT_GAME_MENU && SELECT_THEME_MENU &&
+ SAVED_MENU && NOGAMES_MENU && NOTHEMES_MENU && QUIT_MENU &&
+ ON && OFF)
+ return 0;
+ return -1;
+}
+
+struct parser lang_parser[] = {
+ { "UNKNOWN_ERROR", parse_esc_string, &UNKNOWN_ERROR },
+ { "ERROR_MENU", parse_esc_string, &ERROR_MENU },
+ { "WARNING_MENU", parse_esc_string, &WARNING_MENU },
+ { "SAVE_SLOT_EMPTY", parse_esc_string, &SAVE_SLOT_EMPTY },
+ { "SELECT_LOAD_MENU", parse_esc_string, &SELECT_LOAD_MENU },
+ { "AUTOSAVE_SLOT", parse_esc_string, &AUTOSAVE_SLOT },
+ { "BROKEN_SLOT", parse_esc_string, &BROKEN_SLOT },
+ { "SELECT_SAVE_MENU", parse_esc_string, &SELECT_SAVE_MENU },
+ { "MAIN_MENU", parse_esc_string, &MAIN_MENU },
+ { "ABOUT_MENU", parse_esc_string, &ABOUT_MENU },
+ { "BACK_MENU", parse_esc_string, &BACK_MENU },
+ { "SETTINGS_MENU", parse_esc_string, &SETTINGS_MENU },
+ { "CUSTOM_THEME_MENU", parse_esc_string, &CUSTOM_THEME_MENU },
+ { "OWN_THEME_MENU", parse_esc_string, &OWN_THEME_MENU },
+ { "SELECT_GAME_MENU", parse_esc_string, &SELECT_GAME_MENU },
+ { "SELECT_THEME_MENU", parse_esc_string, &SELECT_THEME_MENU },
+ { "SAVED_MENU", parse_esc_string, &SAVED_MENU },
+ { "NOGAMES_MENU", parse_esc_string, &NOGAMES_MENU },
+ { "NOTHEMES_MENU", parse_esc_string, &NOTHEMES_MENU },
+ { "QUIT_MENU", parse_esc_string, &QUIT_MENU },
+ { "ON", parse_esc_string, &ON },
+ { "OFF", parse_esc_string, &OFF },
+ { NULL, },
+};
+
+static int lang_parse(const char *path)
+{
+ return parse_ini(path, lang_parser);
+}
+
+static int is_lang(const char *path, const char *n)
+{
+ char *p = getfilepath(path, n);
+ if (!p)
+ return 0;
+ if (access(p, F_OK))
+ return 0;
+ free(p);
+
+ if (!(p = strstr(n, ".ini")))
+ return 0;
+ if (strcmp(p, ".ini"))
+ return 0;
+ return 1;
+}
+
+static char *lang_code(const char *str)
+{
+ char *p = strdup(str);
+ if (!p)
+ return NULL;
+ p[strcspn(p, ".")] = 0;
+ return p;
+}
+
+
+static char *lang_name(const char *path, const char *file)
+{
+ int brk = 0;
+ char *l; char line[1024];
+ FILE *fd = fopen(path, "r");
+ if (!fd)
+ goto err;
+ while ((l = fgets(line, sizeof(line), fd)) && !brk) {
+ l = parse_tag(l, "$Name:", ";", &brk);
+ if (l)
+ return l;
+ }
+ fclose(fd);
+err:
+ return lang_code(file);
+}
+
+
+int menu_langs_lookup(const char *path)
+{
+ char *p;
+ int n = 0, i = 0;
+ DIR *d;
+ struct dirent *de;
+
+ if (!path)
+ return 0;
+
+ d = opendir(path);
+ if (!d)
+ return -1;
+ while ((de = readdir(d))) {
+ if (!is_lang(path, de->d_name))
+ continue;
+ n ++;
+ }
+
+ rewinddir(d);
+ if (!n)
+ return 0;
+
+ langs = realloc(langs, sizeof(struct lang) * (n + langs_nr));
+
+ while ((de = readdir(d)) && i < n) {
+ if (!is_lang(path, de->d_name))
+ continue;
+ p = getfilepath(path, de->d_name);
+ langs[langs_nr].path = p;
+ langs[langs_nr].file = lang_code(de->d_name);
+ langs[langs_nr].name = lang_name(p, de->d_name);
+ langs_nr ++;
+ i ++;
+ }
+ closedir(d);
+ return 0;
+}
+
+int menu_lang_select(const char *name)
+{
+ int i;
+ char cwd[PATH_MAX];
+ if (!name)
+ return -1;
+ getcwd(cwd, sizeof(cwd));
+ chdir(game_cwd);
+ for (i = 0; iДа"
+#ifndef __MENU_H_INCLUDED
+#define __MENU_H_INCLUDED
-#define WARNING_MENU "Во время работы игры произошла ошибка:\n\
-'%s'\n\
-\n\
-Да"
+#define MENU_GAMES_MAX 8
+#define MENU_THEMES_MAX 8
-#define SAVE_SLOT_EMPTY "пусто"
-#define SELECT_LOAD_MENU "Загрузите игру\n\n"
-#define AUTOSAVE_SLOT "Автосохранение"
-#define BROKEN_SLOT "ошибка"
-#define SELECT_SAVE_MENU "Сохраните игру\n\n"
+#define FONT_MIN_SZ 8
+#define FONT_MAX_SZ 64
-#define MAIN_MENU \
-"Вернуться в игру\n\
-Выбор игры\n\
-Выбор темы\n\
-Начать заново\n\
-Загрузить игру\n\
-Сохранить игру\n\
-Информация\n\
-Настройки\n\
-Выход"
+#define MAX_SAVE_SLOTS 6
-#define ABOUT_MENU \
-"INSTEAD SDL - "VERSION"\n\
-\n\
-Интерпретатор простых\n\
-текстовых приключений:\n\
-Косых П.А. '2009\n\
-\n\
-Адаптация для Windows:\n\
-Рындин И.В. '2009\n\
-\n\
-Сайт проекта:\n\
-http://instead.googlecode.com\n\
-\n\
-Назад"
+#define LANG_DEF "en.ini"
-#define BACK_MENU "Назад"
-#define ON "Да"
-#define OFF "Нет"
+extern int cur_menu;
+extern char *game_menu_gen(void);
+extern int game_menu_act(const char *a);
+extern void custom_theme_warn(void);
+extern int menu_langs_lookup(const char *path);
+extern int menu_lang_select(const char *name);
-#define SETTINGS_MENU \
-"Громкость\n\
-<<< %d%% >>>\n\
-\n\
-Качество звука\n<< %dГц >>\n\
-\n\
-Музыка: %s\n\
-Звук щелчка: %s\n\
-\n\
-Полный экран: %s\n\
-Масштаб шрифта: <<%d>>\n\
-Подсветка ссылок: %s\n\
-Режим прокрутки: %s\n\
-Фильтр мышки: %s\n\
-\n\
-Собственные темы игр: %s\n\
-Автосохранение: %s\n\
-\n\
-Применить"
+struct lang {
+ char *path;
+ char *name;
+ char *file;
+};
+extern struct lang *langs;
+extern int langs_nr;
-#define CUSTOM_THEME_MENU \
-"Внимание!!!\n\
-\n\
-Игра содержит собственную тему, но поддержка собственных тем отключена в настройках. \
-Игра может выглядеть не так, как задумывал ее автор.\n\
-\n\
-Вы можете разрешить возможность переопределения тем в настройках.\n\
-\n\
-Да"
+enum {
+ menu_main = 0,
+ menu_about,
+ menu_settings,
+ menu_quit,
+ menu_askquit,
+ menu_saved,
+ menu_games,
+ menu_themes,
+ menu_own_theme,
+ menu_custom_theme,
+ menu_load,
+ menu_save,
+ menu_error,
+ menu_warning,
+};
-#define OWN_THEME_MENU \
-"Внимание!!!\n\
-\n\
-Выбранная игра переопределяет тему. Изменения не вступят в силу.\n\
-\n\
-Вы можете запретить возможность переопределения тем в настройках.\n\
-\n\
-Да"
-#define QUIT_MENU \
-"На самом деле выйти?\n\
-\n\
-Да | Нет"
-
-#define SELECT_GAME_MENU "Выбор игры\n\n"
-#define SELECT_THEME_MENU "Выбор темы\n\n"
-#define SAVED_MENU \
-"Игра сохранена!\n\
-\n\
-Да"
-
-#define NOGAMES_MENU \
-"Не найдена ни одна игра.\n\
-Пожалуйста, скопируйте хотя бы одну игру в каталог:\n'%s'"
-
-#define NOTHEMES_MENU \
-"Не найдена ни одна тема.\n\
-Пожалуйста, скопируйте хотя бы одну тему в каталог:\n'%s'"
+#endif
diff --git a/src/sdl-instead/sound.c b/src/sdl-instead/sound.c
index 0c7e36e..40ed3ac 100644
--- a/src/sdl-instead/sound.c
+++ b/src/sdl-instead/sound.c
@@ -1,11 +1,5 @@
-#include "sound.h"
-#include "input.h"
-
-#include
-#include
-
-#include
-#include
+#include "externals.h"
+#include "internals.h"
Mix_Music *music = NULL;
@@ -213,3 +207,13 @@ void snd_done(void)
Mix_CloseAudio();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
+
+int snd_vol_from_pcn(int v)
+{
+ return (v * 127) / 100;
+}
+
+int snd_vol_to_pcn(int v)
+{
+ return (v * 100) / 127;
+}
diff --git a/src/sdl-instead/sound.h b/src/sdl-instead/sound.h
index a2158a7..7405d87 100644
--- a/src/sdl-instead/sound.h
+++ b/src/sdl-instead/sound.h
@@ -24,4 +24,7 @@ extern int snd_playing_mus();
extern void snd_stop_mus(int ms);
extern int snd_volume_mus(int vol);
extern void snd_done(void);
+extern int snd_vol_from_pcn(int v);
+extern int snd_vol_to_pcn(int v);
+
#endif
diff --git a/src/sdl-instead/themes.c b/src/sdl-instead/themes.c
new file mode 100644
index 0000000..cde2f67
--- /dev/null
+++ b/src/sdl-instead/themes.c
@@ -0,0 +1,438 @@
+#include "externals.h"
+#include "internals.h"
+
+char *curtheme_dir = NULL;
+
+static int parse_gfx_mode(const char *v, void *data)
+{
+ int *i = (int *)data;
+ if (!strcmp(v, "fixed"))
+ *i = GFX_MODE_FIXED;
+ else if (!strcmp(v, "embedded"))
+ *i = GFX_MODE_EMBEDDED;
+ else if (!strcmp(v, "float"))
+ *i = GFX_MODE_FLOAT;
+ else
+ return -1;
+ return 0;
+}
+
+static int parse_inv_mode(const char *v, void *data)
+{
+ int *i = (int *)data;
+ if (!strcmp(v, "vertical") || !strcmp(v, "0"))
+ *i = INV_MODE_VERT;
+ else if (!strcmp(v, "horizontal") || !strcmp(v, "1"))
+ *i = INV_MODE_HORIZ;
+ else
+ return -1;
+ return 0;
+}
+
+static int parse_color(const char *v, void *data)
+{
+ color_t *c = (color_t *)data;
+ return gfx_parse_color(v, c);
+}
+
+static int parse_include(const char *v, void *data)
+{
+ int rc;
+ char cwd[PATH_MAX];
+ if (!strcmp(v, DEFAULT_THEME))
+ return 0;
+ getcwd(cwd, sizeof(cwd));
+ chdir(game_cwd);
+ rc = game_theme_load(v);
+// if (!rc)
+// game_theme_select(v);
+ chdir(cwd);
+ return rc;
+}
+
+struct parser cmd_parser[] = {
+ { "scr.w", parse_int, &game_theme.w },
+ { "scr.h", parse_int, &game_theme.h },
+ { "scr.col.bg", parse_color, &game_theme.bgcol },
+ { "scr.gfx.bg", parse_string, &game_theme.bg_name },
+ { "scr.gfx.use", parse_string, &game_theme.use_name },
+ { "scr.gfx.pad", parse_int, &game_theme.pad },
+ { "scr.gfx.x", parse_int, &game_theme.gfx_x },
+ { "scr.gfx.y", parse_int, &game_theme.gfx_y },
+ { "scr.gfx.w", parse_int, &game_theme.max_scene_w },
+ { "scr.gfx.h", parse_int, &game_theme.max_scene_h },
+ { "scr.gfx.mode", parse_gfx_mode, &game_theme.gfx_mode },
+
+ { "win.x", parse_int, &game_theme.win_x },
+ { "win.y", parse_int, &game_theme.win_y },
+ { "win.w", parse_int, &game_theme.win_w },
+ { "win.h", parse_int, &game_theme.win_h },
+ { "win.fnt.name", parse_string, &game_theme.font_name },
+ { "win.fnt.size", parse_int, &game_theme.font_size },
+/* compat mode directive */
+ { "win.gfx.h", parse_int, &game_theme.max_scene_h },
+/* here it was */
+ { "win.gfx.up", parse_string, &game_theme.a_up_name },
+ { "win.gfx.down", parse_string, &game_theme.a_down_name },
+ { "win.col.fg", parse_color, &game_theme.fgcol },
+ { "win.col.link", parse_color, &game_theme.lcol },
+ { "win.col.alink", parse_color, &game_theme.acol },
+
+ { "inv.x", parse_int, &game_theme.inv_x },
+ { "inv.y", parse_int, &game_theme.inv_y },
+ { "inv.w", parse_int, &game_theme.inv_w },
+ { "inv.h", parse_int, &game_theme.inv_h },
+ { "inv.mode", parse_inv_mode, &game_theme.inv_mode },
+ { "inv.horiz", parse_inv_mode, &game_theme.inv_mode },
+
+ { "inv.col.fg", parse_color, &game_theme.icol },
+ { "inv.col.link", parse_color, &game_theme.ilcol },
+ { "inv.col.alink", parse_color, &game_theme.iacol },
+ { "inv.fnt.name", parse_string, &game_theme.inv_font_name },
+ { "inv.fnt.size", parse_int, &game_theme.inv_font_size },
+ { "inv.gfx.up", parse_string, &game_theme.inv_a_up_name },
+ { "inv.gfx.down", parse_string, &game_theme.inv_a_down_name },
+
+ { "menu.col.bg", parse_color, &game_theme.menu_bg },
+ { "menu.col.fg", parse_color, &game_theme.menu_fg },
+ { "menu.col.link", parse_color, &game_theme.menu_link },
+ { "menu.col.alink", parse_color, &game_theme.menu_alink },
+ { "menu.col.alpha", parse_int, &game_theme.menu_alpha },
+ { "menu.col.border", parse_color, &game_theme.border_col },
+ { "menu.bw", parse_int, &game_theme.border_w },
+ { "menu.fnt.name", parse_string, &game_theme.menu_font_name },
+ { "menu.fnt.size", parse_int, &game_theme.menu_font_size },
+ { "menu.gfx.button", parse_string, &game_theme.menu_button_name },
+ { "menu.button.x", parse_int, &game_theme.menu_button_x },
+ { "menu.button.y", parse_int, &game_theme.menu_button_y },
+/* compat */
+ { "menu.buttonx", parse_int, &game_theme.menu_button_x },
+ { "menu.buttony", parse_int, &game_theme.menu_button_y },
+
+ { "snd.click", parse_full_path, &game_theme.click_name },
+ { "include", parse_include, NULL },
+ { NULL, },
+};
+
+struct game_theme game_theme = {
+ .w = 800,
+ .h = 480,
+ .bg_name = NULL,
+ .bg = NULL,
+ .use_name = NULL,
+ .use = NULL,
+ .font_name = NULL,
+ .font = NULL,
+ .a_up_name = NULL,
+ .a_down_name = NULL,
+ .a_up = NULL,
+ .a_down = NULL,
+ .inv_font_name = NULL,
+ .inv_font = NULL,
+ .inv_a_up_name = NULL,
+ .inv_a_down_name = NULL,
+ .inv_a_up = NULL,
+ .inv_a_down = NULL,
+ .menu_font_name = NULL,
+ .menu_font = NULL,
+ .menu_button_name = NULL,
+ .menu_button = NULL,
+ .gfx_mode = GFX_MODE_EMBEDDED,
+ .inv_mode = INV_MODE_VERT,
+ .click_name = NULL,
+ .click = NULL,
+};
+
+
+static void free_theme_strings(void)
+{
+ struct game_theme *t = &game_theme;
+ FREE(t->use_name);
+ FREE(t->bg_name);
+ FREE(t->inv_a_up_name);
+ FREE(t->inv_a_down_name);
+ FREE(t->a_down_name);
+ FREE(t->a_up_name);
+ FREE(t->font_name);
+ FREE(t->inv_font_name);
+ FREE(t->menu_font_name);
+ FREE(t->menu_button_name);
+/* FREE(t->click_name); must be reloaded, ugly :(*/
+}
+
+int game_theme_free(void)
+{
+ free_theme_strings();
+
+ if (game_theme.font)
+ fnt_free(game_theme.font);
+ if (game_theme.inv_font)
+ fnt_free(game_theme.inv_font);
+ if (game_theme.menu_font)
+ fnt_free(game_theme.menu_font);
+
+ if (game_theme.a_up)
+ gfx_free_image(game_theme.a_up);
+ if (game_theme.a_down)
+ gfx_free_image(game_theme.a_down);
+ if (game_theme.inv_a_up)
+ gfx_free_image(game_theme.inv_a_up);
+ if (game_theme.inv_a_down)
+ gfx_free_image(game_theme.inv_a_down);
+
+ if (game_theme.use)
+ gfx_free_image(game_theme.use);
+
+ if (game_theme.bg)
+ gfx_free_image(game_theme.bg);
+
+ if (game_theme.menu_button)
+ gfx_free_image(game_theme.menu_button);
+
+ if (game_theme.click)
+ snd_free_wav(game_theme.click);
+
+ game_theme.font = game_theme.inv_font = game_theme.menu_font = NULL;
+ game_theme.a_up = game_theme.a_down = game_theme.use = NULL;
+ game_theme.inv_a_up = game_theme.inv_a_down = NULL;
+ game_theme.menu_button = NULL;
+ game_theme.bg = NULL;
+ game_theme.click = NULL;
+// game_theme.slide = gfx_load_image("slide.png", 1);
+ return 0;
+}
+
+
+static int game_theme_init(void)
+{
+ struct game_theme *t = &game_theme;
+
+ if (t->font_name) {
+ fnt_free(t->font);
+ if (!(t->font = fnt_load(t->font_name, FONT_SZ(t->font_size))))
+ goto err;
+ }
+
+ if (t->inv_font_name) {
+ fnt_free(t->inv_font);
+ if (!(t->inv_font = fnt_load(t->inv_font_name, FONT_SZ(t->inv_font_size))))
+ goto err;
+ }
+
+
+ if (t->menu_font_name) {
+ fnt_free(t->menu_font);
+ if (!(t->menu_font = fnt_load(t->menu_font_name, t->menu_font_size))) /* do not scale menu!!! */
+ goto err;
+ }
+
+
+ if (t->a_up_name) {
+ gfx_free_image(t->a_up);
+ if (!(t->a_up = gfx_load_image(t->a_up_name)))
+ goto err;
+ }
+
+ if (t->a_down_name) {
+ gfx_free_image(t->a_down);
+ if (!(t->a_down = gfx_load_image(t->a_down_name)))
+ goto err;
+ }
+
+ if (t->inv_a_up_name) {
+ gfx_free_image(t->inv_a_up);
+ if (!(t->inv_a_up = gfx_load_image(t->inv_a_up_name)))
+ goto err;
+ }
+
+
+ if (t->inv_a_down_name) {
+ gfx_free_image(t->inv_a_down);
+ if (!(t->inv_a_down = gfx_load_image(t->inv_a_down_name)))
+ goto err;
+ }
+
+ if (t->bg_name) {
+ gfx_free_image(t->bg);
+ t->bg = NULL;
+ if (t->bg_name[0] && !(t->bg = gfx_load_image(t->bg_name)))
+ goto err;
+ }
+
+ if (t->use_name) {
+ gfx_free_image(t->use);
+ if (!(t->use = gfx_load_image(t->use_name)))
+ goto err;
+ }
+
+ if (t->menu_button_name) {
+ gfx_free_image(t->menu_button);
+ if (!(t->menu_button = gfx_load_image(t->menu_button_name)))
+ goto err;
+ }
+
+ if (t->click_name) {
+ snd_free_wav(t->click);
+ t->click = snd_load_wav(t->click_name);
+ }
+
+ free_theme_strings();
+
+ if (!t->use || !t->inv_a_up || !t->inv_a_down || !t->a_down || !t->a_up ||
+ !t->font || !t->inv_font || !t->menu_font || !t->menu_button) {
+ fprintf(stderr,"Can't init theme.\n");
+ return -1;
+ }
+ return 0;
+err:
+ fprintf(stderr, "Can not init theme!\n");
+ game_theme_free();
+ return -1;
+}
+
+static int theme_parse(const char *path)
+{
+ if (parse_ini(path, cmd_parser)) {
+ fprintf(stderr, "Theme parsed with errors!\n");
+// game_theme_free();
+ return -1;
+ }
+ return 0;
+}
+
+int theme_load(const char *name)
+{
+ if (theme_parse(name))
+ return 0; /* no theme loaded if error in parsing */
+ if (game_theme_init())
+ return -1;
+ return 0;
+}
+
+struct theme *themes = NULL;
+int themes_nr = 0;
+
+static int is_theme(const char *path, const char *n)
+{
+ int rc = 0;
+ char *p = getpath(path, n);
+ char *pp;
+ if (!p)
+ return 0;
+ pp = malloc(strlen(p) + strlen(THEME_FILE) + 1);
+ if (pp) {
+ strcpy(pp, p);
+ strcat(pp, THEME_FILE);
+ if (!access(pp, R_OK))
+ rc = 1;
+ free(pp);
+ }
+ free(p);
+ return rc;
+}
+
+static char *theme_name(const char *path, const char *d_name)
+{
+ int brk = 0;
+ char *p = getfilepath(path, THEME_FILE);
+ if (p) {
+ char *l; char line[1024];
+ FILE *fd = fopen(p, "r");
+ free(p);
+ if (!fd)
+ goto err;
+
+ while ((l = fgets(line, sizeof(line), fd)) && !brk) {
+ l = parse_tag(l, "$Name:", ";", &brk);
+ if (l)
+ return l;
+ }
+ fclose(fd);
+ }
+err:
+ return strdup(d_name);
+}
+
+int themes_lookup(const char *path)
+{
+ char *p;
+ int n = 0, i = 0;
+ DIR *d;
+ struct dirent *de;
+
+ if (!path)
+ return 0;
+
+ d = opendir(path);
+ if (!d)
+ return -1;
+ while ((de = readdir(d))) {
+ if (!is_theme(path, de->d_name))
+ continue;
+ n ++;
+ }
+
+ rewinddir(d);
+ if (!n)
+ return 0;
+ themes = realloc(themes, sizeof(struct theme) * (n + themes_nr));
+ while ((de = readdir(d)) && i < n) {
+ /*if (de->d_type != DT_DIR)
+ continue;*/
+ if (!is_theme(path, de->d_name))
+ continue;
+ p = getpath(path, de->d_name);
+ themes[themes_nr].path = p;
+ themes[themes_nr].dir = strdup(de->d_name);
+ themes[themes_nr].name = theme_name(p, de->d_name);
+ themes_nr ++;
+ i ++;
+ }
+ closedir(d);
+ return 0;
+}
+
+static struct theme *theme_lookup(const char *name)
+{
+ int i;
+ if (!name || !*name) {
+ if (themes_nr == 1)
+ return &themes[0];
+ }
+ for (i = 0; ipath) || theme_load(THEME_FILE)) {
+ chdir(cwd);
+ return -1;
+ }
+ chdir(cwd);
+ return 0;
+}
+
+int game_theme_select(const char *name)
+{
+ struct theme *theme;
+ theme = theme_lookup(name);
+ if (!theme)
+ return -1;
+ curtheme_dir = theme->dir;
+ return 0;
+}
+
+int game_default_theme(void)
+{
+ return game_theme_load(DEFAULT_THEME);
+}
diff --git a/src/sdl-instead/themes.h b/src/sdl-instead/themes.h
new file mode 100644
index 0000000..bf4af60
--- /dev/null
+++ b/src/sdl-instead/themes.h
@@ -0,0 +1,115 @@
+#ifndef __THEMES_INCLUDED_H
+#define __THEMES_INCLUDED_H
+
+#include "graphics.h"
+#include "sound.h"
+
+#define DEFAULT_THEME "default"
+#ifndef THEMES_PATH
+#define THEMES_PATH "./themes"
+#endif
+
+#define THEME_FILE "theme.ini"
+
+struct game_theme {
+ int w;
+ int h;
+ color_t bgcol;
+ char *bg_name;
+ img_t bg;
+ char *use_name;
+ img_t use;
+ int pad;
+
+ int win_x;
+ int win_y;
+ int win_w;
+ int win_h;
+
+ char *font_name;
+ int font_size;
+ fnt_t font;
+
+ int gfx_x;
+ int gfx_y;
+ int max_scene_w;
+ int max_scene_h;
+
+ char *a_up_name;
+ char *a_down_name;
+ img_t a_up;
+ img_t a_down;
+
+ color_t fgcol;
+ color_t lcol;
+ color_t acol;
+
+ int inv_x;
+ int inv_y;
+ int inv_w;
+ int inv_h;
+
+ color_t icol;
+ color_t ilcol;
+ color_t iacol;
+ char *inv_font_name;
+ int inv_font_size;
+ fnt_t inv_font;
+
+ char *inv_a_up_name;
+ char *inv_a_down_name;
+ img_t inv_a_up;
+ img_t inv_a_down;
+
+// int lstyle;
+// int ilstyle;
+
+ color_t menu_bg;
+ color_t menu_fg;
+ color_t border_col;
+ color_t menu_link;
+ color_t menu_alink;
+ int menu_alpha;
+ int border_w;
+ char *menu_font_name;
+ int menu_font_size;
+ fnt_t menu_font;
+
+ char *menu_button_name;
+ img_t menu_button;
+ int menu_button_x;
+ int menu_button_y;
+ int gfx_mode;
+ int inv_mode;
+ char *click_name;
+ void *click;
+};
+
+struct theme {
+ char *path;
+ char *name;
+ char *dir;
+};
+
+extern struct theme *themes;
+extern int themes_nr;
+extern char *curtheme_dir;
+
+extern struct game_theme game_theme;
+extern int game_default_theme(void);
+extern int game_theme_select(const char *name);
+
+extern int themes_lookup(const char *path);
+extern int game_theme_load(const char *name);
+extern int game_theme_free(void);
+extern int theme_load(const char *name);
+extern char *game_local_themes_path(void);
+
+#define GFX_MODE_FLOAT 0
+#define GFX_MODE_FIXED 1
+#define GFX_MODE_EMBEDDED 2
+
+#define INV_MODE_VERT 0
+#define INV_MODE_HORIZ 1
+
+#endif
diff --git a/src/sdl-instead/unix.c b/src/sdl-instead/unix.c
index c0cc9f5..ff196d0 100644
--- a/src/sdl-instead/unix.c
+++ b/src/sdl-instead/unix.c
@@ -6,14 +6,15 @@
#include
#include
#include
+#include
+#include
+
+#include "internals.h"
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
-extern char *curgame;
-extern char *curgame_dir;
-
static char save_path[PATH_MAX];
static char local_games_path[PATH_MAX];
static char local_themes_path[PATH_MAX];
@@ -24,6 +25,17 @@ void nsleep(int u)
usleep(u);
}
+char *game_locale(void)
+{
+ char *p;
+ char *s = strdup(getenv("LANG"));
+ if (!s)
+ return NULL;
+ if ((p = strchr(s, '_')))
+ *p = 0;
+ return s;
+}
+
char *game_local_games_path(void)
{
struct passwd *pw;
@@ -66,7 +78,7 @@ char *game_cfg_path(void)
char *game_save_path(int cr, int nr)
{
struct passwd *pw;
- if (!curgame)
+ if (!curgame_dir)
return NULL;
pw = getpwuid(getuid());
if (!pw)
diff --git a/src/sdl-instead/util.c b/src/sdl-instead/util.c
new file mode 100644
index 0000000..4176261
--- /dev/null
+++ b/src/sdl-instead/util.c
@@ -0,0 +1,218 @@
+#include "externals.h"
+#include "util.h"
+
+char *getfilepath(const char *d, const char *n)
+{
+ int i = strlen(d) + strlen(n) + 3;
+ char *p = malloc(i);
+ if (p) {
+ strcpy(p, d);
+ strcat(p, "/");
+ strcat(p, n);
+ }
+ return p;
+}
+
+char *getpath(const char *d, const char *n)
+{
+ char *p = getfilepath(d, n);
+ strcat(p, "/");
+ return p;
+}
+
+char *strip(char *s)
+{
+ char *e;
+ while (isspace(*s))
+ s ++;
+ if (!*s)
+ return s;
+ e = s + strlen(s) - 1;
+ while (e != s && isspace(*e)) {
+ *e = 0;
+ e --;
+ }
+ return s;
+}
+
+static int process_cmd(char *n, char *v, struct parser *cmd_parser)
+{
+ int i;
+ n = strip(n);
+ v = strip(v);
+ for (i = 0; cmd_parser[i].cmd; i++) {
+ if (!strcmp(cmd_parser[i].cmd, n)) {
+ return cmd_parser[i].fn(v, cmd_parser[i].p);
+ }
+ }
+ return -1;
+}
+
+static int fgetsesc(char *oline, size_t size, FILE *fp)
+{
+ int nr = 0;
+ char line[1024];
+ *oline = 0;
+ *line = 0;
+ while (fgets(line, sizeof(line), fp)) {
+ int i;
+ nr ++;
+ i = strcspn(line, "\n\r");
+ if (!i || !line[i])
+ break;
+ if (line[i - 1] == '\\') {
+ line[i - 1] = 0;
+ strncat(oline, line, size);
+ size -= strlen(line);
+ if (size <= 0)
+ return nr;
+ } else {
+ break;
+ }
+ }
+ strncat(oline, line, size);
+ return nr;
+}
+
+int parse_ini(const char *path, struct parser *cmd_parser)
+{
+ int nr;
+ int rc = 0;
+ int line_nr = 1;
+ FILE *fp;
+ char line[4096];
+ fp = fopen(path, "r");
+ if (!fp)
+ return -1;
+ while ((nr = fgetsesc(line, sizeof(line), fp))) {
+ char *p = line;
+ char *val;
+ int len;
+ line_nr += nr;
+ p += strspn(p, " \t");
+ if (*p == ';')
+ continue;
+ len = strcspn(p, "=");
+ if (p[len] != '=') /* just ignore it */
+ continue;
+ p[len] = 0;
+ val = p + len + 1;
+ len = strcspn(p, " \t");
+ p[len] = 0;
+// printf("%s\n", p);
+ val += strspn(val, " \t");
+ val[strcspn(val, ";\n")] = 0;
+ if (process_cmd(p, val, cmd_parser)) {
+ rc = -1;
+ fprintf(stderr, "Can't process cmd '%s' on line %d : %s\n", p, line_nr - nr, strerror(errno));
+ }
+ }
+ fclose(fp);
+ return rc;
+}
+
+int parse_string(const char *v, void *data)
+{
+ char **p = ((char **)data);
+ if (*p)
+ free(*p);
+ *p = strdup(v);
+ if (!*p)
+ return -1;
+ return 0;
+}
+
+int parse_esc_string(const char *v, void *data)
+{
+ int esc = 0;
+ char *ptr;
+ char **p = ((char **)data);
+ if (*p)
+ free(*p);
+ *p = strdup(v);
+ if (!*p)
+ return -1;
+ for (ptr = *p; *v; v ++) {
+ if (esc) {
+ switch (*v) {
+ case 'n':
+ *ptr = '\n';
+ break;
+ case '\\':
+ *ptr = '\\';
+ break;
+ case 'r':
+ *ptr = '\n';
+ break;
+ default:
+ break;
+ }
+ esc = 0;
+ ptr ++;
+ continue;
+ } else if (*v != '\\') {
+ *ptr = *v;
+ ptr ++;
+ continue;
+ } else
+ esc = 1;
+ }
+ *ptr = 0;
+ return 0;
+}
+
+int parse_int(const char *v, void *data)
+{
+ int *i = (int *)data;
+ char *eptr = NULL;
+ *i = strtol(v, &eptr, 0);
+ if (!eptr || *eptr)
+ return -1;
+ return 0;
+}
+
+int parse_full_path(const char *v, void *data)
+{
+ char cwd[PATH_MAX];
+ char **p = ((char **)data);
+ if (*p)
+ free(*p);
+ getcwd(cwd, sizeof(cwd));
+ *p = malloc(strlen(v) + strlen(cwd) + 2);
+ if (!*p)
+ return -1;
+ strcpy(*p, cwd);
+ strcat(*p,"/");
+ strcat(*p, v);
+ return 0;
+}
+
+void unix_path(char *path)
+{
+ char *p = path;
+ if (!path)
+ return;
+ while (*p) { /* bad bad Windows!!! */
+ if (*p == '\\')
+ *p = '/';
+ p ++;
+ }
+ return;
+}
+
+char *parse_tag(char *line, const char *tag, const char *comm, int *brk)
+{
+ char *l = line;
+ l += strspn(l, " \t");
+ if (strncmp(l, comm, strlen(comm))) { /* non coment block */
+ *brk = 1;
+ return NULL;
+ }
+ l += strlen(comm); l += strspn(l, " \t");
+ if (strncmp(l, tag, strlen(tag)))
+ return NULL;
+ l += strlen(tag);
+ l += strspn(l, " \t");
+ l[strcspn(l, "$\n\r")] = 0;
+ return strdup(l);
+}
diff --git a/src/sdl-instead/util.h b/src/sdl-instead/util.h
new file mode 100644
index 0000000..2648233
--- /dev/null
+++ b/src/sdl-instead/util.h
@@ -0,0 +1,31 @@
+#ifndef __UTIL_H_INCLUDED
+#define __UTIL_H_INCLUDED
+
+typedef int (*parser_fn)(const char *v, void *data);
+
+struct parser {
+ const char *cmd;
+ parser_fn fn;
+ void *p;
+};
+
+extern int parse_ini(const char *path, struct parser *cmd_parser);
+extern char *getpath(const char *d, const char *n);
+extern char *strip(char *s);
+char *getfilepath(const char *d, const char *n);
+
+extern int parse_esc_string(const char *v, void *data);
+extern int parse_string(const char *v, void *data);
+extern int parse_int(const char *v, void *data);
+extern int parse_full_path(const char *v, void *data);
+
+extern void unix_path(char *path);
+extern char *parse_tag(char *line, const char *tag, const char *comm, int *brk);
+
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+#define FREE(v) do { if ((v)) free((v)); v = NULL; } while(0)
+
+#endif
diff --git a/src/sdl-instead/windows.c b/src/sdl-instead/windows.c
index 38cdfff..fcd6a57 100644
--- a/src/sdl-instead/windows.c
+++ b/src/sdl-instead/windows.c
@@ -7,9 +7,7 @@
#include
#include
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
+#include "internals.h"
extern char *curgame;
extern char *curgame_dir;
@@ -24,6 +22,16 @@ void nsleep(int u)
Sleep(u);
}
+char *game_locale(void)
+{
+ char buff[64];
+ buff[0] = 0;
+ if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME,
+ buff,sizeof(buff) - 1))
+ return NULL;
+ return strdup(buff);
+}
+
char *app_dir( void );
char *game_local_games_path(void)