mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-12-24 18:21:50 +01:00
framework for multilanguage support
This commit is contained in:
parent
92cbfafede
commit
b533b8824f
12
Makefile.gc
12
Makefile.gc
@ -18,7 +18,7 @@ include $(DEVKITPPC)/gamecube_rules
|
|||||||
TARGET := snes9xgx-gc
|
TARGET := snes9xgx-gc
|
||||||
TARGETDIR := executables
|
TARGETDIR := executables
|
||||||
BUILD := build_gc
|
BUILD := build_gc
|
||||||
SOURCES := source/ngc/images source/ngc/sounds source/ngc/fonts \
|
SOURCES := source/ngc/images source/ngc/sounds source/ngc/fonts source/ngc/lang \
|
||||||
source/ngc/gui source/ngc source/snes9x source/sz
|
source/ngc/gui source/ngc source/snes9x source/sz
|
||||||
INCLUDES := source/snes9x source/ngc
|
INCLUDES := source/snes9x source/ngc
|
||||||
|
|
||||||
@ -71,6 +71,7 @@ CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
|||||||
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||||
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
|
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
|
||||||
|
LANGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.lang)))
|
||||||
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
|
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
|
||||||
PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm)))
|
PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm)))
|
||||||
|
|
||||||
@ -85,7 +86,8 @@ endif
|
|||||||
|
|
||||||
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
||||||
$(sFILES:.s=.o) $(SFILES:.S=.o) \
|
$(sFILES:.s=.o) $(SFILES:.S=.o) \
|
||||||
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) \
|
$(TTFFILES:.ttf=.ttf.o) $(LANGFILES:.lang=.lang.o) \
|
||||||
|
$(PNGFILES:.png=.png.o) \
|
||||||
$(PCMFILES:.pcm=.pcm.o)
|
$(PCMFILES:.pcm=.pcm.o)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
@ -137,11 +139,15 @@ $(OUTPUT).dol: $(OUTPUT).elf
|
|||||||
$(OUTPUT).elf: $(OFILES)
|
$(OUTPUT).elf: $(OFILES)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# This rule links in binary data with .ttf, .png, and .mp3 extensions
|
# This rule links in binary data with these extensions: ttf lang png pcm
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
%.ttf.o : %.ttf
|
%.ttf.o : %.ttf
|
||||||
@echo $(notdir $<)
|
@echo $(notdir $<)
|
||||||
$(bin2o)
|
$(bin2o)
|
||||||
|
|
||||||
|
%.lang.o : %.lang
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
%.png.o : %.png
|
%.png.o : %.png
|
||||||
@echo $(notdir $<)
|
@echo $(notdir $<)
|
||||||
|
12
Makefile.wii
12
Makefile.wii
@ -18,7 +18,7 @@ include $(DEVKITPPC)/wii_rules
|
|||||||
TARGET := snes9xgx-wii
|
TARGET := snes9xgx-wii
|
||||||
TARGETDIR := executables
|
TARGETDIR := executables
|
||||||
BUILD := build_wii
|
BUILD := build_wii
|
||||||
SOURCES := source/ngc/images source/ngc/sounds source/ngc/fonts \
|
SOURCES := source/ngc/images source/ngc/sounds source/ngc/fonts source/ngc/lang \
|
||||||
source/ngc/gui source/ngc source/snes9x source/sz source/unzip
|
source/ngc/gui source/ngc source/snes9x source/sz source/unzip
|
||||||
INCLUDES := source/snes9x source/ngc source/unzip
|
INCLUDES := source/snes9x source/ngc source/unzip
|
||||||
|
|
||||||
@ -71,6 +71,7 @@ CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
|||||||
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||||
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
|
TTFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ttf)))
|
||||||
|
LANGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.lang)))
|
||||||
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
|
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
|
||||||
OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg)))
|
OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg)))
|
||||||
PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm)))
|
PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm)))
|
||||||
@ -86,7 +87,8 @@ endif
|
|||||||
|
|
||||||
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
||||||
$(sFILES:.s=.o) $(SFILES:.S=.o) \
|
$(sFILES:.s=.o) $(SFILES:.S=.o) \
|
||||||
$(TTFFILES:.ttf=.ttf.o) $(PNGFILES:.png=.png.o) \
|
$(TTFFILES:.ttf=.ttf.o) $(LANGFILES:.lang=.lang.o) \
|
||||||
|
$(PNGFILES:.png=.png.o) \
|
||||||
$(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o)
|
$(OGGFILES:.ogg=.ogg.o) $(PCMFILES:.pcm=.pcm.o)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
@ -138,11 +140,15 @@ $(OUTPUT).dol: $(OUTPUT).elf
|
|||||||
$(OUTPUT).elf: $(OFILES)
|
$(OUTPUT).elf: $(OFILES)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# This rule links in binary data with .ttf, .png, and .mp3 extensions
|
# This rule links in binary data with these extensions: ttf lang png ogg pcm
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
%.ttf.o : %.ttf
|
%.ttf.o : %.ttf
|
||||||
@echo $(notdir $<)
|
@echo $(notdir $<)
|
||||||
$(bin2o)
|
$(bin2o)
|
||||||
|
|
||||||
|
%.lang.o : %.lang
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
%.png.o : %.png
|
%.png.o : %.png
|
||||||
@echo $(notdir $<)
|
@echo $(notdir $<)
|
||||||
|
@ -14,9 +14,32 @@
|
|||||||
|
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
|
|
||||||
|
// Fonts
|
||||||
extern const u8 font_ttf[];
|
extern const u8 font_ttf[];
|
||||||
extern const u32 font_ttf_size;
|
extern const u32 font_ttf_size;
|
||||||
|
|
||||||
|
// Languages
|
||||||
|
extern const u8 jp_lang[];
|
||||||
|
extern const u32 jp_lang_size;
|
||||||
|
extern const u8 en_lang[];
|
||||||
|
extern const u32 en_lang_size;
|
||||||
|
extern const u8 de_lang[];
|
||||||
|
extern const u32 de_lang_size;
|
||||||
|
extern const u8 fr_lang[];
|
||||||
|
extern const u32 fr_lang_size;
|
||||||
|
extern const u8 es_lang[];
|
||||||
|
extern const u32 es_lang_size;
|
||||||
|
extern const u8 it_lang[];
|
||||||
|
extern const u32 it_lang_size;
|
||||||
|
extern const u8 nl_lang[];
|
||||||
|
extern const u32 nl_lang_size;
|
||||||
|
extern const u8 zh_lang[];
|
||||||
|
extern const u32 zh_lang_size;
|
||||||
|
extern const u8 ko_lang[];
|
||||||
|
extern const u32 ko_lang_size;
|
||||||
|
|
||||||
|
// Sounds
|
||||||
|
|
||||||
extern const u8 bg_music_ogg[];
|
extern const u8 bg_music_ogg[];
|
||||||
extern const u32 bg_music_ogg_size;
|
extern const u32 bg_music_ogg_size;
|
||||||
|
|
||||||
@ -32,6 +55,8 @@ extern const u32 button_over_pcm_size;
|
|||||||
extern const u8 button_click_pcm[];
|
extern const u8 button_click_pcm[];
|
||||||
extern const u32 button_click_pcm_size;
|
extern const u32 button_click_pcm_size;
|
||||||
|
|
||||||
|
// Graphics
|
||||||
|
|
||||||
extern const u8 logo_png[];
|
extern const u8 logo_png[];
|
||||||
extern const u32 logo_png_size;
|
extern const u32 logo_png_size;
|
||||||
|
|
||||||
|
286
source/ngc/gettext.cpp
Normal file
286
source/ngc/gettext.cpp
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <gctypes.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "gettext.h"
|
||||||
|
#include "filelist.h"
|
||||||
|
#include "snes9xGX.h"
|
||||||
|
|
||||||
|
typedef struct _MSG
|
||||||
|
{
|
||||||
|
u32 id;
|
||||||
|
char* msgstr;
|
||||||
|
struct _MSG *next;
|
||||||
|
} MSG;
|
||||||
|
static MSG *baseMSG = 0;
|
||||||
|
|
||||||
|
#define HASHWORDBITS 32
|
||||||
|
|
||||||
|
/* Defines the so called `hashpjw' function by P.J. Weinberger
|
||||||
|
[see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
|
||||||
|
1986, 1987 Bell Telephone Laboratories, Inc.] */
|
||||||
|
static inline u32 hash_string(const char *str_param)
|
||||||
|
{
|
||||||
|
u32 hval, g;
|
||||||
|
const char *str = str_param;
|
||||||
|
|
||||||
|
/* Compute the hash value for the given string. */
|
||||||
|
hval = 0;
|
||||||
|
while (*str != '\0')
|
||||||
|
{
|
||||||
|
hval <<= 4;
|
||||||
|
hval += (u8) * str++;
|
||||||
|
g = hval & ((u32) 0xf << (HASHWORDBITS - 4));
|
||||||
|
if (g != 0)
|
||||||
|
{
|
||||||
|
hval ^= g >> (HASHWORDBITS - 8);
|
||||||
|
hval ^= g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expand some escape sequences found in the argument string. */
|
||||||
|
static char *
|
||||||
|
expand_escape(const char *str)
|
||||||
|
{
|
||||||
|
char *retval, *rp;
|
||||||
|
const char *cp = str;
|
||||||
|
|
||||||
|
retval = (char *) malloc(strlen(str) + 1);
|
||||||
|
if (retval == NULL)
|
||||||
|
return NULL;
|
||||||
|
rp = retval;
|
||||||
|
|
||||||
|
while (cp[0] != '\0' && cp[0] != '\\')
|
||||||
|
*rp++ = *cp++;
|
||||||
|
if (cp[0] == '\0')
|
||||||
|
goto terminate;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Here cp[0] == '\\'. */
|
||||||
|
switch (*++cp)
|
||||||
|
{
|
||||||
|
case '\"': /* " */
|
||||||
|
*rp++ = '\"';
|
||||||
|
++cp;
|
||||||
|
break;
|
||||||
|
case 'a': /* alert */
|
||||||
|
*rp++ = '\a';
|
||||||
|
++cp;
|
||||||
|
break;
|
||||||
|
case 'b': /* backspace */
|
||||||
|
*rp++ = '\b';
|
||||||
|
++cp;
|
||||||
|
break;
|
||||||
|
case 'f': /* form feed */
|
||||||
|
*rp++ = '\f';
|
||||||
|
++cp;
|
||||||
|
break;
|
||||||
|
case 'n': /* new line */
|
||||||
|
*rp++ = '\n';
|
||||||
|
++cp;
|
||||||
|
break;
|
||||||
|
case 'r': /* carriage return */
|
||||||
|
*rp++ = '\r';
|
||||||
|
++cp;
|
||||||
|
break;
|
||||||
|
case 't': /* horizontal tab */
|
||||||
|
*rp++ = '\t';
|
||||||
|
++cp;
|
||||||
|
break;
|
||||||
|
case 'v': /* vertical tab */
|
||||||
|
*rp++ = '\v';
|
||||||
|
++cp;
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
*rp = '\\';
|
||||||
|
++cp;
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
{
|
||||||
|
int ch = *cp++ - '0';
|
||||||
|
|
||||||
|
if (*cp >= '0' && *cp <= '7')
|
||||||
|
{
|
||||||
|
ch *= 8;
|
||||||
|
ch += *cp++ - '0';
|
||||||
|
|
||||||
|
if (*cp >= '0' && *cp <= '7')
|
||||||
|
{
|
||||||
|
ch *= 8;
|
||||||
|
ch += *cp++ - '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*rp = ch;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*rp = '\\';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cp[0] != '\0' && cp[0] != '\\')
|
||||||
|
*rp++ = *cp++;
|
||||||
|
} while (cp[0] != '\0');
|
||||||
|
|
||||||
|
/* Terminate string. */
|
||||||
|
terminate: *rp = '\0';
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MSG *findMSG(u32 id)
|
||||||
|
{
|
||||||
|
MSG *msg;
|
||||||
|
for (msg = baseMSG; msg; msg = msg->next)
|
||||||
|
{
|
||||||
|
if (msg->id == id)
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MSG *setMSG(const char *msgid, const char *msgstr)
|
||||||
|
{
|
||||||
|
u32 id = hash_string(msgid);
|
||||||
|
MSG *msg = findMSG(id);
|
||||||
|
if (!msg)
|
||||||
|
{
|
||||||
|
msg = (MSG *) malloc(sizeof(MSG));
|
||||||
|
msg->id = id;
|
||||||
|
msg->msgstr = NULL;
|
||||||
|
msg->next = baseMSG;
|
||||||
|
baseMSG = msg;
|
||||||
|
}
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
if (msgstr)
|
||||||
|
{
|
||||||
|
if (msg->msgstr)
|
||||||
|
free(msg->msgstr);
|
||||||
|
//msg->msgstr = strdup(msgstr);
|
||||||
|
msg->msgstr = expand_escape(msgstr);
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gettextCleanUp(void)
|
||||||
|
{
|
||||||
|
while (baseMSG)
|
||||||
|
{
|
||||||
|
MSG *nextMsg = baseMSG->next;
|
||||||
|
free(baseMSG->msgstr);
|
||||||
|
free(baseMSG);
|
||||||
|
baseMSG = nextMsg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char * memfgets(char * dst, int maxlen, char * src)
|
||||||
|
{
|
||||||
|
if(!src || !dst || maxlen <= 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char * newline = strchr(src, '\n');
|
||||||
|
|
||||||
|
if(newline == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memcpy(dst, src, (newline-src));
|
||||||
|
dst[(newline-src)] = 0;
|
||||||
|
return ++newline;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoadLanguage()
|
||||||
|
{
|
||||||
|
char line[200];
|
||||||
|
char *lastID = NULL;
|
||||||
|
|
||||||
|
char *file, *eof;
|
||||||
|
|
||||||
|
switch(GCSettings.language)
|
||||||
|
{
|
||||||
|
case LANG_JAPANESE: file = (char *)jp_lang; eof = file + jp_lang_size; break;
|
||||||
|
case LANG_ENGLISH: file = (char *)en_lang; eof = file + en_lang_size; break;
|
||||||
|
case LANG_GERMAN: file = (char *)de_lang; eof = file + de_lang_size; break;
|
||||||
|
case LANG_FRENCH: file = (char *)fr_lang; eof = file + fr_lang_size; break;
|
||||||
|
case LANG_SPANISH: file = (char *)es_lang; eof = file + es_lang_size; break;
|
||||||
|
case LANG_ITALIAN: file = (char *)it_lang; eof = file + it_lang_size; break;
|
||||||
|
case LANG_DUTCH: file = (char *)nl_lang; eof = file + nl_lang_size; break;
|
||||||
|
case LANG_SIMP_CHINESE:
|
||||||
|
case LANG_TRAD_CHINESE: file = (char *)zh_lang; eof = file + zh_lang_size; break;
|
||||||
|
case LANG_KOREAN: file = (char *)ko_lang; eof = file + ko_lang_size; break;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gettextCleanUp();
|
||||||
|
|
||||||
|
while (file && file < eof)
|
||||||
|
{
|
||||||
|
file = memfgets(line, sizeof(line), file);
|
||||||
|
|
||||||
|
if(!file)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// lines starting with # are comments
|
||||||
|
if (line[0] == '#')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strncmp(line, "msgid \"", 7) == 0)
|
||||||
|
{
|
||||||
|
char *msgid, *end;
|
||||||
|
if (lastID)
|
||||||
|
{
|
||||||
|
free(lastID);
|
||||||
|
lastID = NULL;
|
||||||
|
}
|
||||||
|
msgid = &line[7];
|
||||||
|
end = strrchr(msgid, '"');
|
||||||
|
if (end && end - msgid > 1)
|
||||||
|
{
|
||||||
|
*end = 0;
|
||||||
|
lastID = strdup(msgid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strncmp(line, "msgstr \"", 8) == 0)
|
||||||
|
{
|
||||||
|
char *msgstr, *end;
|
||||||
|
|
||||||
|
if (lastID == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
msgstr = &line[8];
|
||||||
|
end = strrchr(msgstr, '"');
|
||||||
|
if (end && end - msgstr > 1)
|
||||||
|
{
|
||||||
|
*end = 0;
|
||||||
|
setMSG(lastID, msgstr);
|
||||||
|
}
|
||||||
|
free(lastID);
|
||||||
|
lastID = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *gettext(const char *msgid)
|
||||||
|
{
|
||||||
|
MSG *msg = findMSG(hash_string(msgid));
|
||||||
|
|
||||||
|
if (msg && msg->msgstr)
|
||||||
|
{
|
||||||
|
return msg->msgstr;
|
||||||
|
}
|
||||||
|
return msgid;
|
||||||
|
}
|
12
source/ngc/gettext.h
Normal file
12
source/ngc/gettext.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef _GETTEXT_H_
|
||||||
|
#define _GETTEXT_H_
|
||||||
|
|
||||||
|
bool LoadLanguage();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* input msg = a text in ASCII
|
||||||
|
* output = the translated msg in utf-8
|
||||||
|
*/
|
||||||
|
const char *gettext(const char *msg);
|
||||||
|
|
||||||
|
#endif /* _GETTEXT_H_ */
|
@ -393,11 +393,15 @@ class GuiElement
|
|||||||
//!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE)
|
//!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE)
|
||||||
//!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE)
|
//!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE)
|
||||||
virtual void SetAlignment(int hor, int vert);
|
virtual void SetAlignment(int hor, int vert);
|
||||||
|
//!Called when the language has changed, to obtain new text values for all text elements
|
||||||
|
virtual void ResetText();
|
||||||
//!Called constantly to allow the element to respond to the current input data
|
//!Called constantly to allow the element to respond to the current input data
|
||||||
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
||||||
virtual void Update(GuiTrigger * t);
|
virtual void Update(GuiTrigger * t);
|
||||||
//!Called constantly to redraw the element
|
//!Called constantly to redraw the element
|
||||||
virtual void Draw();
|
virtual void Draw();
|
||||||
|
//!Called constantly to redraw the element's tooltip
|
||||||
|
virtual void DrawTooltip();
|
||||||
protected:
|
protected:
|
||||||
GuiTrigger * trigger[2]; //!< GuiTriggers (input actions) that this element responds to
|
GuiTrigger * trigger[2]; //!< GuiTriggers (input actions) that this element responds to
|
||||||
UpdateCallback updateCB; //!< Callback function to call when this element is updated
|
UpdateCallback updateCB; //!< Callback function to call when this element is updated
|
||||||
@ -495,8 +499,12 @@ class GuiWindow : public GuiElement
|
|||||||
//!Moves the selected element to the element above or below
|
//!Moves the selected element to the element above or below
|
||||||
//!\param d Direction to move (-1 = up, 1 = down)
|
//!\param d Direction to move (-1 = up, 1 = down)
|
||||||
void MoveSelectionVert(int d);
|
void MoveSelectionVert(int d);
|
||||||
|
//!Resets the text for all contained elements
|
||||||
|
void ResetText();
|
||||||
//!Draws all the elements in this GuiWindow
|
//!Draws all the elements in this GuiWindow
|
||||||
void Draw();
|
void Draw();
|
||||||
|
//!Draws all of the tooltips in this GuiWindow
|
||||||
|
void DrawTooltip();
|
||||||
//!Updates the window and all elements contains within
|
//!Updates the window and all elements contains within
|
||||||
//!Allows the GuiWindow and all elements to respond to the input data specified
|
//!Allows the GuiWindow and all elements to respond to the input data specified
|
||||||
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
||||||
@ -647,6 +655,8 @@ class GuiText : public GuiElement
|
|||||||
//!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE)
|
//!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE)
|
||||||
//!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE)
|
//!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE)
|
||||||
void SetAlignment(int hor, int vert);
|
void SetAlignment(int hor, int vert);
|
||||||
|
//!Updates the text to the selected language
|
||||||
|
void ResetText();
|
||||||
//!Constantly called to draw the text
|
//!Constantly called to draw the text
|
||||||
void Draw();
|
void Draw();
|
||||||
protected:
|
protected:
|
||||||
@ -664,6 +674,32 @@ class GuiText : public GuiElement
|
|||||||
bool wrap; //!< Wrapping toggle
|
bool wrap; //!< Wrapping toggle
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//!Display, manage, and manipulate tooltips in the GUI
|
||||||
|
class GuiTooltip : public GuiElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!Constructor
|
||||||
|
//!\param t Text
|
||||||
|
GuiTooltip(const char *t);
|
||||||
|
//!Destructor
|
||||||
|
~GuiTooltip();
|
||||||
|
//!Gets the element's current scale
|
||||||
|
float GetScale();
|
||||||
|
//!Sets the text of the GuiTooltip element
|
||||||
|
//!\param t Text
|
||||||
|
void SetText(const char * t);
|
||||||
|
//!Constantly called to draw the GuiTooltip
|
||||||
|
void DrawTooltip();
|
||||||
|
|
||||||
|
time_t time1, time2; //!< Tooltip times
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GuiImage leftImage; //!< Tooltip left image
|
||||||
|
GuiImage tileImage; //!< Tooltip tile image
|
||||||
|
GuiImage rightImage; //!< Tooltip right image
|
||||||
|
GuiText *text; //!< Tooltip text
|
||||||
|
};
|
||||||
|
|
||||||
//!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional)
|
//!Display, manage, and manipulate buttons in the GUI. Buttons can have images, icons, text, and sound set (all of which are optional)
|
||||||
class GuiButton : public GuiElement
|
class GuiButton : public GuiElement
|
||||||
{
|
{
|
||||||
@ -671,7 +707,7 @@ class GuiButton : public GuiElement
|
|||||||
//!Constructor
|
//!Constructor
|
||||||
//!\param w Width
|
//!\param w Width
|
||||||
//!\param h Height
|
//!\param h Height
|
||||||
GuiButton(int w, int h);
|
GuiButton(int w = 0, int h = 0);
|
||||||
//!Destructor
|
//!Destructor
|
||||||
~GuiButton();
|
~GuiButton();
|
||||||
//!Sets the button's image
|
//!Sets the button's image
|
||||||
@ -723,8 +759,15 @@ class GuiButton : public GuiElement
|
|||||||
//!Sets the sound to play on click
|
//!Sets the sound to play on click
|
||||||
//!\param s Pointer to GuiSound object
|
//!\param s Pointer to GuiSound object
|
||||||
void SetSoundClick(GuiSound * s);
|
void SetSoundClick(GuiSound * s);
|
||||||
|
//!Sets the tooltip for the button
|
||||||
|
//!\param t Tooltip
|
||||||
|
void SetTooltip(GuiTooltip * t);
|
||||||
//!Constantly called to draw the GuiButton
|
//!Constantly called to draw the GuiButton
|
||||||
void Draw();
|
void Draw();
|
||||||
|
//!Constantly called to draw the GuiButton's tooltip
|
||||||
|
void DrawTooltip();
|
||||||
|
//!Resets the text for all contained elements
|
||||||
|
void ResetText();
|
||||||
//!Constantly called to allow the GuiButton to respond to updated input data
|
//!Constantly called to allow the GuiButton to respond to updated input data
|
||||||
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
|
||||||
void Update(GuiTrigger * t);
|
void Update(GuiTrigger * t);
|
||||||
@ -744,6 +787,7 @@ class GuiButton : public GuiElement
|
|||||||
GuiSound * soundOver; //!< Sound to play for STATE_SELECTED
|
GuiSound * soundOver; //!< Sound to play for STATE_SELECTED
|
||||||
GuiSound * soundHold; //!< Sound to play for STATE_HELD
|
GuiSound * soundHold; //!< Sound to play for STATE_HELD
|
||||||
GuiSound * soundClick; //!< Sound to play for STATE_CLICKED
|
GuiSound * soundClick; //!< Sound to play for STATE_CLICKED
|
||||||
|
GuiTooltip * tooltip; //!< Tooltip to display on over
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _keytype {
|
typedef struct _keytype {
|
||||||
@ -808,6 +852,7 @@ class GuiOptionBrowser : public GuiElement
|
|||||||
public:
|
public:
|
||||||
GuiOptionBrowser(int w, int h, OptionList * l);
|
GuiOptionBrowser(int w, int h, OptionList * l);
|
||||||
~GuiOptionBrowser();
|
~GuiOptionBrowser();
|
||||||
|
void SetCol1Position(int x);
|
||||||
void SetCol2Position(int x);
|
void SetCol2Position(int x);
|
||||||
int FindMenuItem(int c, int d);
|
int FindMenuItem(int c, int d);
|
||||||
int GetClickedOption();
|
int GetClickedOption();
|
||||||
@ -815,6 +860,7 @@ class GuiOptionBrowser : public GuiElement
|
|||||||
void SetFocus(int f);
|
void SetFocus(int f);
|
||||||
void Draw();
|
void Draw();
|
||||||
void TriggerUpdate();
|
void TriggerUpdate();
|
||||||
|
void ResetText();
|
||||||
void Update(GuiTrigger * t);
|
void Update(GuiTrigger * t);
|
||||||
GuiText * optionVal[PAGESIZE];
|
GuiText * optionVal[PAGESIZE];
|
||||||
protected:
|
protected:
|
||||||
@ -921,6 +967,7 @@ class GuiFileBrowser : public GuiElement
|
|||||||
void ResetState();
|
void ResetState();
|
||||||
void SetFocus(int f);
|
void SetFocus(int f);
|
||||||
void Draw();
|
void Draw();
|
||||||
|
void DrawTooltip();
|
||||||
void TriggerUpdate();
|
void TriggerUpdate();
|
||||||
void Update(GuiTrigger * t);
|
void Update(GuiTrigger * t);
|
||||||
GuiButton * fileList[FILE_PAGESIZE];
|
GuiButton * fileList[FILE_PAGESIZE];
|
||||||
|
@ -37,6 +37,7 @@ GuiButton::GuiButton(int w, int h)
|
|||||||
soundOver = NULL;
|
soundOver = NULL;
|
||||||
soundHold = NULL;
|
soundHold = NULL;
|
||||||
soundClick = NULL;
|
soundClick = NULL;
|
||||||
|
tooltip = NULL;
|
||||||
selectable = true;
|
selectable = true;
|
||||||
holdable = false;
|
holdable = false;
|
||||||
clickable = true;
|
clickable = true;
|
||||||
@ -121,6 +122,12 @@ void GuiButton::SetSoundClick(GuiSound * snd)
|
|||||||
{
|
{
|
||||||
soundClick = snd;
|
soundClick = snd;
|
||||||
}
|
}
|
||||||
|
void GuiButton::SetTooltip(GuiTooltip* t)
|
||||||
|
{
|
||||||
|
tooltip = t;
|
||||||
|
if(t)
|
||||||
|
tooltip->SetParent(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw the button on screen
|
* Draw the button on screen
|
||||||
@ -177,6 +184,23 @@ void GuiButton::Draw()
|
|||||||
this->UpdateEffects();
|
this->UpdateEffects();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiButton::DrawTooltip()
|
||||||
|
{
|
||||||
|
if(tooltip)
|
||||||
|
tooltip->DrawTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiButton::ResetText()
|
||||||
|
{
|
||||||
|
for(int i=0; i<3; i++)
|
||||||
|
{
|
||||||
|
if(label[i])
|
||||||
|
label[i]->ResetText();
|
||||||
|
if(labelOver[i])
|
||||||
|
labelOver[i]->ResetText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GuiButton::Update(GuiTrigger * t)
|
void GuiButton::Update(GuiTrigger * t)
|
||||||
{
|
{
|
||||||
if(state == STATE_CLICKED || state == STATE_DISABLED || !t)
|
if(state == STATE_CLICKED || state == STATE_DISABLED || !t)
|
||||||
|
@ -511,13 +511,18 @@ int GuiElement::GetSelected()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void GuiElement::ResetText()
|
||||||
* Draw an element on screen.
|
{
|
||||||
*/
|
}
|
||||||
|
|
||||||
void GuiElement::Draw()
|
void GuiElement::Draw()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiElement::DrawTooltip()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool GuiElement::IsInside(int x, int y)
|
bool GuiElement::IsInside(int x, int y)
|
||||||
{
|
{
|
||||||
if(unsigned(x - this->GetLeft()) < unsigned(width)
|
if(unsigned(x - this->GetLeft()) < unsigned(width)
|
||||||
|
@ -224,6 +224,10 @@ void GuiFileBrowser::Draw()
|
|||||||
this->UpdateEffects();
|
this->UpdateEffects();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiFileBrowser::DrawTooltip()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void GuiFileBrowser::Update(GuiTrigger * t)
|
void GuiFileBrowser::Update(GuiTrigger * t)
|
||||||
{
|
{
|
||||||
if(state == STATE_DISABLED || !t)
|
if(state == STATE_DISABLED || !t)
|
||||||
|
@ -134,6 +134,12 @@ GuiOptionBrowser::~GuiOptionBrowser()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiOptionBrowser::SetCol1Position(int x)
|
||||||
|
{
|
||||||
|
for(int i=0; i<PAGESIZE; i++)
|
||||||
|
optionTxt[i]->SetPosition(x,0);
|
||||||
|
}
|
||||||
|
|
||||||
void GuiOptionBrowser::SetCol2Position(int x)
|
void GuiOptionBrowser::SetCol2Position(int x)
|
||||||
{
|
{
|
||||||
for(int i=0; i<PAGESIZE; i++)
|
for(int i=0; i<PAGESIZE; i++)
|
||||||
@ -234,6 +240,22 @@ void GuiOptionBrowser::TriggerUpdate()
|
|||||||
listChanged = true;
|
listChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiOptionBrowser::ResetText()
|
||||||
|
{
|
||||||
|
int next = listOffset;
|
||||||
|
|
||||||
|
for(int i=0; i<PAGESIZE; i++)
|
||||||
|
{
|
||||||
|
if(next >= 0)
|
||||||
|
{
|
||||||
|
optionBtn[i]->ResetText();
|
||||||
|
next = this->FindMenuItem(next, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GuiOptionBrowser::Update(GuiTrigger * t)
|
void GuiOptionBrowser::Update(GuiTrigger * t)
|
||||||
{
|
{
|
||||||
if(state == STATE_DISABLED || !t)
|
if(state == STATE_DISABLED || !t)
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
#include "../gettext.h"
|
||||||
|
|
||||||
static GXColor presetColor = (GXColor){255, 255, 255, 255};
|
static GXColor presetColor = (GXColor){255, 255, 255, 255};
|
||||||
static int currentSize = 0;
|
static int currentSize = 0;
|
||||||
@ -46,7 +47,7 @@ GuiText::GuiText(const char * t, int s, GXColor c)
|
|||||||
if(t)
|
if(t)
|
||||||
{
|
{
|
||||||
origText = strdup(t);
|
origText = strdup(t);
|
||||||
text = charToWideChar(t);
|
text = charToWideChar(gettext(t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +76,7 @@ GuiText::GuiText(const char * t)
|
|||||||
if(t)
|
if(t)
|
||||||
{
|
{
|
||||||
origText = strdup(t);
|
origText = strdup(t);
|
||||||
text = charToWideChar(t);
|
text = charToWideChar(gettext(t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +111,7 @@ void GuiText::SetText(const char * t)
|
|||||||
if(t)
|
if(t)
|
||||||
{
|
{
|
||||||
origText = strdup(t);
|
origText = strdup(t);
|
||||||
text = charToWideChar(t);
|
text = charToWideChar(gettext(t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,6 +201,16 @@ void GuiText::SetAlignment(int hor, int vert)
|
|||||||
alignmentVert = vert;
|
alignmentVert = vert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiText::ResetText()
|
||||||
|
{
|
||||||
|
if(!origText)
|
||||||
|
return;
|
||||||
|
if(text)
|
||||||
|
delete[] text;
|
||||||
|
|
||||||
|
text = charToWideChar(gettext(origText));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw the text on screen
|
* Draw the text on screen
|
||||||
*/
|
*/
|
||||||
|
@ -99,6 +99,18 @@ void GuiWindow::Draw()
|
|||||||
Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0xbe, 0xca, 0xd5, 0x70},1);
|
Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0xbe, 0xca, 0xd5, 0x70},1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiWindow::DrawTooltip()
|
||||||
|
{
|
||||||
|
if(_elements.size() == 0 || !this->IsVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (u8 i = 0; i < _elements.size(); i++)
|
||||||
|
{
|
||||||
|
try { _elements.at(i)->DrawTooltip(); }
|
||||||
|
catch (const std::exception& e) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GuiWindow::ResetState()
|
void GuiWindow::ResetState()
|
||||||
{
|
{
|
||||||
if(state != STATE_DISABLED)
|
if(state != STATE_DISABLED)
|
||||||
@ -384,6 +396,15 @@ void GuiWindow::MoveSelectionVert(int dir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiWindow::ResetText()
|
||||||
|
{
|
||||||
|
for (u8 i = 0; i < _elements.size(); i++)
|
||||||
|
{
|
||||||
|
try { _elements.at(i)->ResetText(); }
|
||||||
|
catch (const std::exception& e) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GuiWindow::Update(GuiTrigger * t)
|
void GuiWindow::Update(GuiTrigger * t)
|
||||||
{
|
{
|
||||||
if(_elements.size() == 0 || (state == STATE_DISABLED && parentElement))
|
if(_elements.size() == 0 || (state == STATE_DISABLED && parentElement))
|
||||||
|
@ -263,6 +263,9 @@ UpdateGUI (void *arg)
|
|||||||
UpdatePads();
|
UpdatePads();
|
||||||
mainWindow->Draw();
|
mainWindow->Draw();
|
||||||
|
|
||||||
|
if (mainWindow->GetState() != STATE_DISABLED)
|
||||||
|
mainWindow->DrawTooltip();
|
||||||
|
|
||||||
#ifdef HW_RVL
|
#ifdef HW_RVL
|
||||||
i = 3;
|
i = 3;
|
||||||
do
|
do
|
||||||
|
@ -346,7 +346,7 @@ void USBGeckoOutput()
|
|||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
//USBGeckoOutput(); // uncomment to enable USB gecko output
|
USBGeckoOutput(); // uncomment to enable USB gecko output
|
||||||
__exception_setreload(8);
|
__exception_setreload(8);
|
||||||
|
|
||||||
#ifdef HW_DOL
|
#ifdef HW_DOL
|
||||||
|
@ -61,6 +61,19 @@ enum
|
|||||||
const char ctrlName[6][24] =
|
const char ctrlName[6][24] =
|
||||||
{ "SNES Controller", "SNES Mouse", "Superscope", "Justifier", "SNES Controllers (2)", "SNES Controllers (4)" };
|
{ "SNES Controller", "SNES Mouse", "Superscope", "Justifier", "SNES Controllers (2)", "SNES Controllers (4)" };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LANG_JAPANESE = 0,
|
||||||
|
LANG_ENGLISH,
|
||||||
|
LANG_GERMAN,
|
||||||
|
LANG_FRENCH,
|
||||||
|
LANG_SPANISH,
|
||||||
|
LANG_ITALIAN,
|
||||||
|
LANG_DUTCH,
|
||||||
|
LANG_SIMP_CHINESE,
|
||||||
|
LANG_TRAD_CHINESE,
|
||||||
|
LANG_KOREAN
|
||||||
|
};
|
||||||
|
|
||||||
struct SGCSettings{
|
struct SGCSettings{
|
||||||
int AutoLoad;
|
int AutoLoad;
|
||||||
int AutoSave;
|
int AutoSave;
|
||||||
@ -89,6 +102,7 @@ struct SGCSettings{
|
|||||||
int MusicVolume;
|
int MusicVolume;
|
||||||
int SFXVolume;
|
int SFXVolume;
|
||||||
int Rumble;
|
int Rumble;
|
||||||
|
int language;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ExitApp();
|
void ExitApp();
|
||||||
|
@ -84,11 +84,8 @@ LoadSRAMAuto (bool silent)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(LoadSRAM(filepath2, silent))
|
if(LoadSRAM(filepath2, silent))
|
||||||
{
|
|
||||||
// rename this file - append Auto
|
|
||||||
rename(filepath2, filepath); // rename file (to avoid duplicates)
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,8 +138,21 @@ SaveSRAMAuto (bool silent)
|
|||||||
{
|
{
|
||||||
char filepath[1024];
|
char filepath[1024];
|
||||||
|
|
||||||
if(!MakeFilePath(filepath, FILE_SRAM, Memory.ROMFilename, 0))
|
// look for file with no number or Auto appended
|
||||||
|
if(!MakeFilePath(filepath, FILE_SRAM, Memory.ROMFilename, -1))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
FILE * fp = fopen (filepath, "rb");
|
||||||
|
|
||||||
|
if(fp) // file found
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!MakeFilePath(filepath, FILE_SRAM, Memory.ROMFilename, 0))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return SaveSRAM(filepath, silent);
|
return SaveSRAM(filepath, silent);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user