ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

localize.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/file.h"
00024 #include "common/str.h"
00025 #include "common/endian.h"
00026 
00027 #include "engines/grim/localize.h"
00028 #include "engines/grim/grim.h"
00029 #include "engines/grim/resource.h"
00030 
00031 namespace Grim {
00032 
00033 Localizer *g_localizer = nullptr;
00034 
00035 Localizer::Localizer() {
00036     // To avoid too wide lines further below, we just name these here.
00037     bool isAnyDemo = g_grim->getGameFlags() & ADGF_DEMO;
00038     bool isGrimDemo = g_grim->getGameType() == GType_GRIM && isAnyDemo;
00039     bool isGerman = g_grim->getGameLanguage() == Common::DE_DEU;
00040     bool isFrench = g_grim->getGameLanguage() == Common::FR_FRA;
00041     bool isItalian = g_grim->getGameLanguage() == Common::IT_ITA;
00042     bool isSpanish = g_grim->getGameLanguage() == Common::ES_ESP;
00043     bool isTranslatedGrimDemo = (isGerman || isFrench || isItalian || isSpanish) && isGrimDemo;
00044     bool isPS2 = g_grim->getGamePlatform() == Common::kPlatformPS2;
00045 
00046     if (isGrimDemo && !isTranslatedGrimDemo)
00047         return;
00048 
00049     Common::String filename;
00050     if (g_grim->getGameType() == GType_MONKEY4) {
00051         filename = "script.tab";
00052     } else {
00053         if (isTranslatedGrimDemo) {
00054             filename = "language.tab";
00055         } else {
00056             filename = "grim.tab";
00057         }
00058     }
00059 
00060     Common::SeekableReadStream *f = g_resourceloader->openNewStreamFile(filename);
00061     if (!f) {
00062         error("Localizer::Localizer: Unable to find localization information (%s)", filename.c_str());
00063         return;
00064     }
00065 
00066     int32 filesize = f->size();
00067 
00068     // Read in the data
00069     char *data = new char[filesize + 1];
00070     f->read(data, filesize);
00071     data[filesize] = '\0';
00072     delete f;
00073 
00074     // Explicitly white-list german demo, as it has a .tab-file
00075     if ((isTranslatedGrimDemo) || (!isAnyDemo && !isPS2)) {
00076         if (filesize < 4)
00077             error("%s to short: %i", filename.c_str(), filesize);
00078         switch (READ_BE_UINT32(data)) {
00079         case MKTAG('R','C','N','E'):
00080             // Decode the data
00081             if (g_grim->getGameType() == GType_MONKEY4) {
00082                 uint32 next = 0x16;
00083                 for (int i = 4; i < filesize; i++) {
00084                     next = next * 0x343FD + 0x269EC3;
00085                     data[i] ^= (int)(((((next >> 16) & 0x7FFF) / 32767.f) * 254) + 1);
00086                 }
00087             } else {
00088                 for (int i = 4; i < filesize; i++) {
00089                     data[i] ^= '\xdd';
00090                 }
00091             }
00092         case MKTAG('D', 'O', 'E', 'L'):
00093             break;
00094         default:
00095             error("Invalid magic reading %s: %08x", filename.c_str(), READ_BE_UINT32(data));
00096         }
00097     }
00098 
00099     char *nextline = data;
00100     Common::String last_entry;
00101     //Read file till end
00102     for (char *line = data + 4; line - data <= filesize; line = nextline + 1) {
00103         if (line == nullptr || nextline == nullptr) {
00104             break;
00105         }
00106 
00107         nextline = strchr(line, '\n');
00108         //if there is no next line we arrived the last one
00109         if (nextline == nullptr) {
00110             nextline = strchr(line, '\0');
00111         }
00112 
00113         //in grim we have to exit on first empty line else skip line
00114         if (*line == '\r') {
00115             if (g_grim->getGameType() == GType_GRIM) {
00116                 break;
00117             }
00118 
00119             nextline = strchr(line + 2, '\n');
00120             continue;
00121         }
00122 
00123         //EMI has an garbage line which should be ignored
00124         if (g_grim->getGameType() == GType_MONKEY4 && *line == '\x1A')
00125             continue;
00126 
00127         char *tab = strchr(line, '\t');
00128         //skip line if no tab found
00129         if (tab == nullptr) {
00130             continue;
00131         }
00132 
00133         if (tab > nextline) {
00134             Common::String cont = Common::String(line, nextline - line - 1);
00135             assert(last_entry != "");
00136             warning("Continuation line: \"%s\" = \"%s\" + \"%s\"", last_entry.c_str(), _entries[last_entry].c_str(), cont.c_str());
00137             _entries[last_entry] += cont;
00138         } else {
00139             _entries[last_entry = Common::String(line, tab - line)] = Common::String(tab + 1, (nextline - tab - 2));
00140         }
00141     }
00142     delete[] data;
00143 }
00144 
00145 Common::String Localizer::localize(const char *str) const {
00146     assert(str);
00147 
00148     const char *slash2;
00149 
00150     if (str[0] != '/' || str[0] == 0 || !(slash2 = strchr(str + 1, '/')))
00151         return str;
00152 
00153     Common::String key(str + 1, slash2 - str - 1);
00154     Common::StringMap::iterator it = _entries.find(key);
00155     if (it != _entries.end()) {
00156         return it->_value;
00157     } else {
00158         return slash2 + 1;
00159     }
00160 }
00161 
00162 } // end of namespace Grim


Generated on Sat Apr 20 2019 05:03:05 for ResidualVM by doxygen 1.7.1
curved edge   curved edge