aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
authorWalter van Niftrik2009-06-24 19:12:45 +0000
committerWalter van Niftrik2009-06-24 19:12:45 +0000
commit06144864e13fb2fb9ed32c68e8a612a68103317c (patch)
treec84961a1f0ebf5668ab2a45aa154893fdb7b219d /engines/sci/engine
parent6c049f6b29591262a30864d0570f2a6128f1594d (diff)
downloadscummvm-rg350-06144864e13fb2fb9ed32c68e8a612a68103317c.tar.gz
scummvm-rg350-06144864e13fb2fb9ed32c68e8a612a68103317c.tar.bz2
scummvm-rg350-06144864e13fb2fb9ed32c68e8a612a68103317c.zip
SCI: Partial support for dual-language games.
svn-id: r41833
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/kgraphics.cpp24
-rw-r--r--engines/sci/engine/script.cpp3
-rw-r--r--engines/sci/engine/state.cpp65
-rw-r--r--engines/sci/engine/state.h26
-rw-r--r--engines/sci/engine/vm.h6
5 files changed, 113 insertions, 11 deletions
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index a26c2dbcb1..2856c76aa3 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -621,10 +621,14 @@ reg_t kGraph(EngineState *s, int funct_nr, int argc, reg_t *argv) {
reg_t kTextSize(EngineState *s, int funct_nr, int argc, reg_t *argv) {
int width, height;
char *text = argv[1].segment ? (char *) kernel_dereference_bulk_pointer(s, argv[1], 0) : NULL;
+ const char *sep = NULL;
reg_t *dest = kernel_dereference_reg_pointer(s, argv[0], 4);
int maxwidth = (argc > 3) ? argv[3].toUint16() : 0;
int font_nr = argv[2].toUint16();
+ if ((argc > 4) && (argv[4].segment))
+ sep = (const char *)kernel_dereference_bulk_pointer(s, argv[4], 0);
+
if (maxwidth < 0)
maxwidth = 0;
@@ -636,7 +640,7 @@ reg_t kTextSize(EngineState *s, int funct_nr, int argc, reg_t *argv) {
return s->r_acc;
}
- GFX_ASSERT(gfxop_get_text_params(s->gfx_state, font_nr, text, maxwidth ? maxwidth : MAX_TEXT_WIDTH_MAGIC_VALUE,
+ GFX_ASSERT(gfxop_get_text_params(s->gfx_state, font_nr, s->strSplit(text, sep).c_str(), maxwidth ? maxwidth : MAX_TEXT_WIDTH_MAGIC_VALUE,
&width, &height, 0, NULL, NULL, NULL));
debugC(2, kDebugLevelStrings, "GetTextSize '%s' -> %dx%d\n", text, width, height);
@@ -1570,7 +1574,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
int font_nr = GET_SEL32V(obj, font);
reg_t text_pos = GET_SEL32(obj, text);
- char *text = text_pos.isNull() ? NULL : (char *)s->seg_manager->dereference(text_pos, NULL);
+ const char *text = text_pos.isNull() ? NULL : (char *)s->seg_manager->dereference(text_pos, NULL);
int view = GET_SEL32V(obj, view);
int cel = sign_extend_byte(GET_SEL32V(obj, cel));
int loop = sign_extend_byte(GET_SEL32V(obj, loop));
@@ -1584,7 +1588,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
switch (type) {
case K_CONTROL_BUTTON:
debugC(2, kDebugLevelGraphics, "drawing button %04x:%04x to %d,%d\n", PRINT_REG(obj), x, y);
- ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, text, font_nr,
+ ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, s->strSplit(text, NULL).c_str(), font_nr,
(int8)(state & kControlStateFramed), (int8)inverse, (int8)(state & kControlStateDisabled)));
break;
@@ -1593,7 +1597,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
debugC(2, kDebugLevelGraphics, "drawing text %04x:%04x to %d,%d, mode=%d\n", PRINT_REG(obj), x, y, mode);
- ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, text, font_nr, mode,
+ ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, s->strSplit(text).c_str(), font_nr, mode,
(int8)(!!(state & kControlStateDitherFramed)), (int8)inverse));
break;
@@ -1620,8 +1624,8 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
case K_CONTROL_CONTROL:
case K_CONTROL_CONTROL_ALIAS: {
- char **entries_list = NULL;
- char *seeker;
+ const char **entries_list = NULL;
+ const char *seeker;
int entries_nr;
int lsTop = GET_SEL32V(obj, lsTop) - text_pos.offset;
int list_top = 0;
@@ -1641,7 +1645,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
if (entries_nr) { // determine list_top, selection, and the entries_list
seeker = text;
- entries_list = (char**)malloc(sizeof(char *) * entries_nr);
+ entries_list = (const char**)malloc(sizeof(char *) * entries_nr);
for (i = 0; i < entries_nr; i++) {
entries_list[i] = seeker;
seeker += entry_size ;
@@ -2524,10 +2528,10 @@ reg_t kNewWindow(EngineState *s, int funct_nr, int argc, reg_t *argv) {
lWhite.alpha = 0;
lWhite.priority = -1;
lWhite.control = -1;
+ const char *title = argv[4 + argextra].segment ? kernel_dereference_char_pointer(s, argv[4 + argextra], 0) : NULL;
window = sciw_new_window(s, gfx_rect(x, y, xl, yl), s->titlebar_port->_font, fgcolor, bgcolor,
- s->titlebar_port->_font, lWhite, black, argv[4 + argextra].segment ?
- kernel_dereference_char_pointer(s, argv[4 + argextra], 0) : NULL, flags);
+ s->titlebar_port->_font, lWhite, black, title ? s->strSplit(title, NULL).c_str() : NULL, flags);
// PQ3 and SCI1.1 games have the interpreter store underBits implicitly
if (argextra)
@@ -3287,7 +3291,7 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) {
assert_primary_widget_lists(s);
- text_handle = gfxw_new_text(s->gfx_state, area, font_nr, text, halign, ALIGN_TOP, color0, *color1, bg_color, 0);
+ text_handle = gfxw_new_text(s->gfx_state, area, font_nr, s->strSplit(text).c_str(), halign, ALIGN_TOP, color0, *color1, bg_color, 0);
if (!text_handle) {
error("Display: Failed to create text widget");
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index a0bfdeddc9..fb094e00f6 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -200,6 +200,9 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(points);
FIND_SELECTOR(syncCue);
FIND_SELECTOR(syncTime);
+ FIND_SELECTOR(printLang);
+ FIND_SELECTOR(subtitleLang);
+ FIND_SELECTOR(parseLang);
}
void Kernel::dumpScriptObject(char *data, int seeker, int objsize) {
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index e35530700e..6bc9320050 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -126,4 +126,69 @@ uint16 EngineState::currentRoomNumber() const {
return script_000->locals_block->_locals[13].toUint16();
}
+kLanguage EngineState::charToLanguage(const char c) const {
+ switch (c) {
+ case 'F':
+ return K_LANG_FRENCH;
+ case 'S':
+ return K_LANG_SPANISH;
+ case 'I':
+ return K_LANG_ITALIAN;
+ case 'G':
+ return K_LANG_GERMAN;
+ case 'J':
+ case 'j':
+ return K_LANG_JAPANESE;
+ case 'P':
+ return K_LANG_PORTUGUESE;
+ default:
+ return K_LANG_NONE;
+ }
+}
+
+Common::String EngineState::getLanguageString(const char *str, kLanguage lang) const {
+ kLanguage secondLang = K_LANG_NONE;
+
+ const char *seeker = str;
+ while (*seeker) {
+ if ((*seeker == '%') || (*seeker == '#')) {
+ secondLang = charToLanguage(*(seeker + 1));
+
+ if (secondLang != K_LANG_NONE)
+ break;
+ }
+
+ seeker++;
+ }
+
+ if ((secondLang == K_LANG_JAPANESE) && (*(seeker + 1) == 'J')) {
+ // FIXME: Add Kanji support
+ lang = K_LANG_ENGLISH;
+ }
+
+ if (secondLang == lang)
+ return Common::String(seeker + 2);
+
+ if (seeker)
+ return Common::String(str, seeker - str);
+ else
+ return Common::String(str);
+}
+
+Common::String EngineState::strSplit(const char *str, const char *sep) {
+ EngineState *s = this;
+
+ kLanguage lang = (kLanguage)GET_SEL32V(s->game_obj, printLang);
+ kLanguage subLang = (kLanguage)GET_SEL32V(s->game_obj, subtitleLang);
+
+ Common::String retval = getLanguageString(str, lang);
+
+ if ((subLang != K_LANG_NONE) && (sep != NULL)) {
+ retval += sep;
+ retval += getLanguageString(str, subLang);
+ }
+
+ return retval;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index 15c1c2e63e..ecfb9fe6f7 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -88,6 +88,18 @@ enum {
SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE = 4
};
+/** Supported languages */
+enum kLanguage {
+ K_LANG_NONE = 0,
+ K_LANG_ENGLISH = 1,
+ K_LANG_FRENCH = 33,
+ K_LANG_SPANISH = 34,
+ K_LANG_ITALIAN = 39,
+ K_LANG_GERMAN = 49,
+ K_LANG_JAPANESE = 81,
+ K_LANG_PORTUGUESE = 351
+};
+
struct drawn_pic_t {
int nr;
int palette;
@@ -209,6 +221,16 @@ public:
uint16 currentRoomNumber() const;
+ /**
+ * Processes a multilanguage string based on the current language settings and
+ * returns a string that is ready to be displayed.
+ * @param str the multilanguage string
+ * @param sep optional seperator between main language and subtitle language,
+ * if NULL is passed no subtitle will be added to the returned string
+ * @return processed string
+ */
+ Common::String strSplit(const char *str, const char *sep = "\r----------\r");
+
/* Debugger data: */
Breakpoint *bp_list; /**< List of breakpoints */
int have_bp; /**< Bit mask specifying which types of breakpoints are used in bp_list */
@@ -239,6 +261,10 @@ public:
Kernel *_kernel;
EngineState *successor; /**< Successor of this state: Used for restoring */
+
+private:
+ kLanguage charToLanguage(const char c) const;
+ Common::String getLanguageString(const char *str, kLanguage lang) const;
};
/**
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index 379719a448..a3fabbe44b 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -198,7 +198,11 @@ struct selector_map_t {
Selector points; /**< Used by AvoidPath() */
Selector syncCue; /**< Used by DoSync() */
- Selector syncTime; /**< Used by DoSync() */
+ Selector syncTime;
+
+ Selector printLang; /**< Used for i18n */
+ Selector subtitleLang;
+ Selector parseLang;
};
// A reference to an object's variable.