/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "common/file.h" #include "common/textconsole.h" #include "cine/cine.h" #include "cine/various.h" namespace Cine { const char *const *failureMessages; const CommandeType *defaultActionCommand; const CommandeType *systemMenu; const CommandeType *confirmMenu; const char *const *otherMessages; const char *defaultCommandPreposition; const char *const *commandPrepositionTable; /** * Loads font data from the given file. * The number of characters used in the font varies between game versions: * 78 (Most PC, Amiga and Atari ST versions of Future Wars, but also Operation Stealth's Amiga demo), * 85 (All observed versions of German Future Wars (Amiga and PC), possibly Spanish Future Wars too), * 90 (Most PC, Amiga and Atari ST versions of Operation Stealth), * 93 (All observed versions of German Operation Stealth (Amiga and PC)). */ void loadTextData(const char *filename) { Common::File fileHandle; assert(filename); if (!fileHandle.open(filename)) error("loadTextData(): Cannot open file %s", filename); static const uint headerSize = 2 + 2; // The entry size (16-bit) and entry count (16-bit). const uint entrySize = fileHandle.readUint16BE(); // Observed values: 8. const uint entryCount = fileHandle.readUint16BE(); // Observed values: 624, 680, 720, 744. const uint fontDataSize = entryCount * entrySize; // Observed values: 4992, 5440, 5760, 5952. const uint numChars = entryCount / entrySize; // Observed values: 78, 85, 90, 93. const uint bytesPerChar = fontDataSize / numChars; // Observed values: 64. static const uint bytesPerRow = FONT_WIDTH / 2; // The input font data is 4-bit so it takes only half the space if (headerSize + fontDataSize != (uint)fileHandle.size()) { warning("loadTextData: file '%s' (entrySize = %d, entryCount = %d) is of incorrect size %d", filename, entrySize, entryCount, fileHandle.size()); } Common::Array source; source.resize(fontDataSize); fileHandle.read(source.begin(), fontDataSize); if (g_cine->getGameType() == Cine::GType_FW) { loadRelatedPalette(filename); } for (uint i = 0; i < numChars; i++) { gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][FONT_DATA], &source[i * bytesPerChar], bytesPerRow, FONT_HEIGHT); generateMask(g_cine->_textHandler.textTable[i][FONT_DATA], g_cine->_textHandler.textTable[i][FONT_MASK], FONT_WIDTH * FONT_HEIGHT, 0); } fileHandle.close(); } static const CharacterEntry fontParamTable_standard[NUM_FONT_CHARS] = { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {63, 1}, {69, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {68, 3}, {64, 3}, {65, 3}, { 0, 0}, { 0, 0}, {62, 2}, {74, 6}, {66, 1}, {67, 6}, {52, 6}, {53, 6}, {54, 6}, {55, 6}, {56, 6}, {57, 6}, {58, 6}, {59, 6}, {60, 6}, {61, 6}, {76, 3}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {75, 6}, { 0, 0}, { 0, 6}, //a { 1, 6}, { 2, 6}, { 3, 6}, { 4, 6}, { 5, 6}, { 6, 6}, { 7, 6}, { 8, 3}, { 9, 6}, {10, 6}, {11, 6}, {12, 7}, {13, 6}, {14, 6}, {15, 6}, {16, 6}, {17, 6}, {18, 6}, {19, 6}, {20, 6}, {21, 6}, {22, 7}, {23, 6}, {24, 6}, {25, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {26, 6}, //a {27, 6}, {28, 5}, {29, 6}, {30, 6}, {31, 5}, {32, 6}, {33, 6}, {34, 4}, {35, 4}, {36, 5}, {37, 3}, {38, 7}, {39, 6}, {40, 6}, {41, 6}, {42, 6}, {43, 6}, {44, 6}, {45, 6}, {46, 6}, {47, 6}, {48, 7}, {49, 6}, {50, 6}, {51, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {70, 6}, { 0, 0}, { 0, 0}, {72, 6}, { 0, 0}, {73, 5}, {77, 6}, { 0, 0}, {71, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {77, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }; static const CharacterEntry fontParamTable_alt[NUM_FONT_CHARS] = { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {63, 1}, {69, 5}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {68, 3}, {64, 3}, {65, 3}, { 0, 0}, { 0, 0}, {62, 2}, {74, 6}, {66, 1}, {67, 6}, {52, 6}, {53, 6}, {54, 6}, {55, 6}, {56, 6}, {57, 6}, {58, 6}, {59, 6}, {60, 6}, {61, 6}, {76, 3}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {75, 6}, { 0, 0}, { 0, 6}, { 1, 6}, { 2, 6}, { 3, 6}, { 4, 6}, { 5, 6}, { 6, 6}, { 7, 6}, { 8, 3}, { 9, 6}, {10, 6}, {11, 6}, {12, 7}, {13, 6}, {14, 6}, {15, 6}, {16, 6}, {17, 6}, {18, 6}, {19, 6}, {20, 6}, {21, 6}, {22, 7}, {23, 6}, {24, 6}, {25, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {26, 6}, {27, 6}, {28, 5}, {29, 6}, {30, 6}, {31, 5}, {32, 6}, {33, 6}, {34, 4}, {35, 4}, {36, 5}, {37, 3}, {38, 7}, {39, 6}, {40, 6}, {41, 6}, {42, 6}, {43, 6}, {44, 6}, {45, 6}, {46, 6}, {47, 6}, {48, 7}, {49, 6}, {50, 6}, {51, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {82, 6}, {70, 6}, { 0, 0}, {78, 6}, {72, 6}, { 0, 0}, {73, 5}, {77, 6}, {79, 6}, {71, 6}, {80, 4}, { 0, 0}, { 0, 0}, {78, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {81, 6}, { 0, 0}, { 0, 0}, {77, 6}, {83, 6}, {81, 6}, {82, 6}, { 0, 0}, { 0, 0}, { 0, 0}, {84, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {84, 6}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }; void initLanguage(Common::Language lang) { static const char *const failureMessages_EN[] = { // EXAMINE "I don't see anything unusual.", "There's nothing of interest here.", "This isn't particularly interesting.", "You won't find anything.", // TAKE "I can't take that.", "I find it difficult.", "I don't see what I am supposed to take.", "I have difficulty in following you.", // INVENTORY "There's no point.", "You have better things to do.", "Come on, don't let's waste any time.", "That doesn't seem to me to be a good idea.", // USE "I don't see why I should do that.", "It's had no effect whatsoever.", "It won't produce any results.", "Try and find something else.", // OPERATE "It doesn't work.", "Let suppose you are trying and don't let's mention it again.", "Nothing happens.", "You have better things to do.", // SPEAK "No answer.", "More action , less talking !", "I'd be very surprised if you got an answer", "A wall of silence ..." }; static const CommandeType defaultActionCommand_EN[] = { "EXAMINE", "TAKE", "INVENTORY", "USE", "OPERATE", "SPEAK", "NOACTION" }; static const char *const commandPrepositionTable_EN[] = { "", // EXAMINE "", // TAKE "", // INVENTORY "on", // USE "", // OPERATE "to", // SPEAK "" // NOACTION }; static const CommandeType systemMenu_EN[] = { "Pause", "Restart Game", "Quit", "Backup Drive is A:", "Restore game", "Save game" }; static const char *const otherMessages_EN[] = { "This backup doesn't exist ...", "Could not create save file ...", "PAUSE", "Loading | %s", "Loading canceled ...", "No backup in the drive...", "Please enter the backup name" }; static const CommandeType confirmMenu_EN[] = { "Ok, go ahead ...", "Absolutely Not!" }; static const char *const failureMessages_FR[] = { // EXAMINER "Je ne vois rien de special.", "Il n'y a rien d'int\x82ressant.", "Cela pr\x82sente peu d'int\x82r\x88ts.", "Vous ne trouvez rien.", // PRENDRE "Je ne peux pas prendre cela.", "Cela me semble difficile", "Je ne vois pas ce qu'il y a \x85 prendre", "j'ai du mal \x85 vous suivre.", // INVENTAIRE "C'est inutile", "Vous avez mieux \x85 faire", "Allons, ne perdons pas de temps", "\x87""a ne me semble pas \x88tre une bonne id\x82""e", // UTILISER "Je ne vois pas pourquoi je ferais cela.", "C'est absolument sans effets", "Cela n'amenerait \x85 rien", "Essayez de trouver autre chose.", // ACTIONNER "Ca ne marche pas", "Supposons que vous essayez et n'en parlons plus.", "Rien n'y fait.", "Vous avez mieux \x85 faire.", // PARLER "Vous lui parlez . Sans r\x82ponse.", "Plus d'actes et moins de Paroles !", "Je serais bien surpris si vous obteniez une r\x82ponse.", "Un mur de silence ..." }; static const CommandeType defaultActionCommand_FR[] = { "EXAMINER", "PRENDRE", "INVENTAIRE", "UTILISER", "ACTIONNER", "PARLER", "NOACTION" }; static const char *const commandPrepositionTable_FR[] = { "", // EXAMINER "", // PRENDRE "", // INVENTAIRE "sur", // UTILISER "", // ACTIONNER "a", // PARLER "" // NOACTION }; static const CommandeType systemMenu_FR[] = { "Pause", "Nouvelle partie", "Quitter", "Lecteur de Svg. A:", "Charger une partie", "Sauver la partie" }; static const CommandeType confirmMenu_FR[] = { "Ok , Vas-y ...", "Surtout Pas !" }; static const char *const otherMessages_FR[] = { "Cette sauvegarde n'existe pas ...", "Could not create save file ...", // "PAUSE", "Sauvegarde de | %s", "Sauvegarde Annul\x82""e ...", "Aucune sauvegarde dans le lecteur ...", "Veuillez entrer le Nom de la Sauvegarde ." }; static const char *const failureMessages_ES[] = { // EXAMINE "No veo nada especial", "No hay nada interesante", "No tiene mucho interes", "No encuentras nada", // TAKE "No puedo coger eso", "Eso parece dificil", "No veo nada mas para coger", "No he debido entenderte", // INVENTORY "Es inutil", "Tienes algo mejor que hacer", "Vamos. No perdamos tiempo", "Esa no es una buena idea", // USE "No veo porque hacerlo", "No ha tenido efecto", "Eso no arreglara nada", "Intenta encontrar otra cosa", // OPERATE "Eso no funciona", "Suponfamos que pruebas y no hablamos mas", "Nada ha pasado", "Tienes cosas mejores que hacer", // SPEAK "Le hablas. Sin respuesta.", "Menos hablar y mas trabajar", "Me sorprenderia si tuvieras otra repuesta", "Un muro de silencio ..." }; static const CommandeType defaultActionCommand_ES[] = { "EXAMINAR", "COGER", "INVENTARIO", "USAR", "ACCIONAR", "HABLAR", "NOACTION" }; static const char *const commandPrepositionTable_ES[] = { "", // EXAMINAR "", // COGER "", // INVENTARIO "donde", // USAR "", // ACCIONAR "a", // HABLAR "" // NOACTION }; static const CommandeType systemMenu_ES[] = { "Pause", "Nueva partida", "Abandonar", "Unidad grabar. A:", "Cargar una partida", "Salvar la partida" }; static const CommandeType confirmMenu_ES[] = { "Ok , Vas a ...", "Nade de nada !" }; static const char *const otherMessages_ES[] = { "Esta granacion no existe", "Could not create save file ...", // "PAUSE", "Gabacion de| %s", "Rrabacion anulada", "No hay partidas grabadas en este disco...", "Teclea el nombre de la partida grabada" }; static const char *const failureMessages_DE[] = { // EXAMINE "Ich sehe nichts Besonderes", "Es gibt hier nichts Interessantes", "Das ist nicht besonders interessant", "Sie werden nichts finden", // TAKE "Ich Kann das nicht nehmen", "Das finde ich schwierig'", "Ich wei\x9e nicht, was ich nehmen soll", "Ich kann Ihnen nicht folgen", // INVENTORY "Das bringt nichts", "Sie haben wirklich was Besseres zu tun", "Los, wir sollten keine Zeit verschwenden", "Das scheint mir eine gute Idee zu sein", // USE "Ich wei\x9e nicht, warum ich das tun soll", "Es hat so oder so nichts begracht", "Davon haben wir nichts", "Versuchen Sie, etwas anderes zu finden", // OPERATE "Es geht nicht", "Sagen wir, das war ein Versuch, und reden wir nicht mehr dr\x81""ber", "Nichts passiert", "Sie haben wirklich was Besseres zu tun", // SPEAK "Sie sprechen m it ihm. Keine Antwort", "Nicht reden, sondern handeln!", "Wenn Sie eine Antwork bek\x84men, w\x81rde es mich sehr wundern", "Eine Wand des Schweigens..." }; static const CommandeType defaultActionCommand_DE[] = { "Pr\x81""fe", // FIXME? The third letter should be Latin Small Letter U with diaeresis "Nimm", "Bestand", "Benutze", "Bet\x84tige", // FIXME? The fourth letter should be Latin Small Letter A with diaeresis "Sprich", "NOACTION" }; static const char *const commandPrepositionTable_DE[] = { "", // Prufe "", // Nimm "", // Bestand "gegen", // Benutze "", // Betatige "a", // Sprich "" // NOACTION }; static const CommandeType systemMenu_DE[] = { "Pause", "Spiel Neu Starten", "Lassen", "Backuplaufwerk A:", "Spiel Laden", "Spiel Speichern" }; static const CommandeType confirmMenu_DE[] = { "Gut, Weitermachen", "Absolut Nicht!" }; static const char *const otherMessages_DE[] = { "Diese Sicherungskopie gibt es nicht", "Could not create save file ...", // "PAUSE", "Er L\x84""dt | %s", "Ladevorgang Abgebrochen...", "Kein Backup im Laufwerk...", "Geben Sie den Namen|der Sicherungsdiskette ein" }; static const char *const failureMessages_IT[] = { // EXAMINE "Non vedo nula di speciale", "Non c'\x8a niente di interessante", "E' di poco interesse", "Non trovate nulla", // TAKE "Non poso prendere quello", "Quello mi sembra difficile", "Non vedo cosa ci sia da prendere", "Faccio fatica a seguirvi", // INVENTORY "E' inutile", "Avete di meglio da fare", "Allora, no perdiamo tempo", "Non mi pare che sia una buona idea", // USE "Non vedo perch\x82 dovrei farlo", "E' assolutamente privo di effetti", "Cio non portera a nulla", "Provate a trovare qualcosa d'altro", // OPERATE "Non funziona", "Supponiamo che voi proviate e non ne parliamo piu", "Niente di fatto", "Avete di meglio da fare", // SPEAK "Gli parlate. Senza risposta", "Piu fatti e meno parole", "Sarei sorpreso se voi otterreste una risposta", "Un muro di silenzio ..." }; static const CommandeType defaultActionCommand_IT[] = { "ESAMINARE", "PRENDERE", "INVENTARIO", "UTILIZZARE", "AZIONARE", "PARLARE", "NOACTION" }; static const char *const commandPrepositionTable_IT[] = { "", // ESAMINARE "", // PRENDERE "", // INVENTARIO "su", // UTILIZZARE "", // AZIONARE "a", // PARLARE "" // NOACTION }; static const CommandeType systemMenu_IT[] = { "Pausa", "Parte nuova", "Quit", "Drive di svg. A:", "Caricare una parte", "Salvare una parte" }; static const CommandeType confirmMenu_IT[] = { "Ok, vacci ...", "Supratutto non!" }; static const char *const otherMessages_IT[] = { "Questo salvataggio non esiste...", "Could not create save file ...", // "PAUSE", "Caricamento di| %s", "Caricamento annullato...", "Nessun salvataggio su questo disco...", "Vogliate accedere con il nome del salvataggio" }; switch (lang) { case Common::FR_FRA: failureMessages = failureMessages_FR; defaultActionCommand = defaultActionCommand_FR; systemMenu = systemMenu_FR; confirmMenu = confirmMenu_FR; otherMessages = otherMessages_FR; defaultCommandPreposition = commandPrepositionTable_FR[3]; commandPrepositionTable = commandPrepositionTable_FR; break; case Common::ES_ESP: failureMessages = failureMessages_ES; defaultActionCommand = defaultActionCommand_ES; systemMenu = systemMenu_ES; confirmMenu = confirmMenu_ES; otherMessages = otherMessages_ES; defaultCommandPreposition = commandPrepositionTable_ES[3]; commandPrepositionTable = commandPrepositionTable_ES; break; case Common::DE_DEU: failureMessages = failureMessages_DE; defaultActionCommand = defaultActionCommand_DE; systemMenu = systemMenu_DE; confirmMenu = confirmMenu_DE; otherMessages = otherMessages_DE; defaultCommandPreposition = commandPrepositionTable_DE[3]; commandPrepositionTable = commandPrepositionTable_DE; break; case Common::IT_ITA: failureMessages = failureMessages_IT; defaultActionCommand = defaultActionCommand_IT; systemMenu = systemMenu_IT; confirmMenu = confirmMenu_IT; otherMessages = otherMessages_IT; defaultCommandPreposition = commandPrepositionTable_IT[3]; commandPrepositionTable = commandPrepositionTable_IT; break; default: failureMessages = failureMessages_EN; defaultActionCommand = defaultActionCommand_EN; systemMenu = systemMenu_EN; confirmMenu = confirmMenu_EN; otherMessages = otherMessages_EN; defaultCommandPreposition = commandPrepositionTable_EN[3]; commandPrepositionTable = commandPrepositionTable_EN; break; } if (g_cine->getFeatures() & GF_ALT_FONT) { // Copy alternative font parameter table to the current font parameter table Common::copy(fontParamTable_alt, fontParamTable_alt + NUM_FONT_CHARS, g_cine->_textHandler.fontParamTable); } else { // Copy standard font parameter to the current font parameter table Common::copy(fontParamTable_standard, fontParamTable_standard + NUM_FONT_CHARS, g_cine->_textHandler.fontParamTable); } } void loadErrmessDat(const char *fname) { Common::File in; in.open(fname); if (in.isOpen()) { // FIXME - This can leak in some situations in Operation Stealth // Engine Restart - multiple allocations with no free? char **ptr = (char **)malloc(sizeof(char *) * 6 * 4 + 60 * 6 * 4); for (int i = 0; i < 6 * 4; i++) { ptr[i] = (char *)ptr + (sizeof(char *) * 6 * 4) + 60 * i; in.read(ptr[i], 60); } failureMessages = const_cast(ptr); in.close(); } else { error("Cannot open file %s for reading", fname); } } void freeErrmessDat() { free(const_cast(failureMessages)); failureMessages = 0; } void loadPoldatDat(const char *fname) { Common::File in; in.open(fname); if (in.isOpen()) { for (int i = 0; i < NUM_FONT_CHARS; i++) { g_cine->_textHandler.fontParamTable[i].characterIdx = in.readByte(); g_cine->_textHandler.fontParamTable[i].characterWidth = in.readByte(); } in.close(); } else { error("Cannot open file %s for reading", fname); } } /** * Fit a substring of text into one line of fixed width text box * @param str Text to fit * @param maxWidth Text box width * @param[out] words Number of words that fit * @param[out] width Total width of nonblank characters that fit * @return Length of substring which fits */ int fitLine(const char *str, int maxWidth, int &words, int &width) { int i, bkpWords = 0, bkpWidth = 0, bkpLen = 0; int charWidth = 0, fullWidth = 0; words = 0; width = 0; for (i = 0; str[i]; i++) { if (str[i] == 0x7C) { i++; break; } else if (str[i] == ' ') { charWidth = 5; bkpWords = words++; bkpWidth = width; bkpLen = i + 1; } else { charWidth = g_cine->_textHandler.fontParamTable[(unsigned char)str[i]].characterWidth + 1; width += charWidth; } if (!charWidth) { continue; } if (fullWidth + charWidth < maxWidth) { fullWidth += charWidth; } else if (fullWidth) { words = bkpWords; width = bkpWidth; i = bkpLen; break; } } return i; } } // End of namespace Cine