Index: tools/genlang =================================================================== --- tools/genlang (revision 20189) +++ 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,9 +22,21 @@ # figured it was boring and unnecessary to write support for now since we # don't use it anymore. +# This hash array and string must be kept in sync and the order must match. my %user2num = - ('core' => 1); + ('core' => 1, + 'blackjack' => 2, + 'chessbox' => 3, + 'chopper' => 4); +my $plugin_enum = " +enum user_type { + USER_CORE, /* 0 */ + USER_BLACKJACK, /* 1 */ + USER_CHESSBOX, /* 2 */ + USER_CHOPPER /* 3 */ +}; +"; if(!$ARGV[0]) { print <) { # get rid of DOS newlines @@ -227,17 +254,24 @@ # if id is something, when we count and store this phrase if($id) { + #print $id . "," . $user . "\n"; # voice-only entries get a difference range if($id =~ /^VOICE_/) { # Assign an ID number to this entry - $idmap{$id}=$vidnum; - $vidnum++; + $idmap[$user]{$id}=$vidnum[$user]; + #print $idmap[$user]{$id} . "\n"; + $vidnum[$user]++; } + #elsif($id =~ /^P_LANG_/) { + # Assign an ID number to this entry + # $idmap{$id}=$pl_idnum; + # $pl_idnum++; + #} else { # Assign an ID number to this entry - $idmap{$id}=$idnum; - $idnum++; - # print STDERR "DEST: bumped idnum to $idnum\n"; + $idmap[$user]{$id}=$idnum[$user]; + $idnum[$user]++; + # print STDERR "DEST: bumped idnum to $idnum[$user]\n"; } # this is the end of a phrase, add it to the english hash @@ -369,9 +403,16 @@ print @show; } -my $idcount; # counter for lang ID numbers -my $voiceid=0x8000; # counter for voice-only ID numbers +my @idcount; # counter for lang ID numbers +my @voiceid; # counter for voice-only ID numbers +my $pl_idcount; # count for plugin lang ID numbers +my $pl_voiceid=0xB000; # counter for plugin voice-only ID numbers +foreach $i (keys %user2num) { + push @idcount, 0; + push @voiceid, 0x8000; +} + # # Now start the scanning of the selected language string # @@ -379,6 +420,7 @@ open(LANG, "<$input") || die "Error: couldn't read language file named $input\n"; my @phrase; my $header = 1; +my @num_strings; while() { $line++; @@ -418,9 +460,9 @@ 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($sortfile) { $allphrases{$idstr}=join('',@phrase); @@ -465,18 +507,20 @@ # separated. if($idstr =~ /^VOICE/) { - $idnum = $voiceid++; + $idnum = $voiceid[$user]++; } else { - $idnum = $idcount++; + $idnum = $idcount[$user]++; + $num_strings[$user]++; } $id{$idstr} = $idnum; - $idnum[$idnum]=$idstr; + $idnum[$user][$idnum]=$idstr; $source{$idstr}=$src; $dest{$idstr}=$dest; $voice{$idstr}=$voice; + $user{$idstr}=$user; if($verbose) { print "id: $phrase{id} ($idnum)\n"; @@ -485,7 +529,6 @@ print "voice: $voice\n"; print "user: $user\n"; } - undef $src; undef $dest; undef $voice; @@ -553,101 +596,139 @@ if($prefix) { # We create a .c and .h file - open(HFILE, ">$prefix/lang.h") || + open(HFILE_CORE, ">$prefix/lang.h") || die "Error: couldn't create file $prefix/lang.h\n"; - open(CFILE, ">$prefix/lang_core.c") || - die "Error: couldn't create file $prefix/lang_core.c\n"; # get header file name $headername = "$prefix/lang.h"; $headername =~ s/(.*\/)*//; - print HFILE <$prefix/lang\_$key.c") || + die "Error: couldn't create file $prefix\_$key.c\n"; + + if($key eq "core") { + print CFILE <$prefix\_plugin.h") || + die "Error: couldn't create file $prefix\_plugin.h\n"; + foreach $key (sort {$user2num{$a} cmp $user2num{$b} } keys %user2num) { + if($key ne "core") { + printf HFILE_PLUGIN "extern const unsigned char $key\_language_builtin\[];\n"; } + } - printf CFILE (" %s\n", $dest); + print HFILE_PLUGIN $plugin_enum; + close(HFILE_PLUGIN); + open(CFILE_PLUGIN, ">$prefix/lang\_plugin.c") || + die "Error: couldn't create file $prefix/lang\_plugin.c\n"; + printf CFILE_PLUGIN ("unsigned int num_strings[%d] = {\n", scalar keys %user2num); + for $i (1 .. keys %user2num) { + printf CFILE_PLUGIN (" %d,\n", $idcount[$i]); } - -# Output end of string chunk - print CFILE <$binary") or die "Error: Can't create $binary"; binmode OUTF; printf OUTF ("\x1a%c%c", $langversion, $target_id); # magic lang file header + + # output the number of strings for each user + my $foffset = 3 + keys(%user2num) * 6; + for $i (1 .. keys(%user2num)) { + my $size; + for $n (0 .. $idcount[$i] - 1) { + $size += length(trim($dest{$idnum[$i][$n]})) + 1; + } + #printf ("%d %d %d\n", $idcount[$i], $size, $foffset); + printf OUTF ("%c%c%c%c%c%c", ($idcount[$i] >> 8), ($idcount[$i] & 0xff), + ($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 + for $i (1 .. keys(%user2num)) { + # loop over the target phrases + for $n (1 .. $idcount[$i]) { + my $name=$idnum[$i][$n - 1]; # get the ID + my $dest = $dest{$name}; # get the destination phrase - if($dest) { - $dest =~ s/^\"(.*)\"\s*$/$1/g; # cut off quotes + if($dest) { + $dest =~ s/^\"(.*)\"\s*$/$1/g; # cut off quotes - # Now, make sure we get the number from the english sort order: - $idnum = $idmap{$name}; + # Now, make sure we get the number from the english sort order: + $idnum = $idmap[$i]{$name}; - printf OUTF ("%c%c%s\x00", ($idnum>>8), ($idnum&0xff), $dest); + printf OUTF ("%c%c%s\x00", ($idnum>>8), ($idnum&0xff), $dest); + } } } } @@ -681,52 +777,81 @@ # fashion my @engl; + my $idcount; + my $voiceid; + + for $i (1 .. keys(%user2num)) { + $idcount += $idcount[$i] - 1; + } # This loops over the strings in the translated language file order my @ids = ((0 .. ($idcount-1))); - push @ids, (0x8000 .. ($voiceid-1)); + push @ids, (0x8000 .. ($voiceid[$user2num{'core'}]-1)); #for my $id (@ids) { - # print "$id\n"; + # print "id: $id\n"; #} - for $i (@ids) { - my $name=$idnum[$i]; # get the ID - my $dest = $voice{$name}; # get the destination voice string + my $offset = 0; + foreach $key (sort {$user2num{$a} cmp $user2num{$b} } keys %user2num) { + my $start = 0; + my $end = $idcount[$user2num{$key}] - 1; + for $j (1 .. 2) { + for $i ($start .. $end) { + my $name = $idnum[$user2num{$key}][$i]; # get the ID + my $dest = $voice{$name}; # get the destination voice string - if($dest) { - $dest =~ s/^\"(.*)\"\s*$/$1/g; # cut off quotes + if($dest) { + $dest =~ s/^\"(.*)\"\s*$/$1/g; # cut off quotes - # Now, make sure we get the number from the english sort order: - $idnum = $idmap{$name}; + # Now, make sure we get the number from the english sort order: + $idnum = $idmap[$user2num{$key}]{$name} + $offset; - if(length($idnum)) { - $engl[$idnum] = $i; + if(length($idnum)) { + $engl[$idnum] = $i + $offset; - #print "Input index $i output index $idnum\n"; + #print "Input index $i output index $idnum\n"; + } + else { + # not used, mark it so + $engl[$i + $offset] = -1 + } + + } } - else { - # not used, mark it so - $engl[$i] = -1 + if($j == 1) { + $offset += $idcount[$user2num{$key}]; + $start = 0x8000; + $end = $voiceid[$user2num{$key}] - 1; } - } } - for my $i (@ids) { + $offset = 0; + foreach $key (sort {$user2num{$a} cmp $user2num{$b} } keys %user2num) { + my $start = 0; + my $end = $idcount[$user2num{$key}] - 1; + for $j (1 .. 2) { + printf("Range: %d-%d\n", $start, $end); + for $i ($start .. $end) { + my $o = $engl[$i + $offset]; - my $o = $engl[$i]; + if(($o < 0) || !length($o)) { + printf("#%d\nid: NOT_USED_%d\nvoice: \"\"\n", $i+$offset, $i+$offset); + next; + } - if(($o < 0) || !length($o)) { - print "#$i\nid: NOT_USED_$i\nvoice: \"\"\n"; - next; + my $name=$idnum[$user2num{$key}][$o - $offset]; # get the ID + my $dest = $voice{$name}; # get the destination voice string + + printf("#%d (%d)\nid: %s\nvoice: %s\n", $i+$offset, $o, $name, $dest); + } + if($j == 1) { + $offset += $idcount[$user2num{$key}]; + $start = 0x8000; + $end = $voiceid[$user2num{$key}] - 1; + } } - - my $name=$idnum[$o]; # get the ID - my $dest = $voice{$name}; # get the destination voice string - - print "#$i ($o)\nid: $name\nvoice: $dest\n"; } - } Index: tools/make.inc =================================================================== --- tools/make.inc (revision 20189) +++ tools/make.inc (working copy) @@ -45,7 +45,7 @@ rm $$del; \ del=""; \ fi \ - done | sed -e "s:[^[:space:]]*lang.h:$(OBJDIR)/lang/lang_core.o:" \ + done | sed -e "s:[^[:space:]]*lang.h:$(BUILDDIR)/lang/lang_core.o:" \ -e "s:[^[:space:]]*sysfont.h:$(BUILDDIR)/sysfont.h:" \ -e "s:[^[:space:]]*max_language_size.h:$(BUILDDIR)/max_language_size.h:" \ -e "s: bitmaps/: $(BUILDDIR)/bitmaps/:g" \ Index: apps/language.c =================================================================== --- apps/language.c (revision 20189) +++ apps/language.c (working copy) @@ -33,68 +33,101 @@ /* 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 static unsigned char language_buffer[MAX_LANGUAGE_SIZE]; +static unsigned char** plugin_language_strings; +static unsigned int id_offset; -void lang_init(void) +void lang_init_helper(unsigned char *builtin, unsigned char **dest, int count) { - 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 */ + while(count--) { + *dest++ = builtin; + builtin += strlen((char *)builtin) + 1; /* advance pointer to next string */ } } -int lang_load(const char *filename) +void lang_init(void) { - int fsize; + lang_init_helper((unsigned char*)core_language_builtin, language_strings, + LANG_LAST_INDEX_IN_ARRAY); +} + +int lang_load_helper(const char *filename, const unsigned char *builtin, + unsigned char **dest, unsigned char *buffer, + unsigned int user, unsigned int max_lang_size, + unsigned int max) +{ int fd = open(filename, O_RDONLY); int retcode=0; - unsigned char lang_header[3]; + unsigned int id, num_str, lang_size, foffset; + unsigned char read_buffer[6]; if(fd < 0) return 1; - 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 */ + + read(fd, read_buffer, 3); + if((read_buffer[0] == LANGUAGE_COOKIE) && + (read_buffer[1] == LANGUAGE_VERSION) && + (read_buffer[2] == TARGET_ID)) { + /* read in the number of strings, filesize, and file offset*/ + lseek(fd, user * 6, SEEK_CUR); + read(fd, read_buffer, 6); + num_str = (read_buffer[0]<<8) | read_buffer[1]; + lang_size = (read_buffer[2]<<8) | read_buffer[3]; + foffset = (read_buffer[4]<<8) | read_buffer[5]; + if(lang_size <= max_lang_size) { + /* initialize with builtin */ + lang_init_helper((unsigned char*)builtin, dest, num_str); + lseek(fd, foffset, SEEK_SET); + read(fd, buffer, lang_size); - 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 - DEBUGF("%2x New: %30s ", id, ptr); - DEBUGF("Replaces: %s\n", language_strings[id]); -#endif - language_strings[id] = ptr; /* point to this string */ + while(lang_size > 3) { + id = ((buffer[0]<<8) | buffer[1]); /* get two-byte id */ + buffer += 2; /* 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 be loaded */ + dest[id] = buffer; } - while(*ptr) { /* pass the string */ - fsize--; - ptr++; + while(*buffer) { /* pass the string */ + lang_size--; + buffer++; } - fsize-=3; /* the id and the terminating zero */ - ptr++; /* pass the terminating zero-byte */ + lang_size-=3; /* the id and the terminating zero */ + buffer++; /* pass the terminating zero-byte */ } } else { - DEBUGF("Illegal language file\n"); - retcode = 2; + DEBUGF("Language %s too large: %d\n", filename, lang_size); + retcode = 3; } } else { - DEBUGF("Language %s too large: %d\n", filename, fsize); - retcode = 3; + DEBUGF("Illegal language file\n"); + retcode = 2; } close(fd); return retcode; } + +int lang_load(const char *filename) +{ + return lang_load_helper(filename, core_language_builtin, language_strings, + language_buffer, 0, MAX_LANGUAGE_SIZE, + LANG_LAST_INDEX_IN_ARRAY); +} + +void lang_set_plugin_access(unsigned char **strings_ptr, unsigned int offset) +{ + plugin_language_strings = strings_ptr; + id_offset = offset; +} + +unsigned char * lang_get_plugin_string(unsigned int id) +{ + return plugin_language_strings[id - PLUGIN_DELIMITER - id_offset - 1]; +} Index: apps/language.h =================================================================== --- apps/language.h (revision 20189) +++ apps/language.h (working copy) @@ -21,10 +21,18 @@ * ****************************************************************************/ -/* Initialize language array with the builtin strings */ -void lang_init(void); + /* Initialize language array with the builtin strings */ + void lang_init(void); +void lang_init_helper(unsigned char *builtin, unsigned char **dest, int count); + + /* load a given language file */ + int lang_load(const char *filename); +int lang_load_helper(const char *filename, const unsigned char *builtin, + unsigned char **dest, unsigned char *buffer, + unsigned int user, unsigned int max_lang_size, + unsigned int max); + +void lang_set_plugin_access(unsigned char **strings_ptr, unsigned int offset); +unsigned char * lang_get_plugin_string(unsigned int id); -/* load a given language file */ -int lang_load(const char *filename); - #endif Index: apps/plugins/chessbox/chessbox.c =================================================================== --- apps/plugins/chessbox/chessbox.c (revision 20189) +++ apps/plugins/chessbox/chessbox.c (working copy) @@ -22,6 +22,8 @@ ****************************************************************************/ #include "plugin.h" +#include "lang.h" +#include "lib/pluginlib_lang.h" #ifdef HAVE_LCD_BITMAP @@ -269,7 +271,7 @@ short sq,i,c; unsigned short temp; - rb->splash ( 0 , "Saving position" ); + rb->splash ( 0 , ID2P(P_LANG_CHESSBOX_LOADING_POS) ); fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT); @@ -324,7 +326,7 @@ unsigned short m; if ( (fd = rb->open(SAVE_FILE, O_RDONLY)) >= 0 ) { - rb->splash ( 0 , "Loading position" ); + rb->splash ( 0 , ID2P(P_LANG_CHESSBOX_LOADING_POS) ); rb->read(fd, &(computer), sizeof(computer)); rb->read(fd, &(opponent), sizeof(opponent)); rb->read(fd, &(Game50), sizeof(Game50)); @@ -393,9 +395,13 @@ int result = 0; bool menu_quit = false; - MENUITEM_STRINGLIST(menu,"Chessbox Menu",NULL,"Restart Game", - "Select Other Game", "Quit"); - + //MENUITEM_STRINGLIST(menu,"Chessbox Menu",NULL,"Restart Game", + // "Select Other Game", "Quit"); + MENUITEM_STRINGLIST(menu,ID2P(P_LANG_CHESSBOX_MENU_TITLE), NULL, + ID2P(P_LANG_CHESSBOX_MENU_RESTART_GAME), + ID2P(P_LANG_CHESSBOX_MENU_SELECT_OTHER_GAME), + ID2P(P_LANG_CHESSBOX_MENU_QUIT)); + while(!menu_quit) { switch(rb->do_menu(&menu, &selection, NULL, false)) @@ -455,7 +461,7 @@ first_game = pgn_list_games(filename); if (first_game == NULL){ - rb->splash ( HZ*2 , "No games found !" ); + rb->splash ( HZ*2 , ID2P(P_LANG_CHESSBOX_NO_GAME) ); return; } @@ -485,7 +491,7 @@ if (curr_ply->prev_node != NULL){ curr_ply = curr_ply->prev_node; } else { - rb->splash ( HZ*2 , "At the begining of the game" ); + rb->splash ( HZ*2 , ID2P(P_LANG_CHESSBOX_BEGINNING) ); break; } board[locn[curr_ply->row_from][curr_ply->column_from]] @@ -531,7 +537,7 @@ case COMMAND_NEXT: /* apply the current move */ if (curr_ply->player == neutral){ - rb->splash ( HZ*2 , "At the end of the game" ); + rb->splash ( HZ*2 , ID2P(P_LANG_CHESSBOX_END) ); break; } board[locn[curr_ply->row_to][curr_ply->column_to]] @@ -583,7 +589,7 @@ } } while (!exit_game && !exit_viewer); } else { - rb->splash ( HZ*2 , "Error parsing game !"); + rb->splash ( HZ*2 , ID2P(P_LANG_CHESSBOX_PARSE_ERROR)); } } while (!exit_viewer); } @@ -595,12 +601,18 @@ int result = 0; bool menu_quit = false; - MENUITEM_STRINGLIST(menu,"Chessbox Menu",NULL,"New Game","Resume Game", +/* MENUITEM_STRINGLIST(menu,"Chessbox Menu",NULL,"New Game","Resume Game", "Save Game", "Restore Game", #ifdef HAVE_PLAYBACK_CONTROL "Playback Control", #endif - "Quit"); + "Quit"); */ + MENUITEM_STRINGLIST(menu,ID2P(P_LANG_CHESSBOX_MENU_TITLE), NULL, + ID2P(P_LANG_CHESSBOX_MENU_NEW_GAME), + ID2P(P_LANG_CHESSBOX_MENU_RESUME_GAME), + ID2P(P_LANG_CHESSBOX_MENU_SAVE_GAME), + ID2P(P_LANG_CHESSBOX_MENU_RESTORE_GAME), + ID2P(P_LANG_CHESSBOX_MENU_QUIT)); while(!menu_quit) { @@ -793,7 +805,7 @@ while (!exit) { if ( mate ) { - rb->splash ( HZ*3 , "Checkmate!" ); + rb->splash ( HZ*3 , ID2P(P_LANG_CHESSBOX_CHECKMATE) ); rb->button_get(true); pgn_store_game(game); GNUChess_Initialize(); @@ -804,7 +816,7 @@ switch (command.type) { case COMMAND_MOVE: if ( ! VerifyMove (opponent, command.mv_s , 0 , &command.mv, move_buffer ) ) { - rb->splash ( HZ/2 , "Illegal move!" ); + rb->splash ( HZ/2 , ID2P(P_LANG_CHESSBOX_ILLEGAL_MOVE) ); cb_drawboard(); } else { cb_drawboard(); @@ -812,7 +824,7 @@ /* Add the ply to the PGN history (in algebraic notation) */ pgn_append_ply(game, opponent, move_buffer, mate); - rb->splash ( 0 , "Thinking..." ); + rb->splash ( 0 , ID2P(P_LANG_CHESSBOX_THINKING) ); #ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost ( true ); #endif @@ -872,7 +884,7 @@ opponent = white; computer = black; } - rb->splash ( 0 , "Thinking..." ); + rb->splash ( 0 , ID2P(P_LANG_CHESSBOX_THINKING) ); ElapsedTime(1); #ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost ( true ); @@ -923,6 +935,7 @@ #if LCD_DEPTH > 1 rb->lcd_set_backdrop(NULL); #endif + plugin_use_lang(rb, USER_CHESSBOX, chessbox_language_builtin); /* end of plugin init */ Index: apps/plugins/plugins.make =================================================================== --- apps/plugins/plugins.make (revision 20189) +++ apps/plugins/plugins.make (working copy) @@ -24,7 +24,7 @@ PLUGINLIB_OBJ := $(PLUGINLIB_SRC:.c=.o) PLUGINLIB_OBJ := $(PLUGINLIB_OBJ:.S=.o) -PLUGINLIB_OBJ := $(subst $(ROOTDIR),$(BUILDDIR),$(PLUGINLIB_OBJ)) +PLUGINLIB_OBJ := $(subst $(ROOTDIR),$(BUILDDIR),$(PLUGINLIB_OBJ)) $(BUILDDIR)/lang/lang_plugin.o ### build data / rules ifndef SIMVER @@ -71,11 +71,17 @@ $(SILENT)mkdir -p $(dir $@) $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) -I$(dir $<) $(PLUGINFLAGS) -ffunction-sections -c $< -o $@ +# special pattern rule for compiling plugins with extra flags and loadable languages +$(BUILDDIR)/apps/plugins/%.o: $(ROOTDIR)/apps/plugins/%.c $(BUILDDIR)/lang/lang_%.o $(PLUGINBITMAPLIB) + $(SILENT)mkdir -p $(dir $@) + $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) -I$(dir $<) $(PLUGINFLAGS) -c $< -o $@ + # special pattern rule for compiling plugins with extra flags $(BUILDDIR)/apps/plugins/%.o: $(ROOTDIR)/apps/plugins/%.c $(PLUGINBITMAPLIB) $(SILENT)mkdir -p $(dir $@) $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) -I$(dir $<) $(PLUGINFLAGS) -c $< -o $@ + ifdef SIMVER PLUGINLDFLAGS = $(SHARED_FLAG) # <-- from Makefile else @@ -85,6 +91,7 @@ $(BUILDDIR)/%.rock: $(BUILDDIR)/%.o $(call PRINTS,LD $(@F))$(CC) $(PLUGINFLAGS) -o $(BUILDDIR)/$*.elf \ + $(BUILDDIR)/lang/lang_blackjack.o $(BUILDDIR)/lang/lang_chessbox.o $(BUILDDIR)/lang/lang_chopper.o\ $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(PLUGINLDFLAGS) 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,60 @@ +/*************************************************************************** + * __________ __ ___. + * 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 "pluginlib_lang.h" + +static unsigned char *plugin_language_buffer; +extern unsigned int num_strings[]; + +static int get_id_offset(enum user_type user) +{ + unsigned int i, offset = 0; + for(i=1; i < user; i++) { + offset += num_strings[i]; + } + return offset; +} + +void plugin_use_lang(const struct plugin_api* rb, enum user_type user, + const unsigned char* plugin_language_builtin) +{ + char path[MAX_PATH]; + unsigned char **plugin_language_strings; + size_t buffer_size; + size_t langsize = sizeof(char*) * num_strings[user]; + + if(langsize & 3) + langsize += (4 - (langsize & 3)); + + plugin_language_strings = (unsigned char**)rb->plugin_get_buffer(&buffer_size); + rb->lang_init_helper((unsigned char*)plugin_language_builtin, plugin_language_strings, + num_strings[user]); + rb->lang_set_plugin_access(plugin_language_strings, get_id_offset(user)); + + if (rb->global_settings->lang_file[0] && + rb->global_settings->lang_file[0] != 0xff) { + rb->snprintf(path, sizeof(path), LANG_DIR "/%s.lng", rb->global_settings->lang_file); + plugin_language_buffer = (unsigned char *)(plugin_language_strings + + langsize); + rb->lang_load_helper(path, plugin_language_builtin, plugin_language_strings, + plugin_language_buffer, user, buffer_size - langsize, + num_strings[user]); + } +} 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,32 @@ +/*************************************************************************** + * __________ __ ___. + * 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_plugin.h" + +#undef str +#define str(x) ((x < LANG_LAST_INDEX_IN_ARRAY) ? rb->language_strings[x] : \ + rb->lang_get_plugin_string(x)) + +void plugin_use_lang(const struct plugin_api* rb, enum user_type user, + const unsigned char* plugin_language_builtin); + +#endif /* _LIB_LANG_H_ */ Index: apps/plugins/lib/SOURCES =================================================================== --- apps/plugins/lib/SOURCES (revision 20189) +++ apps/plugins/lib/SOURCES (working copy) @@ -52,3 +52,4 @@ touchscreen.c #endif md5.c +pluginlib_lang.c Index: apps/plugins/chopper.c =================================================================== --- apps/plugins/chopper.c (revision 20189) +++ apps/plugins/chopper.c (working copy) @@ -21,6 +21,8 @@ ****************************************************************************/ #include "plugin.h" +#include "lang.h" +#include "lib/pluginlib_lang.h" #include "lib/xlcd.h" #include "lib/configfile.h" #include "lib/helper.h" @@ -45,7 +47,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) || \ @@ -53,19 +54,16 @@ #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) || \ @@ -74,40 +72,33 @@ (CONFIG_KEYPAD == SANSA_FUZE_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 @@ -116,19 +107,16 @@ #define QUIT BUTTON_POWER #define ACTION BUTTON_PLAY #define ACTION2 BUTTON_STOP -#define ACTIONTEXT "PLAY" #elif CONFIG_KEYPAD == CREATIVEZVM_PAD #define QUIT BUTTON_BACK #define ACTION BUTTON_UP #define ACTION2 BUTTON_MENU -#define ACTIONTEXT "UP" #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD #define QUIT BUTTON_POWER #define ACTION BUTTON_MENU #define ACTION2 BUTTON_SELECT -#define ACTIONTEXT "MENU" #else #error No keymap defined! @@ -144,10 +132,7 @@ #ifndef ACTION2 #define ACTION2 BUTTON_BOTTOMRIGHT #endif -#ifndef ACTIONTEXT -#define ACTIONTEXT "BOTTOMRIGHT" #endif -#endif #define NUMBER_OF_BLOCKS 8 #define NUMBER_OF_PARTICLES 3 @@ -549,17 +534,14 @@ #if LCD_DEPTH >= 2 rb->lcd_set_foreground(LCD_LIGHTGRAY); #endif - rb->splash(HZ, "Game Over"); + rb->splash(HZ, ID2P(P_LANG_CHOPPER_GAMEOVER)); if (score > highscore) { - char scoretext[30]; highscore = score; - rb->snprintf(scoretext, sizeof(scoretext), "New High Score: %d", - highscore); - rb->splash(HZ*2, scoretext); + rb->splashf(HZ*2, str(P_LANG_CHOPPER_HIGHSCORE), highscore); } - rb->splash(HZ/4, "Press " ACTIONTEXT " to continue"); + rb->splash(HZ/4, ID2P(P_LANG_CHOPPER_CONTINUE)); rb->lcd_update(); rb->lcd_set_drawmode(DRMODE_SOLID); @@ -669,21 +651,14 @@ rb->lcd_set_foreground(LCD_WHITE); #endif -#if LCD_WIDTH <= 128 - rb->snprintf(s, sizeof(s), "Dist: %d", score); -#else - rb->snprintf(s, sizeof(s), "Distance: %d", score); -#endif + rb->snprintf(s, sizeof(s), 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 - rb->snprintf(s, sizeof(s), "Hi: %d", highscore); -#else - rb->snprintf(s, sizeof(s), "Best: %d", highscore); -#endif + rb->snprintf(s, sizeof(s), 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); @@ -704,8 +679,10 @@ { "Steep", -1 }, }; - MENUITEM_STRINGLIST(menu,"Chopper Menu",NULL,"Start New Game","Resume Game", - "Level","Playback Control","Quit"); + MENUITEM_STRINGLIST(menu, ID2P(P_LANG_CHOPPER_MENUTITLE), NULL, + ID2P(P_LANG_CHOPPER_START),ID2P(P_LANG_CHOPPER_RESUME), + ID2P(P_LANG_CHOPPER_LEVEL),"Playback Control", + ID2P(P_LANG_CHOPPER_QUIT)); #ifdef HAVE_LCD_COLOR rb->lcd_set_foreground(LCD_WHITE); @@ -730,11 +707,12 @@ menu_quit=true; res = -1; } else if(menunum==0){ - rb->splash(HZ, "No game to resume"); + rb->splash(HZ, str(P_LANG_CHOPPER_NO_GAME)); } break; case 2: - rb->set_option("Level", &iLevelMode, INT, levels, 2, NULL); + rb->set_option(str(P_LANG_CHOPPER_LEVEL), &iLevelMode, INT, + levels, 2, NULL); break; case 3: playback_control(NULL); @@ -1009,6 +987,7 @@ (void)parameter; int ret; + plugin_use_lang(rb, USER_CHOPPER, chopper_language_builtin); rb->lcd_setfont(FONT_SYSFIXED); #if LCD_DEPTH > 1 rb->lcd_set_backdrop(NULL); Index: apps/plugins/blackjack.c =================================================================== --- apps/plugins/blackjack.c (revision 20189) +++ apps/plugins/blackjack.c (working copy) @@ -5,7 +5,7 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id: $ + * $Id$ * * Copyright (C) 2006 Tom Ross * @@ -20,6 +20,8 @@ ****************************************************************************/ #include "plugin.h" +#include "lang.h" +#include "lib/pluginlib_lang.h" #include "pluginbitmaps/card_deck.h" #include "pluginbitmaps/card_back.h" @@ -454,18 +456,20 @@ ******************************************************************************/ 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", str(P_LANG_BLACKJACK_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", str(P_LANG_BLACKJACK_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); @@ -473,13 +477,14 @@ 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, str(P_LANG_BLACKJACK_DEALER)); + rb->lcd_putsxy(0, y_loc, str(P_LANG_BLACKJACK_PLAYER)); + rb->snprintf(str, sizeof(str), "%s", str(P_LANG_BLACKJACK_TOTAL)); + rb->lcd_getstringsize(str, &w, &h); + rb->lcd_putsxy(LCD_WIDTH - w, y_loc, str); + rb->snprintf(str, sizeof(str), "%s", str(P_LANG_BLACKJACK_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); @@ -565,13 +570,16 @@ 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); + rb->talk_number(bj->dealer_cards[1].value, true); 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; @@ -682,11 +690,14 @@ 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++; } @@ -707,32 +718,42 @@ ******************************************************************************/ 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); - + + rb->talk_id(P_LANG_BLACKJACK_DEALER, true); + rb->talk_number(bj->dealer_total, true); + rb->talk_id(P_LANG_BLACKJACK_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 ", str(P_LANG_BLACKJACK_BUST)); + rb->talk_id(P_LANG_BLACKJACK_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 ", str(P_LANG_BLACKJACK_LOST)); + rb->talk_id(P_LANG_BLACKJACK_LOST, true); bj->player_money -= bj->current_bet; } else if (rValue == 2) { - rb->snprintf(str, sizeof(str), " Push "); + rb->snprintf(str, sizeof(str), " %s ", str(P_LANG_BLACKJACK_PUSH)); + rb->talk_id(P_LANG_BLACKJACK_PUSH, true); } else if (rValue == 3) { - rb->snprintf(str, sizeof(str), " You won! "); + rb->snprintf(str, sizeof(str), " %s ", str(P_LANG_BLACKJACK_WON)); + rb->talk_id(P_LANG_BLACKJACK_WON, true); bj->player_money+= bj->current_bet; } else { - rb->snprintf(str, sizeof(str), " Blackjack! "); + rb->snprintf(str, sizeof(str), " %s! ", str(P_LANG_BLACKJACK_TITLE)); + rb->talk_id(P_LANG_BLACKJACK_TITLE, true); bj->player_money += bj->current_bet * 3 / 2; } rb->lcd_getstringsize(str, &w, &h); @@ -742,7 +763,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), str(P_LANG_BLACKJACK_YOU_HAVE), bj->player_total); rb->lcd_getstringsize(str, &w, &h); rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2, str); #else @@ -889,7 +910,7 @@ 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, ID2P(P_LANG_BLACKJACK_SAVING_HIGH_SCORES)); blackjack_savescores(bj); } } @@ -899,16 +920,19 @@ ******************************************************************************/ static unsigned int blackjack_get_yes_no(char message[20]) { 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; @@ -916,21 +940,20 @@ 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) { @@ -939,6 +962,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; @@ -946,12 +970,12 @@ choice = BJ_QUIT; break; } - } - #if LCD_DEPTH > 1 - rb->lcd_set_foreground(FG_COLOR); - rb->lcd_set_background(BG_COLOR); + rb->lcd_set_foreground(FG_COLOR); + rb->lcd_set_background(BG_COLOR); #endif + } + return choice; } @@ -967,7 +991,7 @@ 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; @@ -986,42 +1010,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, str(P_LANG_BLACKJACK_BET_INC_SMALL)); + rb->lcd_puts(0, 4, str(P_LANG_BLACKJACK_BET_DEC_SMALL)); + rb->lcd_puts(0, 5, str(P_LANG_BLACKJACK_BET_INC_BIG)); + rb->lcd_puts(0, 6, str(P_LANG_BLACKJACK_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, - 8*h -3); + 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, - 8*h -3); - rb->lcd_putsxy(LCD_WIDTH/2 - 9*w, LCD_HEIGHT/2 - 4*h - 1, message); + 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 - 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, str(P_LANG_BLACKJACK_BET_INC_SMALL)); + rb->lcd_putsxy(LCD_WIDTH/2 - w / 2, LCD_HEIGHT/2 - 1, str(P_LANG_BLACKJACK_BET_DEC_SMALL)); + rb->lcd_putsxy(LCD_WIDTH/2 - w / 2, LCD_HEIGHT/2 + h, str(P_LANG_BLACKJACK_BET_INC_BIG)); + rb->lcd_putsxy(LCD_WIDTH/2 - w / 2, LCD_HEIGHT/2 + 2*h + 1, str(P_LANG_BLACKJACK_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); @@ -1076,15 +1087,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; } @@ -1095,7 +1107,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, + rb->talk_id(P_LANG_BLACKJACK_GET_BET, true); + bj->current_bet = blackjack_get_amount(str(P_LANG_BLACKJACK_GET_BET), 10, bj->player_money, bj->current_bet); } @@ -1115,7 +1128,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) + rb->talk_id(P_LANG_BLACKJACK_ASK_SPLIT, true); + if (blackjack_get_yes_no(str(P_LANG_BLACKJACK_ASK_SPLIT)) == 1) bj->split_status = 1; else { bj->split_status = 2; @@ -1133,13 +1147,15 @@ static unsigned int insurance(struct game_context* bj) { unsigned int insurance, max_amount; - insurance = blackjack_get_yes_no("Buy Insurance?"); + rb->talk_id(P_LANG_BLACKJACK_BUY_INSURANCE, false); + insurance = blackjack_get_yes_no(str(P_LANG_BLACKJACK_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); + rb->talk_id(P_LANG_BLACKJACK_HOW_MUCH, true); + insurance = blackjack_get_amount(str(P_LANG_BLACKJACK_HOW_MUCH), 0, max_amount, 0); redraw_board(bj); return insurance; } @@ -1148,7 +1164,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?"); + rb->talk_id(P_LANG_BLACKJACK_PLAY_AGAIN, true); + return blackjack_get_yes_no(str(P_LANG_BLACKJACK_PLAY_AGAIN)); } /***************************************************************************** @@ -1156,8 +1173,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; @@ -1171,8 +1187,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", str(P_LANG_BLACKJACK_TITLE)); + 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"); @@ -1315,13 +1332,13 @@ 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", str(P_LANG_BLACKJACK_HIGH_SCORE_TITLE)); rb->lcd_getstringsize(str, &w, &h); rb->lcd_putsxy((LCD_WIDTH-w)/2, 0, str); /* 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); } } @@ -1345,9 +1362,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; @@ -1376,6 +1393,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; @@ -1439,7 +1457,7 @@ !bj->asked_insurance) { temp_var = insurance(bj); if (bj->dealer_total == 21) { - rb->splash(HZ, "Dealer has blackjack"); + rb->splash(HZ, ID2P(P_LANG_BLACKJACK_DEALER_BLACKJACK)); bj->player_money += temp_var; bj->end_hand = true; breakout = true; @@ -1447,7 +1465,7 @@ finish_game(bj); } else { - rb->splash(HZ, "Dealer does not have blackjack"); + rb->splash(HZ, ID2P(P_LANG_BLACKJACK_DEALER_NO_BLACKJACK)); bj->player_money -= temp_var; breakout = true; redraw_board(bj); @@ -1472,6 +1490,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) { @@ -1506,13 +1525,13 @@ } } else if((signed int)bj->current_bet * 2 > bj->player_money) { - rb->splash(HZ, "Not enough money to double down."); + rb->splash(HZ, ID2P(P_LANG_BLACKJACK_NEED_MONEY_DOUBLE_DOWN)); redraw_board(bj); rb->lcd_update(); } break; case BJACK_RESUME: /* save and end game */ - rb->splash(HZ, "Saving game..."); + rb->splash(HZ, ID2P(P_LANG_BLACKJACK_SAVING_GAME)); blackjack_savegame(bj); /* fall through to BJACK_QUIT */ @@ -1544,20 +1563,23 @@ 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->snprintf(buf, sizeof(buf), " %s 1 ", str(P_LANG_BLACKJACK_SPLIT)); + rb->talk_id(P_LANG_BLACKJACK_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 >>= 1; rb->lcd_update_rect(LCD_WIDTH/2-w/2, LCD_HEIGHT/2-3*h/2, w,h); - 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 ", str(P_LANG_BLACKJACK_SPLIT)); + rb->talk_id(P_LANG_BLACKJACK_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); @@ -1617,9 +1639,9 @@ struct game_context bj; bool exit = false; unsigned int position; - char str[19]; (void)parameter; + plugin_use_lang(rb, USER_BLACKJACK, blackjack_language_builtin); #if LCD_DEPTH > 1 rb->lcd_set_backdrop(NULL); @@ -1629,18 +1651,20 @@ blackjack_loadscores(&bj); rb->lcd_setfont(FONT_SYSFIXED); + rb->talk_id(P_LANG_BLACKJACK_TITLE, false); while(!exit) { switch(blackjack(&bj)){ case BJ_LOSE: - rb->splash(HZ, "Not enough money to continue"); + rb->splash(HZ, ID2P(P_LANG_BLACKJACK_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->splash(HZ*2, str); + rb->talk_id(P_LANG_BLACKJACK_NEW_HIGH_SCORE, true); + rb->talk_number(position, true); + rb->splashf(HZ*2, str(P_LANG_BLACKJACK_NEW_HIGH_SCORE), position); } } break; @@ -1651,7 +1675,7 @@ case BJ_QUIT: if(bj.dirty) { - rb->splash(HZ, "Saving high scores..."); + rb->splash(HZ, ID2P(P_LANG_BLACKJACK_SAVING_HIGH_SCORES)); blackjack_savescores(&bj); } exit = true; Index: apps/lang/english.lang =================================================================== --- apps/lang/english.lang (revision 20189) +++ apps/lang/english.lang (working copy) @@ -12418,3 +12418,839 @@ speaker: "Enable Speaker" + + id: P_LANG_BLACKJACK_BET + desc: bet text + user: blackjack + + *: "Bet" + + + *: "Bet" + + + *: "Bet" + + + + id: P_LANG_BLACKJACK_DEALER + desc: dealer text + user: blackjack + + *: "Dealer" + + + *: "Dealer" + + + *: "Dealer" + + + + id: P_LANG_BLACKJACK_PLAYER + desc: player text + user: blackjack + + *: "Player" + + + *: "Player" + + + *: "Player" + + + + id: P_LANG_BLACKJACK_TOTAL + desc: total text + user: blackjack + + *: "Total" + + + *: "Total" + + + *: "Total" + + + + id: P_LANG_BLACKJACK_MONEY + desc: money text + user: blackjack + + *: "Money" + + + *: "Money" + + + *: "Money" + + + + id: P_LANG_BLACKJACK_BUST + desc: player busted + user: blackjack + + *: "Bust!" + + + *: "Bust!" + + + *: "Bust" + + + + id: P_LANG_BLACKJACK_LOST + desc: blackjack player lost + user: blackjack + + *: "Sorry, you lost." + + + *: "Sorry, you lost." + + + *: "Sorry, you lost" + + + + id: P_LANG_BLACKJACK_PUSH + desc: blackjack player tied + user: blackjack + + *: "Push" + + + *: "Push" + + + *: "Push" + + + + id: P_LANG_BLACKJACK_WON + desc: blackjack player won + user: blackjack + + *: "You won!" + + + *: "You won!" + + + *: "You won" + + + + id: P_LANG_BLACKJACK_TITLE + desc: blackjack text + user: blackjack + + *: "Blackjack" + + + *: "Blackjack" + + + *: "Blackjack" + + + + id: P_LANG_BLACKJACK_YOU_HAVE + desc: blackjack text that lets user know his total + user: blackjack + + *: none + player,recorder,fmrecorder,recorderv2,ondiofm,ondiosp: "You have: %d" + + + *: none + player,recorder,fmrecorder,recorderv2,ondiofm,ondiosp: "You have: %d" + + + *: none + player,recorder,fmrecorder,recorderv2,ondiofm,ondiosp: "You have" + + + + id: P_LANG_BLACKJACK_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_BLACKJACK_NEW_HIGH_SCORE + desc: player ranked in the top high scores + user: blackjack + + *: "New high score #%d!" + + + *: "New high score #%d!" + + + *: "New high score number" + + + + id: P_LANG_BLACKJACK_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_BLACKJACK_SAVING_GAME + desc: the user can save the game + user: blackjack + + *: "Saving game..." + + + *: "Saving game..." + + + *: "Saving game..." + + + + id: P_LANG_BLACKJACK_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_BLACKJACK_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_BLACKJACK_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_BLACKJACK_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_BLACKJACK_DEALER_BLACKJACK + desc: the dealer has a blackjack + user: blackjack + + *: "Dealer has blackjack" + + + *: "Dealer has blackjack" + + + *: "Dealer has blackjack" + + + + id: P_LANG_BLACKJACK_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_BLACKJACK_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_BLACKJACK_SPLIT + desc: used throughout splitting + user: blackjack + + *: "Split" + + + *: "Split" + + + *: "Split" + + + + id: P_LANG_BLACKJACK_ASK_SPLIT + desc: split the cards? + user: blackjack + + *: "Split?" + + + *: "Split?" + + + *: "Split?" + + + + id: P_LANG_BLACKJACK_BUY_INSURANCE + desc: asking if the user wants to buy insurance + user: blackjack + + *: "Buy Insurance?" + + + *: "Buy Insurance?" + + + *: "Buy Insurance?" + + + + id: P_LANG_BLACKJACK_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_BLACKJACK_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_BLACKJACK_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_BLACKJACK_PLAY_AGAIN + desc: does the user want to keep playing? + user: blackjack + + *: "Play again?" + + + *: "Play again?" + + + *: "Play again?" + + + + id: P_LANG_CHESSBOX_SAVING_POS + desc: saving the board positions + user: chessbox + + *: "Saving position" + + + *: "Saving position" + + + *: "Saving position" + + + + id: P_LANG_CHESSBOX_LOADING_POS + desc: loading the board positions + user: chessbox + + *: "Loading position" + + + *: "Loading position" + + + *: "Loading position" + + + + id: P_LANG_CHESSBOX_NO_GAME + desc: couldn't find any game + user: chessbox + + *: "No games found!" + + + *: "No games found!" + + + *: "No games found!" + + + + id: P_LANG_CHESSBOX_BEGINNING + desc: game beginning, no previous move + user: chessbox + + *: "At the begining of the game" + + + *: "At the begining of the game" + + + *: "At the begining of the game" + + + + id: P_LANG_CHESSBOX_END + desc: game end, no next move + user: chessbox + + *: "At the end of the game" + + + *: "At the end of the game" + + + *: "At the end of the game" + + + + id: P_LANG_CHESSBOX_CHECKMATE + desc: game is over + 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_TITLE + desc: in the chessbox menu + user: chessbox + + *: "Chessbox Menu" + + + *: "Chessbox Menu" + + + *: "Chessbox Menu" + + + + 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!" + + + + id: P_LANG_CHESSBOX_THINKING + desc: in the chessbox game viewer + user: chessbox + + *: "Thinking..." + + + *: "Thinking..." + + + *: "Thinking..." + + + + id: P_LANG_CHOPPER_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_CHOPPER_HIGHSCORE + desc: chopper new high score + user: chopper + + *: "New High Score: %d" + + + *: "New High Score: %d" + + + *: "New High Score" + + + + id: P_LANG_CHOPPER_DISTANCE + desc: distance label + user: chopper + + *: "Distance: %d" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Dist: %d" + + + *: "Distance: %d" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Dist: %d" + + + *: "Distance" + + + + id: P_LANG_CHOPPER_BESTSCORE + desc: distance label + user: chopper + + *: "Best: %d" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Hi: %d" + + + *: "Best: %d" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Hi: %d" + + + *: "Best score" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "High score" + + + + 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_RESUME + desc: chopper menu resume game + user: chopper + + *: "Resume Game" + + + *: "Resume Game" + + + *: "Resume 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_CHOPPER_QUIT + desc: chopper menu quit plugin + user: chopper + + *: "Quit" + + + *: "Quit" + + + *: "Quit" + + Index: apps/lang/espanol.lang =================================================================== --- apps/lang/espanol.lang (revision 20189) +++ apps/lang/espanol.lang (working copy) @@ -12172,3 +12172,573 @@ quickscreen: "" + + id: P_LANG_BLACKJACK_BET + desc: bet text + user: blackjack + + *: "Bet" + + + *: "Apuesta" + + + *: "Apuesta" + + + + id: P_LANG_BLACKJACK_DEALER + desc: dealer text + user: blackjack + + *: "Dealer" + + + *: "Banca" + + + *: "Banca" + + + + id: P_LANG_BLACKJACK_PLAYER + desc: player text + user: blackjack + + *: "Player" + + + *: "Jugador" + + + *: "Jugador" + + + + id: P_LANG_BLACKJACK_TOTAL + desc: total text + user: blackjack + + *: "Total" + + + *: "Total" + + + *: "Total" + + + + id: P_LANG_BLACKJACK_MONEY + desc: money text + user: blackjack + + *: "Money" + + + *: "Dinero" + + + *: "Dinero" + + + + id: P_LANG_BLACKJACK_BUST + desc: player busted + user: blackjack + + *: "Bust" + + + *: "Busto" + + + *: "Busto" + + + + id: P_LANG_BLACKJACK_LOST + desc: blackjack player lost + user: blackjack + + *: "Sorry, you lost" + + + *: "Lo siento, perdiste" + + + *: "Lo siento, perdiste" + + + + id: P_LANG_BLACKJACK_PUSH + desc: blackjack player tied + user: blackjack + + *: "Push" + + + *: "Empata" + + + *: "Empata" + + + + id: P_LANG_BLACKJACK_WON + desc: blackjack player won + user: blackjack + + *: "You won" + + + *: "Ganaste" + + + *: "Ganaste" + + + + id: P_LANG_BLACKJACK_TITLE + desc: blackjack text + user: blackjack + + *: "Blackjack" + + + *: "Blackjack" + + + *: "Blackjack" + + + + id: P_LANG_BLACKJACK_YOU_HAVE + desc: blackjack text that lets user know his total + user: blackjack + + *: none + player,recorder,fmrecorder,recorderv2,ondiofm,ondiosp: "You have: %d" + + + *: none + player,recorder,fmrecorder,recorderv2,ondiofm,ondiosp: "Tienes: %d" + + + *: none + player,recorder,fmrecorder,recorderv2,ondiofm,ondiosp: "Tienes" + + + + id: P_LANG_BLACKJACK_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_BLACKJACK_NEW_HIGH_SCORE + desc: player ranked in the top high scores + user: blackjack + + *: "New high score #%d!" + + + *: "Nueva puntaje alto #%d!" + + + *: "Nueva puntaje alto" + + + + id: P_LANG_BLACKJACK_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_BLACKJACK_SAVING_GAME + desc: the user can save the game + user: blackjack + + *: "Saving game..." + + + *: "Salvar el juego" + + + *: "Salvar el juego" + + + + id: P_LANG_BLACKJACK_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_BLACKJACK_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_BLACKJACK_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_BLACKJACK_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_BLACKJACK_DEALER_BLACKJACK + desc: the dealer has a blackjack + user: blackjack + + *: "Dealer has blackjack" + + + *: "Banca tiene blackjack" + + + *: "Banca tiene blackjack" + + + + id: P_LANG_BLACKJACK_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_BLACKJACK_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_BLACKJACK_SPLIT + desc: used throughout splitting + user: blackjack + + *: "Split" + + + *: "División" + + + *: "División" + + + + id: P_LANG_BLACKJACK_ASK_SPLIT + desc: split the cards? + user: blackjack + + *: "Split?" + + + *: "¿Dividir?" + + + *: "¿Dividir?" + + + + id: P_LANG_BLACKJACK_BUY_INSURANCE + desc: asking if the user wants to buy insurance + user: blackjack + + *: "Buy Insurance?" + + + *: "¿Comprar seguro?" + + + *: "¿Comprar seguro?" + + + + id: P_LANG_BLACKJACK_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_BLACKJACK_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_BLACKJACK_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_BLACKJACK_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: %d" + + + *: "Nueva Puntaje Alto: %d" + + + *: "Nueva Puntaje Alto: %d" + + + + 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: %d" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Hi: %d" + + + *: "Mejor: %d" + ondiofm,ondiosp,fmrecorder,recorder,recorderv2: "Hi: %d" + + + *: "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" + + \ No newline at end of file Index: apps/lang/lang.make =================================================================== --- apps/lang/lang.make (revision 20189) +++ apps/lang/lang.make (working copy) @@ -8,7 +8,7 @@ # LANGS := $(call preprocess, $(APPSDIR)/lang/SOURCES) -LANGOBJ := $(LANGS:$(ROOTDIR)/%.lang=$(BUILDDIR)/%.lng) +LANGOBJ := $(LANGS:$(ROOTDIR)/%.lang=$(BUILDDIR)/%.lng) build-langs LANG_O = $(BUILDDIR)/lang/lang_core.o CLEANOBJS += $(BUILDDIR)/lang/max_language_size.h $(BUILDDIR)/lang/lang* @@ -26,8 +26,15 @@ $(SILENT)for f in `cat $(BUILDDIR)/apps/features`; do feat="$$feat:$$f" ; done; \ perl -s $(TOOLSDIR)/genlang -p=$(BUILDDIR)/lang -t=$(MODELNAME)$$feat $< $(call PRINTS,CC lang_core.c)$(CC) $(CFLAGS) -c $(BUILDDIR)/lang/lang_core.c -o $@ + $(SILENT)touch $(BUILDDIR)/lang/lang-timestamp $(BUILDDIR)/%.lng : $(ROOTDIR)/%.lang $(BUILDDIR)/apps/genlang-features $(call PRINTS,GENLANG $(subst $(ROOTDIR)/,,$<)) $(SILENT)mkdir -p $(dir $@) $(SILENT)$(TOOLSDIR)/genlang -e=$(APPSDIR)/lang/english.lang -t=$(MODELNAME)`cat $(BUILDDIR)/apps/genlang-features` -i=$(TARGET_ID) -b=$@ $< + +build-langs: $(BUILDDIR)/lang/lang-timestamp $(patsubst %.c, %.o, $(wildcard $(BUILDDIR)/lang/lang_*.c)) + +$(BUILDDIR)/lang/lang_%.o: $(BUILDDIR)/lang/lang_%.c + $(SILENT)$(CC) $(CFLAGS) -c $< -o $@ + Index: apps/talk.c =================================================================== --- apps/talk.c (revision 20189) +++ apps/talk.c (working copy) @@ -178,6 +178,11 @@ } else { /* normal use of the first table */ + if (id > PLUGIN_DELIMITER) { /* id is a plugin string */ + id -= PLUGIN_DELIMITER + 1; + id += LANG_LAST_INDEX_IN_ARRAY; + } + if (id >= p_voicefile->id1_max) return NULL; /* must be newer than we have */ } Index: apps/plugin.c =================================================================== --- apps/plugin.c (revision 20189) +++ apps/plugin.c (working copy) @@ -39,6 +39,7 @@ #include "talk.h" #include "version.h" #include "storage.h" +#include "language.h" #if CONFIG_CHARGING #include "power.h" @@ -631,6 +632,15 @@ appsversion, /* new stuff at the end, sort into place next time the API gets incompatible */ + lang_init_helper, + lang_load_helper, + &language_strings[0], + lang_set_plugin_access, + lang_get_plugin_string, + talk_id, + talk_force_enqueue_next, + talk_idarray, + talk_number, }; int plugin_load(const char* plugin, const void* parameter) Index: apps/plugin.h =================================================================== --- apps/plugin.h (revision 20189) +++ apps/plugin.h (working copy) @@ -787,6 +787,19 @@ const char *appsversion; /* new stuff at the end, sort into place next time the API gets incompatible */ + void (*lang_init_helper)(unsigned char *builtin, unsigned char **dest, + int count); + int (*lang_load_helper)(const char *filename, const unsigned char *builtin, + unsigned char **dest, unsigned char *buffer, + unsigned int user, unsigned int max_lang_size, + unsigned int max); + unsigned char **language_strings; + void (*lang_set_plugin_access)(unsigned char** strings_ptr, unsigned int offset); + unsigned char *(*lang_get_plugin_string)(unsigned int id); + int (*talk_id)(int32_t id, bool enqueue); + void (*talk_force_enqueue_next)(void); + int (*talk_idarray)(const long *ids, bool enqueue); + int (*talk_number)(long n, bool enqueue); }; /* plugin header */