Index: tools/voice.pl =================================================================== --- tools/voice.pl (revision 18096) +++ tools/voice.pl (working copy) @@ -263,8 +263,8 @@ } case "espeak" { # xxx: $tts_engine_opts isn't used - $cmd = "espeak $tts_engine_opts -w \"$output\""; - print("> $cmd\n") if $verbose; + $cmd = "speak $tts_engine_opts -w \"$output\""; + print("> $cmd\n"); open(ESPEAK, "| $cmd"); print ESPEAK $string . "\n"; close(ESPEAK); @@ -326,9 +326,11 @@ my ($language, $target, $encoder, $encoder_opts, $tts_engine, $tts_engine_opts) = @_; my $english = dirname($0) . '/../apps/lang/english.lang'; my $langfile = dirname($0) . '/../apps/lang/' . $language . '.lang'; + my $plugin_english = dirname($0) . '/../apps/plugins/lang/english.lang'; + my $plugin_langfile = dirname($0) . '/../apps/plugins/lang/' . $language . '.lang'; my $id = ''; my $voice = ''; - my $cmd = "genlang -o -t=$target -e=$english $langfile 2>/dev/null"; + my $cmd = "genlang -o -t=$target -k=0 -e=$english $langfile 2>/dev/null && genlang -o -t=$target -k=1 -e=$plugin_english $plugin_langfile 2>/dev/null"; my $pool_file; open(VOICEFONTIDS, "> voicefontids"); my $i = 0; @@ -385,7 +387,7 @@ if (defined($ENV{'POOL'})) { copy($mp3, $pool_file); } - unlink($wav); + #unlink($wav); } $voice = ""; $id = ""; @@ -464,7 +466,7 @@ # 500 seems to be a reasonable default for now encodewav($wav, $mp3, $encoder, $encoder_opts, $tts_object); synchronize($tts_object); - unlink($wav); + #unlink($wav); } } @@ -504,7 +506,7 @@ $t, $l, $e, $E, $s, $S); generateclips($l, $t, $e, $E, $s, $S); createvoice($l, $i); - deletemp3s(); + #deletemp3s(); } elsif ($C) { printf("Generating .talk clips\n Path: %s\n Language: %s\n Encoder (options): %s (%s)\n TTS Engine (options): %s (%s)\n", $ARGV[0], $l, $e, $E, $s, $S); Index: tools/genlang =================================================================== --- tools/genlang (revision 18096) +++ tools/genlang (working copy) @@ -11,7 +11,9 @@ # # binary version for the binary lang file -my $langversion = 4; # 3 was the latest one used in the v1 format +# 4 was the latest one used in the v2 format +# 3 was the latest one used in the v1 format +my $langversion = 5; # A note for future users and readers: The original v1 language system allowed # the build to create and use a different language than english built-in. We @@ -20,6 +22,12 @@ # figured it was boring and unnecessary to write support for now since we # don't use it anymore. +my %plugin2num = + ('' => 1, + 'blackjack' => 2, + 'chessbox' => 3, + 'chopper' => 4); + if(!$ARGV[0]) { print < @@ -51,6 +59,10 @@ -i= The target id number, needed for -b. + -k= + The type of language file being generated. If not specified, lang type is + assumed to be "core". + -o Voice mode output. Outputs all id: and voice: lines for the given target! @@ -80,6 +92,7 @@ my $english = $e; my $voiceout = $o; +my $kind = ($k eq "plugin") ? "1" : "0"; my $check = ($binary?1:0) + ($prefix?1:0) + ($update?1:0) + ($voiceout?1:0); @@ -92,6 +105,11 @@ exit; } +if(($kind != 0 && $kind != 1) || !defined($kind)) { + print "Please specify the kind of language file (with -k)!\n"; + exit; +} + if(($binary || $update || $voiceout) && !$english) { print "Please use -e too when you use -b, -o or -u\n"; exit; @@ -196,6 +214,7 @@ my $idnum=0; # start with a true number my $vidnum=0x8000; # first voice id + my $plidnum=0x16000; # first plugin lang id open(ENG, "<$english") || die "Error: can't open $english"; my @phrase; my $id; @@ -219,6 +238,11 @@ $idmap{$id}=$vidnum; $vidnum++; } + #elsif($id =~ /^P_LANG_/) { + # Assign an ID number to this entry + # $idmap{$id}=$plidnum; + # $plidnum++; + #} else { # Assign an ID number to this entry $idmap{$id}=$idnum; @@ -352,6 +376,7 @@ my $idcount; # counter for lang ID numbers my $voiceid=0x8000; # counter for voice-only ID numbers +my $plangid=0x16000; # count for plugin lang ID numbers # # Now start the scanning of the selected language string @@ -359,6 +384,7 @@ open(LANG, "<$input") || die "Error: couldn't read language file named $input\n"; my @phrase; +my @num_strings; while() { $line++; @@ -388,15 +414,24 @@ if($part eq "/phrase") { # closing the phrase + my $user = 0; my $idstr = $phrase{'id'}; my $idnum; + + $user = $plugin2num{$phrase{'user'}}; + if(!$user) { + print "unknown plugin!\n"; + } + else { + $num_strings[$user]++; + } if($binary && !$english{$idstr}) { # $idstr doesn't exist for english, skip it\n"; } - elsif($dest =~ /^none\z/i) { - # "none" as dest (without quotes) means that this entire - # phrase is to be ignored + elsif($dest =~ /^none\z/i || $user =~ /^none\z/i) { + # "none" (without quotes) as dest or as the user + # means that this entire phrase is to be ignored } elsif(!$update) { # we don't do the fully detailed analysis when we "update" @@ -431,6 +466,9 @@ if($idstr =~ /^VOICE/) { $idnum = $voiceid++; } + #elsif($idstr =~ /^P_LANG/) { + # $idnum = $plangid++; + #} else { $idnum = $idcount++; } @@ -441,17 +479,19 @@ $source{$idstr}=$src; $dest{$idstr}=$dest; $voice{$idstr}=$voice; + $user{$idstr}=$user; if($verbose) { print "id: $phrase{id} ($idnum)\n"; print "source: $src\n"; print "dest: $dest\n"; print "voice: $voice\n"; + print "user: $user\n"; } - undef $src; undef $dest; undef $voice; + undef $user; undef %phrase; } @@ -521,6 +561,10 @@ * translated. Use it like str(MACRO) and expect a string to be * returned! */ +MOO + ; + if($kind == 0) { + print HFILE <$binary") or die "Error: Can't create $binary"; binmode OUTF; printf OUTF ("\x1a%c%c", $langversion, $target_id); # magic lang file header + + if($kind == 1) { + # output the number of strings for each user + @hashkeys = keys(%plugin2num); + #printf OUTF ("%c", $#hashkeys); + my $start = 0; + my $foffset = 18; + for $i (1 .. $#hashkeys) { + my $end = $start + $num_strings[$i+1] - 2; + my $size; + for $n ($start .. $end) { + $size += length($dest{$idnum[$n]}) + 2; + } + $start = $end + 1; + printf OUTF ("%c%c%c%c%c", $num_strings[$i+1], ($size >> 8), ($size & 0xff), + ($foffset >> 8), ($foffset & 0xff)); + $foffset += $size; + } + } # loop over the target phrases for $i (1 .. $idcount) { my $name=$idnum[$i - 1]; # get the ID my $dest = $dest{$name}; # get the destination phrase + my $user = $user{$name}; # get the user if($dest) { $dest =~ s/^\"(.*)\"\s*$/$1/g; # cut off quotes @@ -624,7 +728,7 @@ # Now, make sure we get the number from the english sort order: $idnum = $idmap{$name}; - printf OUTF ("%c%c%s\x00", ($idnum>>8), ($idnum&0xff), $dest); + printf OUTF ("%c%c%c%s\x00", ($idnum>>8), ($idnum&0xff), $user, $dest); } } } @@ -637,13 +741,14 @@ # This loops over the strings in the translated language file order my @ids = ((0 .. ($idcount-1))); push @ids, (0x8000 .. ($voiceid-1)); + push @ids, (0x16000 .. ($plangid-1)); #for my $id (@ids) { # print "$id\n"; #} for $i (@ids) { - my $name=$idnum[$i]; # get the ID + my $name = $idnum[$i]; # get the ID my $dest = $voice{$name}; # get the destination voice string if($dest) { @@ -678,7 +783,7 @@ print "#$i ($o)\nid: $name\nvoice: $dest\n"; } - + } Index: tools/configure =================================================================== --- tools/configure (revision 18096) +++ tools/configure (working copy) @@ -492,11 +492,11 @@ NOISEFLOOR="500" TTS_OPTS=$SAPI_OPTS ;; - [Ww]) + [Ww]) TTS_ENGINE="swift" NOISEFLOOR="500" TTS_OPTS=$SWIFT_OPTS - ;; + ;; *) TTS_ENGINE=$DEFAULT_TTS TTS_OPTS=$DEFAULT_TTS_OPTS @@ -2306,10 +2306,11 @@ clean: \$(SILENT)echo Cleaning build directory \$(SILENT)rm -rf rockbox.zip TAGS @APPS@ firmware comsim sim lang.[ch]\ - manual *.pdf *.a credits.raw @OUTPUT@ bitmaps pluginbitmaps \ - @ARCHOSROM@ @FLASHFILE@ UI256.bmp rockbox-full.zip \ + lang_plugin.[ch] manual *.pdf *.a credits.raw @OUTPUT@ bitmaps\ + pluginbitmaps @ARCHOSROM@ @FLASHFILE@ UI256.bmp rockbox-full.zip \ html txt rockbox-manual*.zip sysfont.h rockbox-info.txt \ - voicefontids *.wav *.mp3 *.voice max_language_size.h + voicefontids *.wav *.mp3 *.voice max_language_size.h \ + max_plugin_language_size.h tools: \$(SILENT)\$(MAKE) -C \$(TOOLSDIR) CC=\$(HOSTCC) AR=\$(HOSTAR) @TOOLSET@ @@ -2356,6 +2357,8 @@ langs: features \$(SILENT)mkdir -p \$(BUILDDIR)/apps/lang \$(SILENT)\$(MAKE) -C \$(APPSDIR)/lang OBJDIR=\$(BUILDDIR)/apps/lang + \$(SILENT)mkdir -p \$(BUILDDIR)/apps/plugins/lang + \$(SILENT)\$(MAKE) -C \$(APPSDIR)/plugins/lang OBJDIR=\$(BUILDDIR)/apps/plugins/lang manual: manual-pdf manual-pdf: Index: tools/make.inc =================================================================== --- tools/make.inc (revision 18096) +++ tools/make.inc (working copy) @@ -45,9 +45,11 @@ rm $$del; \ del=""; \ fi \ - done | sed -e "s:[^[:space:]]*lang.h:$(OBJDIR)/lang.o:" \ + done | sed -e "s:[^[:space:]]*lang.h:$(BUILDDIR)/apps/lang.o:" \ + -e "s:[^[:space:]]*lang_plugin.h:$(BUILDDIR)/apps/plugins/lib/lang_plugin.o:" \ -e "s:[^[:space:]]*sysfont.h:$(BUILDDIR)/sysfont.h:" \ -e "s:[^[:space:]]*max_language_size.h:$(BUILDDIR)/max_language_size.h:" \ + -e "s:[^[:space:]]*max_plugin_language_size.h:$(BUILDDIR)/max_plugin_language_size.h:" \ > $(DEPFILE); \ echo "oo" > /dev/null ) Index: tools/buildzip.pl =================================================================== --- tools/buildzip.pl (revision 18096) +++ tools/buildzip.pl (working copy) @@ -199,6 +199,7 @@ } mkdir ".rockbox/langs", 0777; + mkdir ".rockbox/plangs", 0777; mkdir ".rockbox/rocks", 0777; mkdir ".rockbox/rocks/games", 0777; mkdir ".rockbox/rocks/apps", 0777; @@ -391,7 +392,8 @@ system("cp rockbox-info.txt .rockbox/"); # copy the already built lng files - `cp apps/lang/*lng .rockbox/langs/` + system("cp apps/lang/*lng .rockbox/langs/"); + system("cp apps/plugins/lang/*lng .rockbox/plangs/"); } Index: apps/language.c =================================================================== --- apps/language.c (revision 18096) +++ apps/language.c (working copy) @@ -20,74 +20,99 @@ ****************************************************************************/ #include -#if defined(SIMULATOR) && defined(__MINGW32__) -extern int printf(const char *format, ...); -#endif #include "language.h" #include "lang.h" #include "debug.h" #include "string.h" +#include "stdlib.h" static unsigned char language_buffer[MAX_LANGUAGE_SIZE]; +void lang_init_helper(unsigned char *builtin, unsigned char **dest, int count) +{ + unsigned int i = 0; + for (i=0; count; i++) { + //if(i >= offset) { + *dest++ = builtin; + count--; + //} + builtin += strlen((char *)builtin) + 1; /* advance pointer to next string */ + } +} + void lang_init(void) { - int i; - unsigned char *ptr = (unsigned char *) language_builtin; - - for (i = 0; i < LANG_LAST_INDEX_IN_ARRAY; i++) { - language_strings[i] = ptr; - ptr += strlen((char *)ptr) + 1; /* advance pointer to next string */ + lang_init_helper((unsigned char*)language_builtin, language_strings, + LANG_LAST_INDEX_IN_ARRAY); +} + +int lang_validate(int fd) +{ + unsigned char read_buffer[3]; + read(fd, read_buffer, 3); + if (fd < 0) { + DEBUGF("Error opening lang\n"); + return 1; } + if ((read_buffer[0] != LANGUAGE_COOKIE) || + (read_buffer[1] != LANGUAGE_VERSION) || + (read_buffer[2] != TARGET_ID)) { + DEBUGF("Illegal language file\n"); + return 2; + } + return 0; } +void lang_load_helper(int fd, const unsigned char *builtin, unsigned char **dest, + unsigned char *buffer, unsigned int max, + unsigned int lang_size, unsigned int foffset) +{ + unsigned int id; + + /* initialize with builtin */ + lang_init_helper((unsigned char*)builtin, dest, max); + lseek(fd, foffset, SEEK_SET); + read(fd, buffer, lang_size); + //DEBUGF("%d %d\n", fsize, lang_size); + while(lang_size > 3) { + id = (buffer[0]<<8) | buffer[1]; /* get two-byte id */ + buffer += 3; /* pass the id */ + if(id < max) { +#if 0 + DEBUGF("%2x New: %30s ", id, buffer); + DEBUGF("Replaces: %s\n", dest[id]); +#endif + /* point to the string if it should loaded */ + dest[id] = buffer; + } + while(*buffer) { /* pass the string */ + lang_size--; + buffer++; + } + lang_size -= 4; /* the id, user, and the terminating zero */ + buffer++; /* pass the terminating zero-byte */ + } +} + int lang_load(const char *filename) { int fsize; int fd = open(filename, O_RDONLY); - int retcode=0; - unsigned char lang_header[3]; - if(fd < 0) - return 1; + int retcode = 0; + fsize = filesize(fd) - 2; - if(fsize <= MAX_LANGUAGE_SIZE) { - read(fd, lang_header, 3); - if((lang_header[0] == LANGUAGE_COOKIE) && - (lang_header[1] == LANGUAGE_VERSION) && - (lang_header[2] == TARGET_ID)) { - read(fd, language_buffer, MAX_LANGUAGE_SIZE); - unsigned char *ptr = language_buffer; - int id; - lang_init(); /* initialize with builtin */ - - while(fsize>3) { - id = (ptr[0]<<8) | ptr[1]; /* get two-byte id */ - ptr+=2; /* pass the id */ - if(id < LANG_LAST_INDEX_IN_ARRAY) { -#if 0 - printf("%2x New: %30s ", id, ptr); - printf("Replaces: %s\n", language_strings[id]); -#endif - language_strings[id] = ptr; /* point to this string */ - } - while(*ptr) { /* pass the string */ - fsize--; - ptr++; - } - fsize-=3; /* the id and the terminating zero */ - ptr++; /* pass the terminating zero-byte */ - } + retcode = lang_validate(fd); + if(!retcode) { + if(fsize <= MAX_LANGUAGE_SIZE) { + lang_load_helper(fd, language_builtin, language_strings, language_buffer, + LANG_LAST_INDEX_IN_ARRAY, fsize, 3); } else { - DEBUGF("Illegal language file\n"); - retcode = 2; + DEBUGF("Language %s too large: %d\n", filename, fsize); + retcode = 3; } } - else { - DEBUGF("Language %s too large: %d\n", filename, fsize); - retcode = 3; - } close(fd); return retcode; } Index: apps/language.h =================================================================== --- apps/language.h (revision 18096) +++ apps/language.h (working copy) @@ -25,15 +25,22 @@ MAX_LANGUAGE_SIZE to be the size of the largest currently available language! */ #include "max_language_size.h" +#include "max_plugin_language_size.h" /* both these must match the two initial bytes in the binary lang file */ #define LANGUAGE_COOKIE 0x1a -#define LANGUAGE_VERSION 0x04 +#define LANGUAGE_VERSION 0x05 /* Initialize language array with the builtin strings */ void lang_init(void); +void lang_init_helper(unsigned char *builtin, unsigned char **dest, int count); +int lang_validate(int fd); + /* load a given language file */ int lang_load(const char *filename); +void lang_load_helper(int fd, const unsigned char *builtin, unsigned char **dest, + unsigned char *buffer, unsigned int max, + unsigned int lang_size, unsigned int foffset); #endif Index: apps/Makefile =================================================================== --- apps/Makefile (revision 18096) +++ apps/Makefile (working copy) @@ -225,7 +225,7 @@ $(OBJDIR)/lang.o: lang/$(LANGUAGE).lang $(OBJDIR)/features $(SILENT)for f in `cat $(OBJDIR)/features`; do feat="$$feat:$$f" ; done; \ - perl -s $(TOOLSDIR)/genlang -p=$(BUILDDIR)/lang -t=$(MODELNAME)$$feat $< + perl -s $(TOOLSDIR)/genlang -k=core -p=$(BUILDDIR)/lang -t=$(MODELNAME)$$feat $< $(call PRINTS,CC lang.c)$(CC) $(CFLAGS) -c $(BUILDDIR)/lang.c -o $@ clean: Index: apps/plugins/chessbox/chessbox.c =================================================================== --- apps/plugins/chessbox/chessbox.c (revision 18096) +++ apps/plugins/chessbox/chessbox.c (working copy) @@ -22,6 +22,7 @@ ****************************************************************************/ #include "plugin.h" +#include "pluginlib_lang.h" #ifdef HAVE_LCD_BITMAP @@ -580,7 +581,7 @@ } } while (!exit_game && !exit_viewer); } else { - rb->splash ( 200 , "Error parsing game !"); + rb->splash ( 200 , p_str(P_LANG_CHESSBOX_PARSE_ERROR)); } } while (!exit_viewer); } @@ -593,7 +594,11 @@ bool menu_quit = false; MENUITEM_STRINGLIST(menu,"Chessbox Menu",NULL,"New Game","Resume Game", - "Save Game", "Restore Game", "Quit"); + "Save Game", "Restore Game", "Quit"); + /*MENUITEM_STRINGLIST(menu,"Chessbox Menu",NULL, + ID2P(LANG_CHESSBOX_MENU_RESTART_GAME), + ID2P(LANG_CHESSBOX_MENU_SELECT_OTHER_GAME), + ID2P(LANG_CHESSBOX_MENU_QUIT));*/ while(!menu_quit) { @@ -781,7 +786,7 @@ while (!exit) { if ( mate ) { - rb->splash ( 500 , "Checkmate!" ); + rb->splash ( 500 , p_str(P_LANG_CHESSBOX_CHECKMATE) ); rb->button_get(true); pgn_store_game(rb, game); GNUChess_Initialize(); @@ -792,7 +797,7 @@ switch (command.type) { case COMMAND_MOVE: if ( ! VerifyMove (opponent, command.mv_s , 0 , &command.mv, move_buffer ) ) { - rb->splash ( 50 , "Illegal move!" ); + rb->splash ( 50 , p_str(P_LANG_CHESSBOX_ILLEGAL_MOVE) ); cb_drawboard(); } else { cb_drawboard(); @@ -912,6 +917,7 @@ #if LCD_DEPTH > 1 rb->lcd_set_backdrop(NULL); #endif + plugin_use_lang(rb, USER_CHESSBOX); /* end of plugin init */ Index: apps/plugins/chessbox/Makefile =================================================================== --- apps/plugins/chessbox/Makefile (revision 18096) +++ apps/plugins/chessbox/Makefile (working copy) @@ -9,7 +9,7 @@ INCLUDES = -I$(APPSDIR) -I.. -I. $(TARGET_INC) -I$(FIRMDIR)/include -I$(FIRMDIR)/export \ -I$(BUILDDIR)/pluginbitmaps -I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(OUTDIR) \ - -I$(BUILDDIR) + -I$(BUILDDIR) -I$(APPSDIR)/plugins/lib CFLAGS = $(INCLUDES) $(GCCOPTS) -O2 $(TARGET) $(EXTRA_DEFINES) \ -DTARGET_ID=$(TARGET_ID) -DMEM=${MEMORYSIZE} -DPLUGIN @@ -40,7 +40,7 @@ all: $(OUTPUT) ifndef SIMVER -$(OBJDIR)/chessbox.elf: $(OBJS) $(LINKFILE) $(BITMAPLIBS) +$(OBJDIR)/chessbox.elf: $(BUILDDIR)/libplugin.a $(OBJS) $(LINKFILE) $(BITMAPLIBS) $(call PRINTS,LD $(@F))$(CC) $(CFLAGS) -o $@ $(OBJS) -L$(BUILDDIR) -lplugin -lgcc \ $(LINKBITMAPS) -T$(LINKFILE) -Wl,--gc-sections -Wl,-Map,$(OBJDIR)/chessbox.map @@ -67,7 +67,7 @@ ################################################### # This is the SDL simulator version -$(OUTPUT): $(OBJS) +$(OUTPUT): $(BUILDDIR)/libplugin.a $(OBJS) $(call PRINTS,LD $(@F))$(CC) $(CFLAGS) $(SHARED_FLAG) $(OBJS) -L$(BUILDDIR) -lplugin $(LINKBITMAPS) -o $@ ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN) # 'x' must be kept or you'll have "Win32 error 5" Index: apps/plugins/lang/espanol.lang =================================================================== --- apps/plugins/lang/espanol.lang (revision 0) +++ apps/plugins/lang/espanol.lang (revision 0) @@ -0,0 +1,580 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + + + + id: P_LANG_BET + desc: bet text + user: blackjack + + *: "Bet" + + + *: "Apuesta" + + + *: "Apuesta" + + + + id: P_LANG_DEALER + desc: dealer text + user: blackjack + + *: "Dealer" + + + *: "Banca" + + + *: "Banca" + + + + id: P_LANG_PLAYER + desc: player text + user: blackjack + + *: "Player" + + + *: "Jugador" + + + *: "Jugador" + + + + id: P_LANG_TOTAL + desc: total text + user: blackjack + + *: "Total" + + + *: "Total" + + + *: "Total" + + + + id: P_LANG_MONEY + desc: money text + user: blackjack + + *: "Money" + + + *: "Dinero" + + + *: "Dinero" + + + + id: P_LANG_BUST + desc: player busted + user: blackjack + + *: "Bust" + + + *: "Busto" + + + *: "Busto" + + + + id: P_LANG_LOST + desc: blackjack player lost + user: blackjack + + *: "Sorry, you lost" + + + *: "Lo siento, perdiste" + + + *: "Lo siento, perdiste" + + + + id: P_LANG_PUSH + desc: blackjack player tied + user: blackjack + + *: "Push" + + + *: "Empata" + + + *: "Empata" + + + + id: P_LANG_WON + desc: blackjack player won + user: blackjack + + *: "You won" + + + *: "Ganaste" + + + *: "Ganaste" + + + + id: P_LANG_BLACKJACK + desc: blackjack text + user: blackjack + + *: "Blackjack" + + + *: "Blackjack" + + + *: "Blackjack" + + + + id: P_LANG_YOU_HAVE + desc: blackjack text that lets user know his total + user: blackjack + + *: none + player,recorder,fmrecorder,recorderv2,ondiofm,ondiosp: "You have" + + + *: none + player,recorder,fmrecorder,recorderv2,ondiofm,ondiosp: "Tienes" + + + *: none + player,recorder,fmrecorder,recorderv2,ondiofm,ondiosp: "Tienes" + + + + id: P_LANG_HIGH_SCORE_TITLE + desc: text shown at the top of the high scores screen + user: blackjack + + *: "High Scores" + + + *: "Puntajes Altos" + + + *: "Puntajes Altos" + + + + id: P_LANG_NEW_HIGH_SCORE + desc: player ranked in the top high scores + user: blackjack + + *: "New high score" + + + *: "Nueva puntaje alto" + + + *: "Nueva puntaje alto" + + + + id: P_LANG_SAVING_HIGH_SCORES + desc: we save the high scores before exiting some plugins + user: blackjack + + *: "Saving high scores..." + + + *: "Salvar los puntajes altos..." + + + *: "Salvar los puntajes altos..." + + + + id: P_LANG_SAVING_GAME + desc: the user can save the game + user: blackjack + + *: "Saving game..." + + + *: "Salvar el juego" + + + *: "Salvar el juego" + + + + id: P_LANG_BET_INC_SMALL + desc: help text for a small bet increase + user: blackjack + + *: "RIGHT: +1" + ipod*: " >>|: +1" + h10: "RIGHT: +1" + + + *: "RIGHT: +1" + ipod*: " >>|: +1" + h10: "RIGHT: +1" + + + *: "RIGHT: +1" + ipod*: " >>|: +1" + h10: "RIGHT: +1" + + + + id: P_LANG_BET_DEC_SMALL + desc: help text for a small bet decrease + user: blackjack + + *: "LEFT: -1" + ipod*: " |<<: -1" + h10: "LEFT: -1" + + + *: "LEFT: -1" + ipod*: " |<<: -1" + h10: "LEFT: -1" + + + *: "LEFT: -1" + ipod*: " |<<: -1" + h10: "LEFT: -1" + + + + id: P_LANG_BET_INC_BIG + desc: help text for a large bet increase + user: blackjack + + *: "UP: +10" + ipod*,h10: "SCROLL+: +10" + + + *: "UP: +10" + ipod*,h10: "SCROLL+: +10" + + + *: "UP: +10" + ipod*,h10: "SCROLL+: +10" + + + + id: P_LANG_BET_DEC_BIG + desc: help text for a large bet decrease + user: blackjack + + *: "DOWN: -10" + ipod*,h10: "SCROLL-: -10" + + + *: "DOWN: -10" + ipod*,h10: "SCROLL-: -10" + + + *: "DOWN: -10" + ipod*,h10: "SCROLL-: -10" + + + + id: P_LANG_DEALER_BLACKJACK + desc: the dealer has a blackjack + user: blackjack + + *: "Dealer has blackjack" + + + *: "Banca tiene blackjack" + + + *: "Banca tiene blackjack" + + + + id: P_LANG_DEALER_NO_BLACKJACK + desc: the dealer doesn't have a blackjack + user: blackjack + + *: "Dealer does not have blackjack" + + + *: "Banca no tiene blackjack" + + + *: "Banca no tiene blackjack" + + + + id: P_LANG_GET_BET + desc: get the user's bet + user: blackjack + + *: "Please enter a bet" + + + *: "Por favor, entrar en una apuesta" + + + *: "Por favor, entrar en una apuesta" + + + + id: P_LANG_SPLIT + desc: used throughout splitting + user: blackjack + + *: "Split" + + + *: "Divisi—n" + + + *: "Divisi—n" + + + + id: P_LANG_ASK_SPLIT + desc: split the cards? + user: blackjack + + *: "Split?" + + + *: "ĀDividir?" + + + *: "ĀDividir?" + + + + id: P_LANG_BUY_INSURANCE + desc: asking if the user wants to buy insurance + user: blackjack + + *: "Buy Insurance?" + + + *: "ĀComprar seguro?" + + + *: "ĀComprar seguro?" + + + + id: P_LANG_HOW_MUCH + desc: how much money does the user want to spend on insurance + user: blackjack + + *: "How much?" + + + *: "ĀCu‡nto?" + + + *: "ĀCu‡nto?" + + + + id: P_LANG_NEED_MONEY_DOUBLE_DOWN + desc: player doesn't have enough money to double down + user: blackjack + + *: "Not enough money to double down." + + + *: "No suficiente dinero para doblar." + + + *: "No suficiente dinero para doblar." + + + + id: P_LANG_NEED_MONEY_CONTINUE + desc: player doesn't have enough money to keep playing + user: blackjack + + *: "Not enough money to continue." + + + *: "No suficiente dinero para seguir." + + + *: "No suficiente dinero para seguir." + + + + id: P_LANG_PLAY_AGAIN + desc: does the user want to keep playing? + user: blackjack + + *: "Play again?" + + + *: "ĀJugar otro mano?" + + + *: "ĀJugar otro mano?" + + + + id: P_LANG_GAMEOVER + desc: chopper game is ended + user: chopper + + *: "Game Over" + + + *: "Fin de Juego" + + + *: "Fin de Juego" + + + + id: P_LANG_CHOPPER_CONTINUE + desc: button pressed to continue + user: chopper + + *: none + c200,e200,gigabeatf,gigabeats,h100,h120,h300,ipod*,m5,mrobe100,x5: "Press SELECT to continue" + h10: "Press RIGHT to continue" + fmrecorder,recorder,recorderv2,m3: "Press PLAY to continue" + ondiosp,ondiofm: "Press UP to continue" + + + *: none + c200,e200,gigabeatf,gigabeats,h100,h120,h300,ipod*,m5,mrobe100,x5: "Pulsa SELECT para continuar" + h10: "Pulsa RIGHT para continuar" + fmrecorder,recorder,recorderv2,m3: "Pulsa PLAY para continuar" + ondiosp,ondiofm: "Pulsa UP para continuar" + + + *: none + c200,e200,gigabeatf,gigabeats,h100,h120,h300,ipod*,m5,mrobe100,x5: "Pulsa SELECT para continuar" + h10: "Pulsa RIGHT para continuar" + fmrecorder,recorder,recorderv2,m3: "Pulsa PLAY para continuar" + ondiosp,ondiofm: "Pulsa UP para continuar" + + + + id: P_LANG_HIGHSCORE + desc: chopper new high score + user: chopper + + *: "New High Score" + + + *: "Nueva Puntaje Alto" + + + *: "Nueva Puntaje Alto" + + + + id: P_LANG_CHOPPER_DISTANCE + desc: distance label + user: chopper + + *: "Distance" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Dist" + + + *: "Distancia" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Dist" + + + *: "Distancia" + + + + id: P_LANG_CHOPPER_BESTSCORE + desc: distance label + user: chopper + + *: "Best" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Hi" + + + *: "Mejor" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Hi" + + + *: "Mejor" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Hi" + + + + id: P_LANG_CHOPPER_MENUTITLE + desc: chopper menu title + user: chopper + + *: "Chopper Menu" + + + *: "Chopper Menœ" + + + *: "Chopper Menœ" + + + + id: P_LANG_CHOPPER_START + desc: chopper menu new game + user: chopper + + *: "Start New Game" + + + *: "Iniciar Nuevo Juego" + + + *: "Iniciar Nuevo Juego" + + + + id: P_LANG_CHOPPER_NO_GAME + desc: no saved game found + user: chopper + + *: "No game to resume" + + + *: "No juego para retomar" + + + *: "No juego para retomar" + + + + id: P_LANG_CHOPPER_LEVEL + desc: level label + user: chopper + + *: "Level" + + + *: "Nivel" + + + *: "Nivel" + + Index: apps/plugins/lang/SOURCES =================================================================== --- apps/plugins/lang/SOURCES (revision 0) +++ apps/plugins/lang/SOURCES (revision 0) @@ -0,0 +1,2 @@ +english.lang +espanol.lang \ No newline at end of file Index: apps/plugins/lang/english.lang =================================================================== --- apps/plugins/lang/english.lang (revision 0) +++ apps/plugins/lang/english.lang (revision 0) @@ -0,0 +1,720 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + + + + id: P_LANG_BET + desc: bet text + user: blackjack + + *: "Bet" + + + *: "Bet" + + + *: "Bet" + + + + id: P_LANG_DEALER + desc: dealer text + user: blackjack + + *: "Dealer" + + + *: "Dealer" + + + *: "Dealer" + + + + id: P_LANG_PLAYER + desc: player text + user: blackjack + + *: "Player" + + + *: "Player" + + + *: "Player" + + + + id: P_LANG_TOTAL + desc: total text + user: blackjack + + *: "Total" + + + *: "Total" + + + *: "Total" + + + + id: P_LANG_MONEY + desc: money text + user: blackjack + + *: "Money" + + + *: "Money" + + + *: "Money" + + + + id: P_LANG_BUST + desc: player busted + user: blackjack + + *: "Bust!" + + + *: "Bust!" + + + *: "Bust" + + + + id: P_LANG_LOST + desc: blackjack player lost + user: blackjack + + *: "Sorry, you lost." + + + *: "Sorry, you lost." + + + *: "Sorry, you lost" + + + + id: P_LANG_PUSH + desc: blackjack player tied + user: blackjack + + *: "Push" + + + *: "Push" + + + *: "Push" + + + + id: P_LANG_WON + desc: blackjack player won + user: blackjack + + *: "You won!" + + + *: "You won!" + + + *: "You won" + + + + id: P_LANG_BLACKJACK + desc: blackjack text + user: blackjack + + *: "Blackjack" + + + *: "Blackjack" + + + *: "Blackjack" + + + + id: P_LANG_YOU_HAVE + desc: blackjack text that lets user know his total + user: blackjack + + *: none + player,recorder,fmrecorder,recorderv2,ondiofm,ondiosp: "You have" + + + *: none + player,recorder,fmrecorder,recorderv2,ondiofm,ondiosp: "You have" + + + *: none + player,recorder,fmrecorder,recorderv2,ondiofm,ondiosp: "You have" + + + + id: P_LANG_HIGH_SCORE_TITLE + desc: text shown at the top of the high scores screen + user: blackjack + + *: "High Scores" + + + *: "High Scores" + + + *: "High Scores" + + + + id: P_LANG_NEW_HIGH_SCORE + desc: player ranked in the top high scores + user: blackjack + + *: "New high score" + + + *: "New high score" + + + *: "New high score" + + + + id: P_LANG_SAVING_HIGH_SCORES + desc: we save the high scores before exiting some plugins + user: blackjack + + *: "Saving high scores..." + + + *: "Saving high scores..." + + + *: "Saving high scores..." + + + + id: P_LANG_SAVING_GAME + desc: the user can save the game + user: blackjack + + *: "Saving game..." + + + *: "Saving game..." + + + *: "Saving game..." + + + + id: P_LANG_BET_INC_SMALL + desc: help text for a small bet increase + user: blackjack + + *: "RIGHT: +1" + ipod*: " >>|: +1" + h10: "RIGHT: +1" + + + *: "RIGHT: +1" + ipod*: " >>|: +1" + h10: "RIGHT: +1" + + + *: "RIGHT: +1" + ipod*: " >>|: +1" + h10: "RIGHT: +1" + + + + id: P_LANG_BET_DEC_SMALL + desc: help text for a small bet decrease + user: blackjack + + *: "LEFT: -1" + ipod*: " |<<: -1" + h10: "LEFT: -1" + + + *: "LEFT: -1" + ipod*: " |<<: -1" + h10: "LEFT: -1" + + + *: "LEFT: -1" + ipod*: " |<<: -1" + h10: "LEFT: -1" + + + + id: P_LANG_BET_INC_BIG + desc: help text for a large bet increase + user: blackjack + + *: "UP: +10" + ipod*,h10: "SCROLL+: +10" + + + *: "UP: +10" + ipod*,h10: "SCROLL+: +10" + + + *: "UP: +10" + ipod*,h10: "SCROLL+: +10" + + + + id: P_LANG_BET_DEC_BIG + desc: help text for a large bet decrease + user: blackjack + + *: "DOWN: -10" + ipod*,h10: "SCROLL-: -10" + + + *: "DOWN: -10" + ipod*,h10: "SCROLL-: -10" + + + *: "DOWN: -10" + ipod*,h10: "SCROLL-: -10" + + + + id: P_LANG_DEALER_BLACKJACK + desc: the dealer has a blackjack + user: blackjack + + *: "Dealer has blackjack" + + + *: "Dealer has blackjack" + + + *: "Dealer has blackjack" + + + + id: P_LANG_DEALER_NO_BLACKJACK + desc: the dealer doesn't have a blackjack + user: blackjack + + *: "Dealer does not have blackjack" + + + *: "Dealer does not have blackjack" + + + *: "Dealer does not have blackjack" + + + + id: P_LANG_GET_BET + desc: get the user's bet + user: blackjack + + *: "Please enter a bet" + + + *: "Please enter a bet" + + + *: "Please enter a bet" + + + + id: P_LANG_SPLIT + desc: used throughout splitting + user: blackjack + + *: "Split" + + + *: "Split" + + + *: "Split" + + + + id: P_LANG_ASK_SPLIT + desc: split the cards? + user: blackjack + + *: "Split?" + + + *: "Split?" + + + *: "Split?" + + + + id: P_LANG_BUY_INSURANCE + desc: asking if the user wants to buy insurance + user: blackjack + + *: "Buy Insurance?" + + + *: "Buy Insurance?" + + + *: "Buy Insurance?" + + + + id: P_LANG_HOW_MUCH + desc: how much money does the user want to spend on insurance + user: blackjack + + *: "How much?" + + + *: "How much?" + + + *: "How much?" + + + + id: P_LANG_NEED_MONEY_DOUBLE_DOWN + desc: player doesn't have enough money to double down + user: blackjack + + *: "Not enough money to double down." + + + *: "Not enough money to double down." + + + *: "Not enough money to double down." + + + + id: P_LANG_NEED_MONEY_CONTINUE + desc: player doesn't have enough money to keep playing + user: blackjack + + *: "Not enough money to continue." + + + *: "Not enough money to continue." + + + *: "Not enough money to continue." + + + + id: P_LANG_PLAY_AGAIN + desc: does the user want to keep playing? + user: blackjack + + *: "Play again?" + + + *: "Play again?" + + + *: "Play again?" + + + + id: P_LANG_GAMEOVER + desc: chopper game is ended + user: chopper + + *: "Game Over" + + + *: "Game Over" + + + *: "Game Over" + + + + id: P_LANG_CHOPPER_CONTINUE + desc: button pressed to continue + user: chopper + + *: none + c200,e200,gigabeatf,gigabeats,h100,h120,h300,ipod*,m5,mrobe100,x5: "Press SELECT to continue" + h10: "Press RIGHT to continue" + fmrecorder,recorder,recorderv2,m3: "Press PLAY to continue" + ondiosp,ondiofm: "Press UP to continue" + + + *: none + c200,e200,gigabeatf,gigabeats,h100,h120,h300,ipod*,m5,mrobe100,x5: "Press SELECT to continue" + h10: "Press RIGHT to continue" + fmrecorder,recorder,recorderv2,m3: "Press PLAY to continue" + ondiosp,ondiofm: "Press UP to continue" + + + *: none + c200,e200,gigabeatf,gigabeats,h100,h120,h300,ipod*,m5,mrobe100,x5: "Press SELECT to continue" + h10: "Press RIGHT to continue" + fmrecorder,recorder,recorderv2,m3: "Press PLAY to continue" + ondiosp,ondiofm: "Press UP to continue" + + + + id: P_LANG_HIGHSCORE + desc: chopper new high score + user: chopper + + *: "New High Score" + + + *: "New High Score" + + + *: "New High Score" + + + + id: P_LANG_CHOPPER_DISTANCE + desc: distance label + user: chopper + + *: "Distance" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Dist" + + + *: "Distance" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Dist" + + + *: "Distance" + + + + id: P_LANG_CHOPPER_BESTSCORE + desc: distance label + user: chopper + + *: "Best" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Hi" + + + *: "Best" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Hi" + + + *: "Best" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Hi" + + + + id: P_LANG_CHOPPER_MENUTITLE + desc: chopper menu title + user: chopper + + *: "Chopper Menu" + + + *: "Chopper Menu" + + + *: "Chopper Menu" + + + + id: P_LANG_CHOPPER_START + desc: chopper menu new game + user: chopper + + *: "Start New Game" + + + *: "Start New Game" + + + *: "Start New Game" + + + + id: P_LANG_CHOPPER_NO_GAME + desc: no saved game found + user: chopper + + *: "No game to resume" + + + *: "No game to resume" + + + *: "No game to resume" + + + + id: P_LANG_CHOPPER_LEVEL + desc: level label + user: chopper + + *: "Level" + + + *: "Level" + + + *: "Level" + + + + id: P_LANG_CHESSBOX_CHECKMATE + desc: in the chessbox menu + user: chessbox + + *: "Checkmate!" + + + *: "Checkmate!" + + + *: "Checkmate!" + + + + id: P_LANG_CHESSBOX_ILLEGAL_MOVE + desc: in chessbox + user: chessbox + + *: "Illegal move!" + + + *: "Illegal move!" + + + *: "Illegal move!" + + + + id: P_LANG_CHESSBOX_MENU_NEW_GAME + desc: in the chessbox menu + user: chessbox + + *: "New Game" + + + *: "New Game" + + + *: "New Game" + + + + id: P_LANG_CHESSBOX_MENU_RESUME_GAME + desc: in the chessbox menu + user: chessbox + + *: "Resume Game" + + + *: "Resume Game" + + + *: "Resume Game" + + + + id: P_LANG_CHESSBOX_MENU_SAVE_GAME + desc: in the chessbox menu + user: chessbox + + *: "Save Game" + + + *: "Save Game" + + + *: "Save Game" + + + + id: P_LANG_CHESSBOX_MENU_RESTORE_GAME + desc: in the chessbox menu + user: chessbox + + *: "Restore Game" + + + *: "Restore Game" + + + *: "Restore Game" + + + + id: P_LANG_CHESSBOX_MENU_RESTART_GAME + desc: in the chessbox menu + user: chessbox + + *: "Restart Game" + + + *: "Restart Game" + + + *: "Restart Game" + + + + id: P_LANG_CHESSBOX_MENU_SELECT_OTHER_GAME + desc: in the chessbox menu + user: chessbox + + *: "Select Other Game" + + + *: "Select Other Game" + + + *: "Select Other Game" + + + + id: P_LANG_CHESSBOX_MENU_QUIT + desc: in the chessbox menu + user: chessbox + + *: "Quit" + + + *: "Quit" + + + *: "Quit" + + + + id: P_LANG_CHESSBOX_PARSE_ERROR + desc: in the chessbox game viewer + user: chessbox + + *: "Error parsing game !" + + + *: "Error parsing game !" + + + *: "Error parsing game !" + + Index: apps/plugins/lang/Makefile =================================================================== --- apps/plugins/lang/Makefile (revision 0) +++ apps/plugins/lang/Makefile (revision 0) @@ -0,0 +1,40 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +INCLUDES= $(TARGET_INC) -I$(FIRMDIR)/include -I$(FIRMDIR)/export \ +-I. -I$(BUILDDIR) -I$(OBJDIR) + +# the header we generate +HEADER = $(BUILDDIR)/max_plugin_language_size.h + +# This sets up 'SRC' based on the files mentioned in SOURCES +include $(TOOLSDIR)/makesrc.inc +SOURCES=$(SRC) + +# OUTP is the list of files to depend upon +OUTP = $(patsubst %.lang,$(OBJDIR)/%.lng, $(SOURCES)) + +# the generated file with features specified genlang-style +FEATS=$(BUILDDIR)/apps/genlang-features + +ifndef V +SILENT=@ +endif +PRINTS=$(SILENT)$(call info,$(1)) + +all: $(HEADER) + +# generic rule for creating .lng from .lang +$(OBJDIR)/%.lng : %.lang + $(call PRINTS,PLUGIN GENLANG $<) + $(SILENT)$(TOOLSDIR)/genlang -e=$(APPSDIR)/plugins/lang/english.lang -t=$(MODELNAME) -i=$(TARGET_ID) -b=$@ -k=plugin $< + +$(HEADER): $(OUTP) + $(call PRINTS,Make $(HEADER)) + $(SILENT)echo "#define MAX_PLUGIN_LANGUAGE_SIZE `ls -ln $(OBJDIR)/* | awk '{print $$5}' | sort -n | tail -1`" > $(HEADER) Index: apps/plugins/lib/pluginlib_lang.c =================================================================== --- apps/plugins/lib/pluginlib_lang.c (revision 0) +++ apps/plugins/lib/pluginlib_lang.c (revision 0) @@ -0,0 +1,80 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 by Tom Ross + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "plugin.h" +#include "language.h" +#include "pluginlib_lang.h" + +#define NUM_PLUGIN_LANG 3 + +static unsigned char *plugin_language_buffer; +static unsigned char **plugin_language_strings; +static lang_t langs[NUM_PLUGIN_LANG]; + +void plugin_use_lang(const struct plugin_api* rb, enum user_type load) +{ + char buf[64]; + size_t buffer_size; + size_t langsize = MAX_PLUGIN_LANGUAGE_SIZE; + unsigned char read_buffer[5]; + int i, fd; + + if(langsize & 3) + langsize += (4 - (langsize & 3)); + + plugin_language_buffer = (unsigned char*)rb->plugin_get_buffer(&buffer_size); + plugin_language_strings = (unsigned char **)(plugin_language_buffer + + langsize); + rb->lang_init_helper((unsigned char*)plugin_language_builtin, plugin_language_strings, + P_LANG_LAST_INDEX_IN_ARRAY); + + if ( rb->global_settings->lang_file[0]) { + rb->snprintf(buf, sizeof(buf), PLUGIN_LANG_DIR "/%s.lng", + rb->global_settings->lang_file); + fd = rb->open(buf, O_RDONLY); + if (!rb->lang_validate(fd)) { + /* read in the number of strings, filesize, and file offset*/ + for(i=0; i < NUM_PLUGIN_LANG; i++) { + rb->read(fd, read_buffer, 5); + langs[i].num_str = read_buffer[0]; + langs[i].fsize = (read_buffer[1]<<8) | read_buffer[2]; + langs[i].foffset = (read_buffer[3]<<8) | read_buffer[4]; + } + if(langs[load-2].fsize <= MAX_PLUGIN_LANGUAGE_SIZE) { + rb->lang_load_helper(fd, plugin_language_builtin, plugin_language_strings, + plugin_language_buffer, langs[load-2].num_str, + langs[load-2].fsize, langs[load-2].foffset); + } + else { + DEBUGF("Language %s too large: %d\n", buf, langs[load-2].fsize); + } + } + rb->close(fd); + } +} + +int plugin_talk_id(const struct plugin_api* rb, int32_t id, bool enqueue) +{ + return rb->talk_id(id + LANG_LAST_INDEX_IN_ARRAY, enqueue); +} + +char* get_plugin_str(int x) +{ + return plugin_language_strings[x]; +} Index: apps/plugins/lib/pluginlib_lang.h =================================================================== --- apps/plugins/lib/pluginlib_lang.h (revision 0) +++ apps/plugins/lib/pluginlib_lang.h (revision 0) @@ -0,0 +1,39 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 by Tom Ross + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef _LIB_LANG_H_ +#define _LIB_LANG_H_ + +#include "plugin.h" +#include "lang.h" +#include "lang_plugin.h" + +#undef str +#define str(x) rb->language_strings[x] +#define p_str(x) get_plugin_str(x) + +typedef struct lang_t { + int num_str; + int fsize; + int foffset; +} lang_t; + +void plugin_use_lang(const struct plugin_api* rb, enum user_type load); +int plugin_talk_id(const struct plugin_api* rb, int32_t id, bool enqueue); +char* get_plugin_str(int x); +#endif /* _LIB_LANG_H_ */ Index: apps/plugins/lib/Makefile =================================================================== --- apps/plugins/lib/Makefile (revision 18096) +++ apps/plugins/lib/Makefile (working copy) @@ -29,7 +29,7 @@ include $(TOOLSDIR)/makesrc.inc SOURCES = $(SRC) -OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o) +OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o) $(OBJDIR)/lang_plugin.o OBJS = $(patsubst %.S, $(OBJDIR)/%.o, $(OBJS2)) DEPFILE = $(OBJDIR)/dep-pluginlib DIRS = . @@ -42,6 +42,10 @@ $(call PRINTS,AR+RANLIB $(@F))$(AR) ruv $@ $+ >/dev/null 2>&1 $(SILENT)$(RANLIB) $@ +$(OBJDIR)/lang_plugin.o: $(APPSDIR)/plugins/lang/$(LANGUAGE).lang + $(SILENT)perl -s $(TOOLSDIR)/genlang -k=plugin -p=$(BUILDDIR)/lang_plugin -t=$(MODELNAME) $< + $(call PRINTS,CC lang_plugin.c)$(CC) $(CFLAGS) -c $(BUILDDIR)/lang_plugin.c -o $@ + include $(TOOLSDIR)/make.inc clean: Index: apps/plugins/lib/SOURCES =================================================================== --- apps/plugins/lib/SOURCES (revision 18096) +++ apps/plugins/lib/SOURCES (working copy) @@ -39,6 +39,7 @@ #endif pluginlib_actions.c helper.c +pluginlib_lang.c #ifdef HAVE_TOUCHPAD touchscreen.c #endif Index: apps/plugins/chopper.c =================================================================== --- apps/plugins/chopper.c (revision 18096) +++ apps/plugins/chopper.c (working copy) @@ -21,6 +21,7 @@ ****************************************************************************/ #include "plugin.h" +#include "pluginlib_lang.h" #include "xlcd.h" #include "configfile.h" #include "helper.h" @@ -44,7 +45,6 @@ #define QUIT BUTTON_OFF #define ACTION BUTTON_UP #define ACTION2 BUTTON_SELECT -#define ACTIONTEXT "SELECT" #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ (CONFIG_KEYPAD == IPOD_3G_PAD) || \ @@ -52,58 +52,48 @@ #define QUIT BUTTON_MENU #define ACTION BUTTON_SELECT -#define ACTIONTEXT "SELECT" #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD /* grayscale at the moment */ #define QUIT BUTTON_POWER #define ACTION BUTTON_UP #define ACTION2 BUTTON_SELECT -#define ACTIONTEXT "SELECT" #elif CONFIG_KEYPAD == IRIVER_H10_PAD #define QUIT BUTTON_POWER #define ACTION BUTTON_RIGHT -#define ACTIONTEXT "RIGHT" #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \ (CONFIG_KEYPAD == SANSA_C200_PAD) #define QUIT BUTTON_POWER #define ACTION BUTTON_SELECT -#define ACTIONTEXT "SELECT" #elif CONFIG_KEYPAD == GIGABEAT_PAD #define QUIT BUTTON_MENU #define ACTION BUTTON_SELECT -#define ACTIONTEXT "SELECT" #elif CONFIG_KEYPAD == RECORDER_PAD #define QUIT BUTTON_OFF #define ACTION BUTTON_PLAY -#define ACTIONTEXT "PLAY" #elif CONFIG_KEYPAD == ONDIO_PAD #define QUIT BUTTON_OFF #define ACTION BUTTON_UP #define ACTION2 BUTTON_MENU -#define ACTIONTEXT "UP" #elif CONFIG_KEYPAD == GIGABEAT_S_PAD #define QUIT BUTTON_BACK #define ACTION BUTTON_SELECT #define ACTION2 BUTTON_MENU -#define ACTIONTEXT "SELECT" #elif CONFIG_KEYPAD == MROBE100_PAD #define QUIT BUTTON_POWER #define ACTION BUTTON_SELECT -#define ACTIONTEXT "SELECT" #elif CONFIG_KEYPAD == IAUDIO_M3_PAD #define QUIT BUTTON_RC_REC #define ACTION BUTTON_RC_PLAY #define ACTION2 BUTTON_RC_MODE -#define ACTIONTEXT "PLAY" #elif CONFIG_KEYPAD == COWOND2_PAD #define QUIT BUTTON_POWER @@ -122,10 +112,7 @@ #ifndef ACTION2 #define ACTION2 BUTTON_BOTTOMRIGHT #endif -#ifndef ACTIONTEXT -#define ACTIONTEXT "BOTTOMRIGHT" #endif -#endif static const struct plugin_api* rb; @@ -529,17 +516,19 @@ #if LCD_DEPTH >= 2 rb->lcd_set_foreground(LCD_LIGHTGRAY); #endif - rb->splash(HZ, "Game Over"); + //rb->splash(HZ, "Game Over"); + rb->splash(HZ, p_str(P_LANG_GAMEOVER)); if (score > highscore) { char scoretext[30]; highscore = score; - rb->snprintf(scoretext, sizeof(scoretext), "New High Score: %d", - highscore); + rb->snprintf(scoretext, sizeof(scoretext), "%s: %d", + p_str(P_LANG_HIGHSCORE), highscore); rb->splash(HZ*2, scoretext); } - rb->splash(HZ/4, "Press " ACTIONTEXT " to continue"); + //rb->splash(HZ/4, "Press " ACTIONTEXT " to continue"); + rb->splash(HZ/4, p_str(P_LANG_CHOPPER_CONTINUE)); rb->lcd_update(); rb->lcd_set_drawmode(DRMODE_SOLID); @@ -649,21 +638,24 @@ rb->lcd_set_foreground(LCD_WHITE); #endif -#if LCD_WIDTH <= 128 +/*#if LCD_WIDTH <= 128 rb->snprintf(s, sizeof(s), "Dist: %d", score); #else rb->snprintf(s, sizeof(s), "Distance: %d", score); -#endif +#endif*/ + rb->snprintf(s, sizeof(s), "%s: %d", p_str(P_LANG_CHOPPER_DISTANCE), score); rb->lcd_getstringsize(s, &w, NULL); rb->lcd_putsxy(2, 2, s); if (score < highscore) { int w2; -#if LCD_WIDTH <= 128 +/*#if LCD_WIDTH <= 128 rb->snprintf(s, sizeof(s), "Hi: %d", highscore); #else rb->snprintf(s, sizeof(s), "Best: %d", highscore); -#endif +#endif*/ + rb->snprintf(s, sizeof(s), "%s: %d", p_str(P_LANG_CHOPPER_BESTSCORE), + highscore); rb->lcd_getstringsize(s, &w2, NULL); if (LCD_WIDTH - 2 - w2 > w + 2) rb->lcd_putsxy(LCD_WIDTH - 2 - w2, 2, s); @@ -686,6 +678,9 @@ MENUITEM_STRINGLIST(menu,"Chopper Menu",NULL,"Start New Game","Resume Game", "Level","Quit"); + /*MENUITEM_STRINGLIST(menu, p_str(P_LANG_CHOPPER_MENUTITLE), NULL, + p_str(P_LANG_CHOPPER_START),"Resume Game", + p_str(P_LANG_CHOPPER_LEVEL),"Quit");*/ #ifdef HAVE_LCD_COLOR rb->lcd_set_foreground(LCD_WHITE); @@ -710,11 +705,11 @@ menu_quit=true; res = -1; } else if(menunum==0){ - rb->splash(HZ, "No game to resume"); + rb->splash(HZ, p_str(P_LANG_CHOPPER_NO_GAME)); } break; case 2: - rb->set_option("Level", &iLevelMode, INT, levels, 2, NULL); + rb->set_option(p_str(P_LANG_CHOPPER_LEVEL), &iLevelMode, INT, levels, 2, NULL); break; case 3: menu_quit=true; @@ -987,6 +982,7 @@ rb = api; int ret; + plugin_use_lang(rb, USER_CHOPPER); //3 rb->lcd_setfont(FONT_SYSFIXED); #if LCD_DEPTH > 1 rb->lcd_set_backdrop(NULL); Index: apps/plugins/blackjack.c =================================================================== --- apps/plugins/blackjack.c (revision 18096) +++ apps/plugins/blackjack.c (working copy) @@ -5,7 +5,7 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id: $ + * $Id$ * * Copyright (C) 2006 Tom Ross * @@ -20,6 +20,7 @@ ****************************************************************************/ #include "plugin.h" +#include "pluginlib_lang.h" #include "card_deck.h" #include "card_back.h" @@ -383,32 +384,34 @@ ******************************************************************************/ static void blackjack_drawtable(struct game_context* bj) { unsigned int w, h, y_loc; - char str[10]; + char str[64]; #if LCD_HEIGHT <= 64 - rb->lcd_getstringsize("Bet", &w, &h); - rb->lcd_putsxy(LCD_WIDTH - w, 2*h + 1, "Bet"); + rb->snprintf(str, sizeof(str), "%s", p_str(P_LANG_BET)); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, 2*h + 1, str); rb->snprintf(str, 9, "$%d", bj->current_bet); rb->lcd_getstringsize(str, &w, &h); rb->lcd_putsxy(LCD_WIDTH - w, 3*h + 1, str); y_loc = LCD_HEIGHT/2; #else - rb->lcd_getstringsize("Bet", &w, &h); - rb->lcd_putsxy(LCD_WIDTH - w, 5*h / 2, "Bet"); + rb->snprintf(str, sizeof(str), "%s", p_str(P_LANG_BET)); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, 5*h / 2, str); rb->snprintf(str, 9, "$%d", bj->current_bet); rb->lcd_getstringsize(str, &w, &h); rb->lcd_putsxy(LCD_WIDTH - w, 7*h / 2, str); rb->lcd_hline(0, LCD_WIDTH, LCD_HEIGHT/2); y_loc = LCD_HEIGHT/2 + h; #endif - - rb->lcd_putsxy(0,0, "Dealer"); - rb->lcd_getstringsize("Player", &w, &h); - rb->lcd_putsxy(0, y_loc, "Player"); - rb->lcd_getstringsize("Total", &w, &h); - rb->lcd_putsxy(LCD_WIDTH - w, y_loc, "Total"); - rb->lcd_getstringsize("Money", &w, &h); - rb->lcd_putsxy(LCD_WIDTH - w, 0, "Money"); + rb->lcd_putsxy(0, 0, p_str(P_LANG_DEALER)); + rb->lcd_putsxy(0, y_loc, p_str(P_LANG_PLAYER)); + rb->snprintf(str, sizeof(str), "%s", p_str(P_LANG_TOTAL)); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, y_loc, str); + rb->snprintf(str, sizeof(str), "%s", p_str(P_LANG_MONEY)); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, 0, str); rb->snprintf(str, 9, "$%d", bj->player_money - bj->current_bet); rb->lcd_getstringsize(str, &w, &h); rb->lcd_putsxy(LCD_WIDTH - w, h + 1, str); @@ -486,21 +489,24 @@ * initial cards. ******************************************************************************/ static void deal_init_cards(struct game_context* bj) { + bj->dealer_cards[0] = new_card(); + rb->talk_number(bj->dealer_cards[0].value, true); bj->dealer_total += bj->dealer_cards[0].value; + draw_card(bj->dealer_cards[0], true, dealer_x, dealer_y); - draw_card(bj->dealer_cards[0], false, dealer_x, dealer_y); - bj->dealer_cards[1] = new_card(); bj->dealer_total += bj->dealer_cards[1].value; - draw_card(bj->dealer_cards[1], true, dealer_x + CARD_WIDTH + 4, dealer_y); + draw_card(bj->dealer_cards[1], false, dealer_x + CARD_WIDTH + 4, dealer_y); bj->player_cards[0][0] = new_card(); + rb->talk_number(bj->player_cards[0][0].value, true); bj->player_total += bj->player_cards[0][0].value; draw_card(bj->player_cards[0][0], true, player_x, player_y); player_x += CARD_WIDTH + 4; bj->player_cards[0][1] = new_card(); + rb->talk_number(bj->player_cards[0][1].value, true); bj->player_total += bj->player_cards[0][1].value; draw_card(bj->player_cards[0][1], true, player_x, player_y); player_x += CARD_WIDTH + 4; @@ -610,12 +616,15 @@ ******************************************************************************/ static void finish_dealer(struct game_context* bj) { signed int temp = 0; + + rb->talk_number(bj->dealer_cards[1].value, true); if (bj->dealer_total > 16 && bj->dealer_total < 22) return; while (bj->dealer_total < 17) { bj->dealer_cards[bj->num_dealer_cards] = new_card(); + rb->talk_number(bj->dealer_cards[bj->num_dealer_cards].value, true); bj->dealer_total += bj->dealer_cards[bj->num_dealer_cards].value; bj->num_dealer_cards++; } @@ -636,32 +645,41 @@ ******************************************************************************/ static void finish_game(struct game_context* bj) { unsigned int rValue, w, h; - char str[19]; + char str[64]; do { finish_dealer(bj); } while (bj->dealer_total < 17); + plugin_talk_id(rb, P_LANG_DEALER, true); + rb->talk_number(bj->dealer_total, true); + plugin_talk_id(rb, P_LANG_PLAYER, true); + rb->talk_number(bj->player_total, true); redraw_board(bj); rValue = check_totals(bj); if (rValue == 0) { - rb->snprintf(str, sizeof(str), " Bust! "); + rb->snprintf(str, sizeof(str), " %s ", p_str(P_LANG_BUST)); + plugin_talk_id(rb, P_LANG_BUST, true); bj->player_money -= bj->current_bet; } else if (rValue == 1) { - rb->snprintf(str, sizeof(str), " Sorry, you lost. "); + rb->snprintf(str, sizeof(str), " %s ", p_str(P_LANG_LOST)); + plugin_talk_id(rb, P_LANG_LOST, true); bj->player_money -= bj->current_bet; } else if (rValue == 2) { - rb->snprintf(str, sizeof(str), " Push "); + rb->snprintf(str, sizeof(str), " %s ", p_str(P_LANG_PUSH)); + plugin_talk_id(rb, P_LANG_PUSH, true); } else if (rValue == 3) { - rb->snprintf(str, sizeof(str), " You won! "); + rb->snprintf(str, sizeof(str), " %s ", p_str(P_LANG_WON)); + plugin_talk_id(rb, P_LANG_WON, true); bj->player_money+= bj->current_bet; } else { - rb->snprintf(str, sizeof(str), " Blackjack! "); + rb->snprintf(str, sizeof(str), " %s! ", p_str(P_LANG_BLACKJACK)); + plugin_talk_id(rb, P_LANG_BLACKJACK, true); bj->player_money += bj->current_bet * 3 / 2; } rb->lcd_getstringsize(str, &w, &h); @@ -671,7 +689,7 @@ rb->lcd_fillrect(0, LCD_HEIGHT/2, LCD_WIDTH, LCD_HEIGHT/2); rb->lcd_set_drawmode(DRMODE_SOLID); rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + h, str); - rb->snprintf(str, 12, "You have %d", bj->player_total); + rb->snprintf(str, sizeof(str), "%s %d", p_str(P_LANG_YOU_HAVE), bj->player_total); rb->lcd_getstringsize(str, &w, &h); rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2, str); #else @@ -818,7 +836,8 @@ static void blackjack_callback(void* param) { struct game_context* bj = (struct game_context*) param; if(bj->dirty) { - rb->splash(HZ, "Saving high scores..."); + rb->splash(HZ, p_str(P_LANG_SAVING_HIGH_SCORES)); + plugin_talk_id(rb, P_LANG_SAVING_HIGH_SCORES, true); blackjack_savescores(bj); } } @@ -826,40 +845,41 @@ /***************************************************************************** * blackjack_get_yes_no() gets a yes/no answer from the user ******************************************************************************/ -static unsigned int blackjack_get_yes_no(char message[20]) { +static unsigned int blackjack_get_yes_no(const char *message) { int button; - unsigned int w, h, b, choice = 0; + unsigned int w1, w2, h, b, choice = 0; bool breakout = false; - char message_yes[24], message_no[24]; + char message_yes[64], message_no[64]; + const char *stg[] = {message_yes, message_no}; - rb->strcpy(message_yes, message); - rb->strcpy(message_no, message); - rb->strcat(message_yes, " Yes"); - rb->strcat(message_no, " No"); - rb->lcd_getstringsize(message_yes, &w, &h); - const char *stg[] = {message_yes, message_no}; - + rb->snprintf(message_yes, sizeof(message_yes), "%s %s", message, str(LANG_SET_BOOL_YES)); + rb->snprintf(message_no, sizeof(message_no), "%s %s", message, str(LANG_SET_BOOL_NO)); + rb->lcd_getstringsize(message_yes, &w1, &h); + rb->lcd_getstringsize(message_no, &w2, &h); + w1 = MAX(w1, w2); + rb->talk_id(LANG_SET_BOOL_YES, true); + #if LCD_HEIGHT <= 64 b = 2*h+1; #else b = h-1; #endif + + while(!breakout) { #ifdef HAVE_LCD_COLOR - rb->lcd_fillrect(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b, w+1, h+3); - rb->lcd_set_foreground(LCD_BLACK); - rb->lcd_set_background(LCD_WHITE); + rb->lcd_fillrect(LCD_WIDTH/2 - w1/2, LCD_HEIGHT/2 + b, w1+1, h+3); + rb->lcd_set_foreground(LCD_BLACK); + rb->lcd_set_background(LCD_WHITE); #else - rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID); - rb->lcd_fillrect(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b, w+1, h+3); - rb->lcd_set_drawmode(DRMODE_SOLID); + rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID); + rb->lcd_fillrect(LCD_WIDTH/2 - w1/2, LCD_HEIGHT/2 + b, w1+1, h+3); + rb->lcd_set_drawmode(DRMODE_SOLID); #endif - rb->lcd_drawrect(LCD_WIDTH/2 - w/2 - 1, LCD_HEIGHT/2 + b - 1, w+3, h+4); - - while(!breakout) { - rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + b +1, stg[choice]); - rb->lcd_update_rect(LCD_WIDTH/2 - w/2 - 1, LCD_HEIGHT/2 + b -1, - w+3, h+4); + rb->lcd_drawrect(LCD_WIDTH/2 - w1/2 - 1, LCD_HEIGHT/2 + b - 1, w1+3, h+4); + rb->lcd_putsxy(LCD_WIDTH/2 - w1/2, LCD_HEIGHT/2 + b +1, stg[choice]); + rb->lcd_update_rect(LCD_WIDTH/2 - w1/2 - 1, LCD_HEIGHT/2 + b -1, + w1+3, h+4); button = rb->button_get(true); switch(button) { @@ -868,6 +888,7 @@ case BJACK_RIGHT: case (BJACK_RIGHT|BUTTON_REPEAT): choice ^= 1; + rb->talk_id(choice ? LANG_SET_BOOL_NO : LANG_SET_BOOL_YES, true); break; case BJACK_START: breakout = true; break; @@ -875,28 +896,27 @@ choice = BJ_QUIT; break; } +#if LCD_DEPTH > 1 + rb->lcd_set_foreground(FG_COLOR); + rb->lcd_set_background(BG_COLOR); +#endif } -#if LCD_DEPTH > 1 - rb->lcd_set_foreground(FG_COLOR); - rb->lcd_set_background(BG_COLOR); -#endif return choice; } /***************************************************************************** * blackjack_get_amount() gets an amount from the player to be used ******************************************************************************/ -static signed int blackjack_get_amount(char message[20], signed int lower_limit, - signed int upper_limit, - signed int start) { +static signed int blackjack_get_amount(const char *message, signed int lower_limit, + signed int upper_limit, signed int start) { int button; char str[6]; bool changed = false; unsigned int w, h; signed int amount; - rb->lcd_getstringsize("A", &w, &h); /* find the size of one character */ + rb->lcd_getstringsize(message, &w, &h); if (start > upper_limit) amount = upper_limit; @@ -915,42 +935,29 @@ rb->lcd_puts(0, 1, message); rb->snprintf(str, 9, "$%d", amount); rb->lcd_puts(0, 2, str); - rb->lcd_puts(0, 3, "RIGHT: +1"); - rb->lcd_puts(0, 4, "LEFT: -1"); - rb->lcd_puts(0, 5, "UP: +10"); - rb->lcd_puts(0, 6, "DOWN: -10"); + rb->lcd_puts(0, 3, p_str(P_LANG_BET_INC_SMALL)); + rb->lcd_puts(0, 4, p_str(P_LANG_BET_DEC_SMALL)); + rb->lcd_puts(0, 5, p_str(P_LANG_BET_INC_BIG)); + rb->lcd_puts(0, 6, p_str(P_LANG_BET_DEC_BIG)); rb->lcd_update(); #else rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID); - rb->lcd_fillrect(LCD_WIDTH/2 - 9*w - 1, LCD_HEIGHT/2 - 4*h - 3, 37*w / 2, + rb->lcd_fillrect(LCD_WIDTH/2 - w / 2 - 1, LCD_HEIGHT/2 - 4*h - 3, w+3, 8*h -3); rb->lcd_set_drawmode(DRMODE_SOLID); - rb->lcd_drawrect(LCD_WIDTH/2 - 9*w - 1, LCD_HEIGHT/2 - 4*h - 3, 37*w / 2, + rb->lcd_drawrect(LCD_WIDTH/2 - w / 2 - 1, LCD_HEIGHT/2 - 4*h - 3, w+3, 8*h -3); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 4*h - 1, message); + rb->lcd_putsxy(LCD_WIDTH/2 - w / 2, LCD_HEIGHT/2 - 4*h - 1, message); rb->snprintf(str, 9, "$%d", amount); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, str); -#if (CONFIG_KEYPAD == IPOD_4G_PAD) || \ - (CONFIG_KEYPAD == IPOD_3G_PAD) || \ - (CONFIG_KEYPAD == IPOD_1G2G_PAD) - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, " >>|: +1"); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, " |<<: -1"); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "SCROLL+: +10"); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "SCROLL-: -10"); -#elif CONFIG_KEYPAD == IRIVER_H10_PAD - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, "RIGHT: +1"); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, "LEFT: -1"); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "SCROLL+: +10"); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "SCROLL-: -10"); -#else - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - h-2, "RIGHT: +1"); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 1, "LEFT: -1"); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + h, "UP: +10"); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 + 2*h + 1, "DOWN: -10"); + rb->talk_number(amount, true); + rb->lcd_putsxy(LCD_WIDTH/2 - w / 2, LCD_HEIGHT/2 - 3*h, str); + rb->lcd_putsxy(LCD_WIDTH/2 - w / 2, LCD_HEIGHT/2 - h-2, p_str(P_LANG_BET_INC_SMALL)); + rb->lcd_putsxy(LCD_WIDTH/2 - w / 2, LCD_HEIGHT/2 - 1, p_str(P_LANG_BET_DEC_SMALL)); + rb->lcd_putsxy(LCD_WIDTH/2 - w / 2, LCD_HEIGHT/2 + h, p_str(P_LANG_BET_INC_BIG)); + rb->lcd_putsxy(LCD_WIDTH/2 - w / 2, LCD_HEIGHT/2 + 2*h + 1, p_str(P_LANG_BET_DEC_BIG)); + rb->lcd_update_rect(LCD_WIDTH/2 - w / 2 - 2, LCD_HEIGHT/2 - 9*h/2, w+2, 8*h-2); + rb->lcd_update(); #endif - rb->lcd_update_rect(LCD_WIDTH/2 - 9*w - 2, LCD_HEIGHT/2 - 9*h/2, 37*w/2 + 1, - 8*h-2); -#endif while(true) { button = rb->button_get(true); @@ -1005,15 +1012,16 @@ if(changed) { rb->snprintf(str, 9, "$%d", amount); + rb->talk_number(amount, false); #if LCD_HEIGHT <= 64 rb->lcd_puts(0, 2, str); rb->lcd_update(); #else rb->lcd_set_drawmode(DRMODE_BG+DRMODE_INVERSEVID); - rb->lcd_fillrect(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, 5*w, h); + rb->lcd_fillrect(LCD_WIDTH/2 - w / 2, LCD_HEIGHT/2 - 3*h, w, h); rb->lcd_set_drawmode(DRMODE_SOLID); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, str); - rb->lcd_update_rect(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 3*h, 5*w, h); + rb->lcd_putsxy(LCD_WIDTH/2 - w / 2, LCD_HEIGHT/2 - 3*h, str); + rb->lcd_update_rect(LCD_WIDTH/2 - w / 2, LCD_HEIGHT/2 - 3*h, w, h); #endif changed = false; } @@ -1024,7 +1032,8 @@ * blackjack_get_bet() gets the player's bet. ******************************************************************************/ static void blackjack_get_bet(struct game_context* bj) { - bj->current_bet = blackjack_get_amount("Please enter a bet", 10, + plugin_talk_id(rb, P_LANG_GET_BET, true); + bj->current_bet = blackjack_get_amount(p_str(P_LANG_GET_BET), 10, bj->player_money, bj->current_bet); } @@ -1044,7 +1053,8 @@ * means a split has already occurred and the first hand is done. ******************************************************************************/ static void split(struct game_context* bj) { - if (blackjack_get_yes_no("Split?") == 1) + plugin_talk_id(rb, P_LANG_ASK_SPLIT, true); + if (blackjack_get_yes_no(p_str(P_LANG_ASK_SPLIT)) == 1) bj->split_status = 1; else { bj->split_status = 2; @@ -1062,13 +1072,15 @@ static unsigned int insurance(struct game_context* bj) { unsigned int insurance, max_amount; - insurance = blackjack_get_yes_no("Buy Insurance?"); + plugin_talk_id(rb, P_LANG_BUY_INSURANCE, false); + insurance = blackjack_get_yes_no(p_str(P_LANG_BUY_INSURANCE)); bj->asked_insurance = true; max_amount = bj->current_bet < (unsigned int)bj->player_money ? bj->current_bet/2 : (unsigned int)bj->player_money; if (insurance == 1) return 0; - insurance = blackjack_get_amount("How much?", 0, max_amount, 0); + plugin_talk_id(rb, P_LANG_HOW_MUCH, true); + insurance = blackjack_get_amount(p_str(P_LANG_HOW_MUCH), 0, max_amount, 0); redraw_board(bj); return insurance; } @@ -1077,7 +1089,8 @@ * play_again() checks to see if the player wants to keep playing. ******************************************************************************/ static unsigned int play_again(void) { - return blackjack_get_yes_no("Play Again?"); + plugin_talk_id(rb, P_LANG_PLAY_AGAIN, true); + return blackjack_get_yes_no(p_str(P_LANG_PLAY_AGAIN)); } /***************************************************************************** @@ -1085,8 +1098,7 @@ ******************************************************************************/ static unsigned int blackjack_menu(struct game_context* bj) { int button; - char *title = "Blackjack"; - char str[18]; + char str[64]; unsigned int i, w, h; bool breakout = false; bool showscores = false; @@ -1100,8 +1112,9 @@ if(!showscores) { /* welcome screen to display key bindings */ - rb->lcd_getstringsize(title, &w, &h); - rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, title); + rb->snprintf(str, sizeof(str), "%s", p_str(P_LANG_BLACKJACK)); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, str); #if CONFIG_KEYPAD == RECORDER_PAD rb->lcd_puts(0, 1, "ON: start"); @@ -1234,13 +1247,14 @@ rb->lcd_puts(0, 4, "LCD BOTTOMRIGHT to save/resume"); #endif } else { - rb->snprintf(str, 12, "%s", "High Scores"); + rb->snprintf(str, sizeof(str), "%s", p_str(P_LANG_HIGH_SCORE_TITLE)); rb->lcd_getstringsize(str, &w, &h); rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, str); + plugin_talk_id(rb, P_LANG_HIGH_SCORE_TITLE, false); /* print high scores */ for(i=0; isnprintf(str, 14, "#%02d: $%d", i+1, bj->highscores[i]); + rb->snprintf(str, sizeof(str), "#%02d: $%d", i+1, bj->highscores[i]); rb->lcd_puts(0, i+1, str); } } @@ -1264,9 +1278,9 @@ case BJACK_RESUME:/* resume game */ if(!blackjack_loadgame(bj)) { - rb->splash(HZ*2, "Nothing to resume"); + rb->splash(HZ*2, ID2P(LANG_NOTHING_TO_RESUME)); } else { - rb->splash(HZ*2, "Loading..."); + rb->splash(HZ*2, ID2P(LANG_WAIT)); breakout = true; } break; @@ -1295,6 +1309,7 @@ int button; unsigned int w, h, temp_var, done = 0, todo = 1; signed int temp; + char buf[64]; bool breakout = false; bool dbl_down = false; @@ -1358,7 +1373,8 @@ !bj->asked_insurance) { temp_var = insurance(bj); if (bj->dealer_total == 21) { - rb->splash(HZ, "Dealer has blackjack"); + rb->splash(HZ, p_str(P_LANG_DEALER_BLACKJACK)); + plugin_talk_id(rb, P_LANG_DEALER_BLACKJACK, true); bj->player_money += temp_var; bj->end_hand = true; breakout = true; @@ -1366,7 +1382,8 @@ finish_game(bj); } else { - rb->splash(HZ, "Dealer does not have blackjack"); + rb->splash(HZ, p_str(P_LANG_DEALER_NO_BLACKJACK)); + plugin_talk_id(rb, P_LANG_DEALER_NO_BLACKJACK, true); bj->player_money -= temp_var; breakout = true; redraw_board(bj); @@ -1391,6 +1408,7 @@ case BJACK_HIT: NEXT_CARD = new_card(); bj->player_total += NEXT_CARD.value; + rb->talk_number(NEXT_CARD.value, true); draw_card(NEXT_CARD, true, player_x, player_y); bj->num_player_cards[done]++; if (bj->num_player_cards[done] == MAX_CARDS + 1) { @@ -1425,13 +1443,15 @@ } } else if((signed int)bj->current_bet * 2 > bj->player_money) { - rb->splash(HZ, "Not enough money to double down."); + plugin_talk_id(rb, P_LANG_NEED_MONEY_DOUBLE_DOWN, true); + rb->splash(HZ, p_str(P_LANG_NEED_MONEY_DOUBLE_DOWN)); redraw_board(bj); rb->lcd_update(); } break; case BJACK_RESUME: /* save and end game */ - rb->splash(HZ, "Saving game..."); + plugin_talk_id(rb, P_LANG_SAVING_GAME, true); + rb->splash(HZ, p_str(P_LANG_SAVING_GAME)); blackjack_savegame(bj); /* fall through to BJACK_QUIT */ @@ -1463,20 +1483,22 @@ bj->player_total = temp_var; temp_var = temp; finish_game(bj); - rb->lcd_getstringsize(" Split 1 ", &w, &h); - rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, - " Split 1 "); - rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, - w,h); + rb->snprintf(buf, sizeof(buf), " %s 1 ", p_str(P_LANG_SPLIT)); + plugin_talk_id(rb, P_LANG_SPLIT, true); + rb->talk_number(1, true); + rb->lcd_getstringsize(buf, &w, &h); + rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, buf); bj->current_bet /= 2; rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, w,h); rb->sleep(HZ*2); bj->player_total = temp_var; finish_game(bj); - rb->lcd_getstringsize(" Split 2 ", &w, &h); - rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, - " Split 2 "); + rb->snprintf(buf, sizeof(buf), " %s 2 ", p_str(P_LANG_SPLIT)); + plugin_talk_id(rb, P_LANG_SPLIT, true); + rb->talk_number(2, true); + rb->lcd_getstringsize(buf, &w, &h); + rb->lcd_putsxy(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, buf); rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, w,h); rb->sleep(HZ*2); @@ -1536,10 +1558,11 @@ struct game_context bj; bool exit = false; unsigned int position; - char str[19]; + char str[64]; (void)parameter; rb = api; + plugin_use_lang(rb, USER_BLACKJACK); // 2 #if LCD_DEPTH > 1 rb->lcd_set_backdrop(NULL); @@ -1549,17 +1572,22 @@ blackjack_loadscores(&bj); rb->lcd_setfont(FONT_SYSFIXED); + plugin_talk_id(rb, P_LANG_BLACKJACK, false); while(!exit) { switch(blackjack(&bj)){ case BJ_LOSE: - rb->splash(HZ, "Not enough money to continue"); + plugin_talk_id(rb, P_LANG_NEED_MONEY_CONTINUE, true); + rb->splash(HZ, p_str(P_LANG_NEED_MONEY_CONTINUE)); /* fall through to BJ_END */ case BJ_END: if(!bj.resume) { if((position = blackjack_recordscore(&bj))) { - rb->snprintf(str, 19, "New high score #%d!", position); + rb->snprintf(str, sizeof(str), "%s #%d!", + p_str(P_LANG_NEW_HIGH_SCORE), position); + plugin_talk_id(rb, P_LANG_NEW_HIGH_SCORE, true); + rb->talk_number(position, true); rb->splash(HZ*2, str); } } @@ -1571,7 +1599,8 @@ case BJ_QUIT: if(bj.dirty) { - rb->splash(HZ, "Saving high scores..."); + plugin_talk_id(rb, P_LANG_SAVING_HIGH_SCORES, true); + rb->splash(HZ, p_str(P_LANG_SAVING_HIGH_SCORES)); blackjack_savescores(&bj); } exit = true; Index: apps/settings.h =================================================================== --- apps/settings.h (revision 18096) +++ apps/settings.h (working copy) @@ -65,6 +65,7 @@ #define ICON_DIR ROCKBOX_DIR "/icons" #define PLUGIN_DIR ROCKBOX_DIR "/rocks" +#define PLUGIN_LANG_DIR ROCKBOX_DIR "/plangs" #define PLUGIN_GAMES_DIR PLUGIN_DIR "/games" #define PLUGIN_APPS_DIR PLUGIN_DIR "/apps" #define PLUGIN_DEMOS_DIR PLUGIN_DIR "/demos" Index: apps/plugin.c =================================================================== --- apps/plugin.c (revision 18096) +++ apps/plugin.c (working copy) @@ -37,6 +37,7 @@ #include "logf.h" #include "option_select.h" #include "talk.h" +#include "language.h" #if CONFIG_CHARGING #include "power.h" @@ -60,10 +61,10 @@ extern unsigned char pluginbuf[]; #include "bitswap.h" #endif +void plugin_dump_mem(void); /* for actual plugins only, not for codecs */ -static bool plugin_loaded = false; -static int plugin_size = 0; +static int plugin_used_buffer = 0; static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */ static char current_plugin[MAX_PATH]; @@ -605,8 +606,17 @@ #ifdef HAVE_TAGCACHE tagcache_get_numeric, #endif - gui_syncyesno_run, + lang_init_helper, + lang_validate, + lang_load_helper, + &language_strings[0], +#ifdef SIMULATOR + &vp_dummy[0], +#endif + talk_id, + talk_idarray, + talk_number, }; int plugin_load(const char* plugin, const void* parameter) @@ -635,7 +645,7 @@ return PLUGIN_OK; } pfn_tsr_exit = NULL; - plugin_loaded = false; + plugin_used_buffer = 0; } gui_syncsplash(0, ID2P(LANG_WAIT)); @@ -695,16 +705,12 @@ gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); return -1; } - plugin_size = hdr->end_addr - pluginbuf; + plugin_used_buffer = hdr->end_addr - pluginbuf; /* zero out bss area only, above guards end of pluginbuf */ - if (plugin_size > readsize) - memset(pluginbuf + readsize, 0, plugin_size - readsize); + if (plugin_used_buffer > readsize) + memset(pluginbuf + readsize, 0, plugin_used_buffer - readsize); #endif - - plugin_loaded = true; - - #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1 old_backdrop = lcd_get_backdrop(); #endif @@ -717,8 +723,9 @@ #endif invalidate_icache(); - + rc = hdr->entry_point(&rockbox_api, parameter); + plugin_dump_mem(); button_clear_queue(); @@ -755,7 +762,7 @@ #endif if (pfn_tsr_exit == NULL) - plugin_loaded = false; + plugin_used_buffer = 0; sim_plugin_close(pd); @@ -777,23 +784,11 @@ being used. If no plugin is loaded, returns the entire plugin buffer */ void* plugin_get_buffer(size_t *buffer_size) { - int buffer_pos; - - if (plugin_loaded) - { - if (plugin_size >= PLUGIN_BUFFER_SIZE) - return NULL; - - *buffer_size = PLUGIN_BUFFER_SIZE-plugin_size; - buffer_pos = plugin_size; - } - else - { - *buffer_size = PLUGIN_BUFFER_SIZE; - buffer_pos = 0; - } - - return &pluginbuf[buffer_pos]; + if(plugin_used_buffer >= PLUGIN_BUFFER_SIZE) + return NULL; + + *buffer_size = PLUGIN_BUFFER_SIZE - plugin_used_buffer; + return &pluginbuf[plugin_used_buffer]; } /* Returns a pointer to the mp3 buffer. @@ -841,3 +836,13 @@ { return current_plugin; } + +void plugin_dump_mem(void) +{ + unsigned int fd; + + /* write out the high scores to the save file */ + fd = open("/plugin_dump.bin", O_WRONLY|O_CREAT); + write(fd, pluginbuf, PLUGIN_BUFFER_SIZE); + close(fd); +} Index: apps/plugin.h =================================================================== --- apps/plugin.h (revision 18096) +++ apps/plugin.h (working copy) @@ -125,6 +125,11 @@ #define PREFIX(_x_) _x_ #endif +#if defined(SIMULATOR) && defined(PLUGIN) +#undef VIRT_PTR +#define VIRT_PTR rb->vp_dummy +#endif + #define PLUGIN_MAGIC 0x526F634B /* RocK */ /* increase this every time the api struct changes */ @@ -758,11 +763,22 @@ #ifdef HAVE_TAGCACHE long (*tagcache_get_numeric)(const struct tagcache_search *tcs, int tag); #endif - enum yesno_res (*gui_syncyesno_run)(const struct text_message * main_message, const struct text_message * yes_message, const struct text_message * no_message); - + void (*lang_init_helper)(unsigned char *builtin, unsigned char **dest, int count); + int (*lang_validate)(int fd); + void (*lang_load_helper)(int fd, const unsigned char *builtin, + unsigned char **dest, unsigned char *buffer, + unsigned int max, unsigned int lang_size, + unsigned int foffset); + unsigned char **language_strings; +#ifdef SIMULATOR + unsigned char *vp_dummy; +#endif + int (*talk_id)(int32_t id, bool enqueue); + int (*talk_idarray)(long *ids, bool enqueue); + int (*talk_number)(long n, bool enqueue); }; /* plugin header */