/* ScummVM - Scumm Interpreter * Copyright (C) 2001-2005 The ScummVM project * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * $Header$ */ #include "stdafx.h" #include "scumm/charset.h" #include "scumm/scumm.h" #include "scumm/nut_renderer.h" #include "scumm/util.h" #include "scumm/wiz_he.h" namespace Scumm { void ScummEngine::loadCJKFont() { Common::File fp; _useCJKMode = false; if (_language == Common::JA_JPN && _version <= 5) { // FM-TOWNS v3 / v5 Kanji int numChar = 256 * 32; _2byteWidth = 16; _2byteHeight = 16; // use FM-TOWNS font rom, since game files don't have kanji font resources if (fp.open("fmt_fnt.rom", Common::File::kFileReadMode)) { _useCJKMode = true; debug(2, "Loading FM-TOWNS Kanji rom"); _2byteFontPtr = new byte[((_2byteWidth + 7) / 8) * _2byteHeight * numChar]; fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar); fp.close(); } } else if (_language == Common::KO_KOR || _language == Common::JA_JPN || _language == Common::ZH_TWN) { int numChar = 0; const char *fontFile = NULL; switch (_language) { case Common::KO_KOR: fontFile = "korean.fnt"; numChar = 2350; break; case Common::JA_JPN: fontFile = (_gameId == GID_DIG) ? "kanji16.fnt" : "japanese.fnt"; numChar = 1024; //FIXME break; case Common::ZH_TWN: if (_gameId == GID_CMI) { fontFile = "chinese.fnt"; numChar = 1; //FIXME } break; default: break; } if (fontFile && fp.open(fontFile)) { debug(2, "Loading CJK Font"); _useCJKMode = true; fp.seek(2, SEEK_CUR); _2byteWidth = fp.readByte(); _2byteHeight = fp.readByte(); _2byteFontPtr = new byte[((_2byteWidth + 7) / 8) * _2byteHeight * numChar]; fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar); fp.close(); } else { warning("Couldn't load any font"); } } } static int SJIStoFMTChunk(int f, int s) { //converts sjis code to fmt font offset enum { KANA = 0, KANJI = 1, EKANJI = 2 }; int base = s - ((s + 1) % 32); int c = 0, p = 0, chunk_f = 0, chunk = 0, cr = 0, kanjiType = KANA; if (f >= 0x81 && f <= 0x84) kanjiType = KANA; if (f >= 0x88 && f <= 0x9f) kanjiType = KANJI; if (f >= 0xe0 && f <= 0xea) kanjiType = EKANJI; if ((f > 0xe8 || (f == 0xe8 && base >= 0x9f)) || (f > 0x90 || (f == 0x90 && base >= 0x9f))) { c = 48; //correction p = -8; //correction } if (kanjiType == KANA) {//Kana chunk_f = (f - 0x81) * 2; } else if (kanjiType == KANJI) {//Standard Kanji p += f - 0x88; chunk_f = c + 2 * p; } else if (kanjiType == EKANJI) {//Enhanced Kanji p += f - 0xe0; chunk_f = c + 2 * p; } // Base corrections if (base == 0x7f && s == 0x7f) base -= 0x20; if (base == 0x9f && s == 0xbe) base += 0x20; if (base == 0xbf && s == 0xde) base += 0x20; //if (base == 0x7f && s == 0x9e) // base += 0x20; switch (base) { case 0x3f: cr = 0; //3f if (kanjiType == KANA) chunk = 1; else if (kanjiType == KANJI) chunk = 31; else if (kanjiType == EKANJI) chunk = 111; break; case 0x5f: cr = 0; //5f if (kanjiType == KANA) chunk = 17; else if (kanjiType == KANJI) chunk = 47; else if (kanjiType == EKANJI) chunk = 127; break; case 0x7f: cr = -1; //80 if (kanjiType == KANA) chunk = 9; else if (kanjiType == KANJI) chunk = 63; else if (kanjiType == EKANJI) chunk = 143; break; case 0x9f: cr = 1; //9e if (kanjiType == KANA) chunk = 2; else if (kanjiType == KANJI) chunk = 32; else if (kanjiType == EKANJI) chunk = 112; break; case 0xbf: cr = 1; //be if (kanjiType == KANA) chunk = 18; else if (kanjiType == KANJI) chunk = 48; else if (kanjiType == EKANJI) chunk = 128; break; case 0xdf: cr = 1; //de if (kanjiType == KANA) chunk = 10; else if (kanjiType == KANJI) chunk = 64; else if (kanjiType == EKANJI) chunk = 144; break; default: warning("Invaild Char! f %x s %x base %x c %d p %d", f, s, base, c, p); return 0; } debug(6, "Kanji: %c%c f 0x%x s 0x%x base 0x%x c %d p %d chunk %d cr %d index %d", f, s, f, s, base, c, p, chunk, cr, ((chunk_f + chunk) * 32 + (s - base)) + cr); return ((chunk_f + chunk) * 32 + (s - base)) + cr; } byte *ScummEngine::get2byteCharPtr(int idx) { switch (_language) { case Common::KO_KOR: idx = ((idx % 256) - 0xb0) * 94 + (idx / 256) - 0xa1; break; case Common::JA_JPN: idx = SJIStoFMTChunk((idx % 256), (idx / 256)); break; case Common::ZH_TWN: default: idx = 0; } return _2byteFontPtr + ((_2byteWidth + 7) / 8) * _2byteHeight * idx; } #pragma mark - CharsetRenderer::CharsetRenderer(ScummEngine *vm) { _nextLeft = 0; _nextTop = 0; _top = 0; _left = 0; _startLeft = 0; _right = 0; _color = 0; _dropShadow = false; _center = false; _hasMask = false; _textScreenID = kMainVirtScreen; _ignoreCharsetMask = false; _blitAlso = false; _firstChar = false; _disableOffsX = false; _vm = vm; _curId = 0; const int size = _vm->_screenWidth * _vm->_screenHeight; _textSurface.pixels = malloc(size); _textSurface.w = _vm->_screenWidth; _textSurface.h = _vm->_screenHeight; _textSurface.pitch = _vm->_screenWidth; _textSurface.bytesPerPixel = 1; clearTextSurface(); } CharsetRenderer::~CharsetRenderer() { free(_textSurface.pixels); } void CharsetRendererCommon::setCurID(byte id) { checkRange(_vm->_numCharsets - 1, 0, id, "Printing with bad charset %d"); _curId = id; _fontPtr = _vm->getResourceAddress(rtCharset, id); if (_fontPtr == 0) error("CharsetRendererCommon::setCurID: charset %d not found!", id); if (_vm->_version == 4) _fontPtr += 17; else _fontPtr += 29; } void CharsetRendererV3::setCurID(byte id) { checkRange(_vm->_numCharsets - 1, 0, id, "Printing with bad charset %d"); _curId = id; _fontPtr = _vm->getResourceAddress(rtCharset, id); if (_fontPtr == 0) error("CharsetRendererCommon::setCurID: charset %d not found!", id); _numChars = _fontPtr[4]; _fontPtr += 6; _widthTable = _fontPtr; _fontPtr += _numChars; } int CharsetRendererCommon::getFontHeight() { if (_vm->_useCJKMode) return MAX(_vm->_2byteHeight + 1, (int)_fontPtr[1]); else return _fontPtr[1]; } int CharsetRendererV3::getFontHeight() { if (_vm->_useCJKMode) return MAX(_vm->_2byteHeight + 1, 8); else return 8; } // do spacing for variable width old-style font int CharsetRendererClassic::getCharWidth(byte chr) { if (chr >= 0x80 && _vm->_useCJKMode) return _vm->_2byteWidth / 2; int spacing = 0; int offs = READ_LE_UINT32(_fontPtr + chr * 4 + 4); if (offs) { spacing = _fontPtr[offs] + (signed char)_fontPtr[offs + 2]; } return spacing; } int CharsetRenderer::getStringWidth(int arg, const byte *text) { int pos = 0; int width = 1; byte chr; int oldID = getCurID(); int code = (_vm->_heversion >= 80) ? 127 : 64; while ((chr = text[pos++]) != 0) { if (_vm->_heversion >= 72 && chr == code) { chr = text[pos++]; if (chr == 84) { // Strings of speech offset/size while (chr != code) chr = text[pos++]; continue; } if (chr == 119) // 'Wait' break; if (chr == 104|| chr == 110) // 'Newline' break; } else if (chr == '@') continue; if (chr == 0xD) break; if (chr == 254 || chr == 255) { //process in LE if (chr == 254 && checkKSCode(text[pos], chr) && _vm->_useCJKMode) { goto loc_avoid_ks_fe; } chr = text[pos++]; if (chr == 3) // 'WAIT' break; if (chr == 8) { // 'Verb on next line' if (arg == 1) break; while (text[pos++] == ' ') ; continue; } if (chr == 10 || chr == 21 || chr == 12 || chr == 13) { pos += 2; continue; } if (chr == 9 || chr == 1 || chr == 2) // 'Newline' break; if (chr == 14) { int set = text[pos] | (text[pos + 1] << 8); pos += 2; setCurID(set); continue; } } loc_avoid_ks_fe: if ((chr & 0x80) && _vm->_useCJKMode) { pos++; width += _vm->_2byteWidth; } else { width += getCharWidth(chr); } } setCurID(oldID); return width; } void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) { int lastspace = -1; int curw = 1; byte chr; int oldID = getCurID(); int code = (_vm->_heversion >= 80) ? 127 : 64; while ((chr = str[pos++]) != 0) { if (_vm->_heversion >= 72 && chr == code) { chr = str[pos++]; if (chr == 84) { // Strings of speech offset/size while (chr != code) chr = str[pos++]; continue; } if (chr == 119) // 'Wait' break; if (chr == 110) { // 'Newline' curw = 1; continue; } if (chr == 104) // 'Don't terminate with \n' break; } else if (chr == '@') continue; if (chr == 254 || chr == 255) { //process in LE if (chr == 254 && checkKSCode(str[pos], chr) && _vm->_useCJKMode) { goto loc_avoid_ks_fe; } chr = str[pos++]; if (chr == 3) // 'Wait' break; if (chr == 8) { // 'Verb on next line' if (a == 1) { curw = 1; } else { while (str[pos] == ' ') str[pos++] = '@'; } continue; } if (chr == 10 || chr == 21 || chr == 12 || chr == 13) { pos += 2; continue; } if (chr == 1) { // 'Newline' curw = 1; continue; } if (chr == 2) // 'Don't terminate with \n' break; if (chr == 14) { int set = str[pos] | (str[pos + 1] << 8); pos += 2; setCurID(set); continue; } } if (chr == ' ') lastspace = pos - 1; loc_avoid_ks_fe: if ((chr & 0x80) && _vm->_useCJKMode) { pos++; curw += _vm->_2byteWidth; } else { curw += getCharWidth(chr); } if (lastspace == -1) continue; if (curw > maxwidth) { str[lastspace] = 0xD; curw = 1; pos = lastspace + 1; lastspace = -1; } } setCurID(oldID); } #ifdef __PALM_OS__ static byte *englishCharsetDataV2; static byte *germanCharsetDataV2; static byte *frenchCharsetDataV2; static byte *italianCharsetDataV2; static byte *spanishCharsetDataV2; #else // English Zak font static byte englishCharsetDataV2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0C, 0x18, 0x3E, 0x03, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x7C, 0xC0, 0x00, 0x00, 0x03, 0x3E, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0xC0, 0x7C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x0F, 0x1F, 0x7F, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0C, 0x18, 0x18, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x30, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0C, 0x07, 0x03, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x1F, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x66, 0xC3, 0xC3, 0x66, 0x3C, 0x18, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x18, 0x66, 0xC3, 0xDB, 0xDB, 0xC3, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xFF, 0x66, 0xFF, 0x66, 0x66, 0x00, 0x18, 0x3E, 0x58, 0x3C, 0x1A, 0x7C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x49, 0x00, 0x3C, 0x66, 0x3C, 0x38, 0x67, 0x66, 0x3F, 0x00, 0x06, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x18, 0x18, 0x38, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x3C, 0x66, 0x06, 0x0C, 0x30, 0x60, 0x7E, 0x00, 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0x00, 0x06, 0x0E, 0x1E, 0x66, 0x7F, 0x06, 0x06, 0x00, 0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0x00, 0x3C, 0x66, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0x00, 0x7E, 0x66, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x0E, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0E, 0x00, 0x7C, 0x82, 0xBA, 0xA2, 0xBA, 0x82, 0x7C, 0x00, 0x70, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x70, 0x00, 0x3C, 0x66, 0x06, 0x0C, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00, 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00, 0x78, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0x78, 0x00, 0x7E, 0x60, 0x60, 0x78, 0x60, 0x60, 0x7E, 0x00, 0x7E, 0x60, 0x60, 0x78, 0x60, 0x60, 0x60, 0x00, 0x3C, 0x66, 0x60, 0x6E, 0x66, 0x66, 0x3C, 0x00, 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x00, 0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E, 0x00, 0x63, 0x77, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x00, 0x66, 0x76, 0x7E, 0x7E, 0x6E, 0x66, 0x66, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x0E, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x78, 0x6C, 0x66, 0x00, 0x3C, 0x66, 0x60, 0x3C, 0x06, 0x66, 0x3C, 0x00, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x0C, 0x12, 0x30, 0x7C, 0x30, 0x62, 0xFC, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDB, 0xDB, 0x00, 0x00, 0x10, 0x30, 0x7F, 0x7F, 0x30, 0x10, 0x00, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00, 0x00, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00, 0x3C, 0x60, 0x60, 0x60, 0x3C, 0x00, 0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00, 0x00, 0x0E, 0x18, 0x3E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x7C, 0x00, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x00, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, 0x3C, 0x00, 0x60, 0x60, 0x6C, 0x78, 0x6C, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x66, 0x7F, 0x7F, 0x6B, 0x63, 0x00, 0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x00, 0x00, 0x7C, 0x66, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x00, 0x00, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x3E, 0x36, 0x00, 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x0C, 0x78, 0x00, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x7E, 0x00, 0x01, 0x03, 0x06, 0x6C, 0x78, 0x70, 0x60, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x7E, 0x3C, 0x18, 0x10, 0x30, 0x70, 0xFF, 0xFF, 0x70, 0x30, 0x10, 0x08, 0x0C, 0x0E, 0xFF, 0xFF, 0x0E, 0x0C, 0x08, }; // German Zak font static byte germanCharsetDataV2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18, 0x3e, 0x03, 0x00, 0x80, 0xc0, 0x60, 0x30, 0x18, 0x7c, 0xc0, 0x00, 0x00, 0x03, 0x3e, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, 0xc0, 0x7c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x1f, 0x7f, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x60, 0x30, 0x18, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x07, 0x03, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x18, 0x66, 0xc3, 0xdb, 0xdb, 0xc3, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0xff, 0x66, 0x66, 0x00, 0x18, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x18, 0x00, 0x62, 0x66, 0x0c, 0x18, 0x30, 0x66, 0x46, 0x00, 0x3c, 0x66, 0x3c, 0x38, 0x67, 0x66, 0x3f, 0x00, 0x30, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x18, 0x18, 0x38, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x3c, 0x66, 0x06, 0x0c, 0x30, 0x60, 0x7e, 0x00, 0x3c, 0x66, 0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00, 0x06, 0x0e, 0x1e, 0x66, 0x7f, 0x06, 0x06, 0x00, 0x7e, 0x60, 0x7c, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x3c, 0x66, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00, 0x7e, 0x66, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x0e, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0e, 0x00, 0x7c, 0x82, 0xba, 0xa2, 0xa2, 0xba, 0x82, 0x7c, 0x70, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x70, 0x00, 0x3c, 0x66, 0x06, 0x0c, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x00, 0x7e, 0x60, 0x60, 0x78, 0x60, 0x60, 0x7e, 0x00, 0x7e, 0x60, 0x60, 0x78, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0x60, 0x6e, 0x66, 0x66, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x66, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x00, 0x63, 0x77, 0x7f, 0x6b, 0x63, 0x63, 0x63, 0x00, 0x66, 0x76, 0x7e, 0x7e, 0x6e, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x0e, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x78, 0x6c, 0x66, 0x00, 0x3c, 0x66, 0x60, 0x3c, 0x06, 0x66, 0x3c, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x63, 0x63, 0x63, 0x6b, 0x7f, 0x77, 0x63, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x7e, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x7e, 0x00, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x66, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00, 0x00, 0x10, 0x30, 0x7f, 0x7f, 0x30, 0x10, 0x00, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x60, 0x60, 0x3c, 0x00, 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x00, 0x0e, 0x18, 0x3e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x7c, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x00, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, 0x3c, 0x00, 0x60, 0x60, 0x6c, 0x78, 0x6c, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x66, 0x7f, 0x7f, 0x6b, 0x63, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x7c, 0x66, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x00, 0x00, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x63, 0x6b, 0x7f, 0x3e, 0x36, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x0c, 0x78, 0x00, 0x00, 0x7e, 0x0c, 0x18, 0x30, 0x7e, 0x00, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x66, 0x18, 0x3c, 0x66, 0x7e, 0x66, 0x66, 0x00, 0x42, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x1c, 0x36, 0x36, 0x7c, 0x66, 0x66, 0x7c, 0x40, 0x08, 0x0c, 0x0e, 0xff, 0xff, 0x0e, 0x0c, 0x08, }; // French Zak font. static byte frenchCharsetDataV2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18, 0x3e, 0x03, 0x00, 0x80, 0xc0, 0x60, 0x30, 0x18, 0x7c, 0xc0, 0x00, 0x00, 0x03, 0x3e, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, 0xc0, 0x7c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x1f, 0x7f, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x60, 0x30, 0x18, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x07, 0x03, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x18, 0x66, 0xc3, 0xdb, 0xdb, 0xc3, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0xff, 0x66, 0x66, 0x00, 0x18, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x18, 0x00, 0x62, 0x66, 0x0c, 0x18, 0x30, 0x66, 0x46, 0x00, 0x3c, 0x66, 0x3c, 0x38, 0x67, 0x66, 0x3f, 0x00, 0x30, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x18, 0x18, 0x38, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x3c, 0x66, 0x06, 0x0c, 0x30, 0x60, 0x7e, 0x00, 0x3c, 0x66, 0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00, 0x06, 0x0e, 0x1e, 0x66, 0x7f, 0x06, 0x06, 0x00, 0x7e, 0x60, 0x7c, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x3c, 0x66, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00, 0x7e, 0x66, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x10, 0x08, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, 0x18, 0x24, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x60, 0x3c, 0x18, 0x38, 0x3c, 0x66, 0x06, 0x0c, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x00, 0x7e, 0x60, 0x60, 0x78, 0x60, 0x60, 0x7e, 0x00, 0x7e, 0x60, 0x60, 0x78, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0x60, 0x6e, 0x66, 0x66, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x66, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x00, 0x63, 0x77, 0x7f, 0x6b, 0x63, 0x63, 0x63, 0x00, 0x66, 0x76, 0x7e, 0x7e, 0x6e, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x0e, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x78, 0x6c, 0x66, 0x00, 0x3c, 0x66, 0x60, 0x3c, 0x06, 0x66, 0x3c, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x63, 0x63, 0x63, 0x6b, 0x7f, 0x77, 0x63, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x7e, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x7e, 0x00, 0x08, 0x10, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x10, 0x08, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x18, 0x24, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00, 0x00, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x60, 0x60, 0x3c, 0x00, 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x00, 0x0e, 0x18, 0x3e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x7c, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x00, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, 0x3c, 0x00, 0x60, 0x60, 0x6c, 0x78, 0x6c, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x66, 0x7f, 0x7f, 0x6b, 0x63, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x7c, 0x66, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x00, 0x00, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x63, 0x6b, 0x7f, 0x3e, 0x36, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x0c, 0x78, 0x00, 0x00, 0x7e, 0x0c, 0x18, 0x30, 0x7e, 0x00, 0x18, 0x24, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00, 0x10, 0x08, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x18, 0x24, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x08, 0x0c, 0x0e, 0xff, 0xff, 0x0e, 0x0c, 0x08, }; // Italian Zak font. static byte italianCharsetDataV2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18, 0x3e, 0x03, 0x00, 0x80, 0xc0, 0x60, 0x30, 0x18, 0x7c, 0xc0, 0x00, 0x00, 0x03, 0x3e, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, 0xc0, 0x7c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x1f, 0x7f, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x60, 0x30, 0x18, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x07, 0x03, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x18, 0x66, 0xc3, 0xdb, 0xdb, 0xc3, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0xff, 0x66, 0x66, 0x00, 0x18, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x18, 0x00, 0x62, 0x66, 0x0c, 0x18, 0x30, 0x66, 0x46, 0x00, 0x3c, 0x66, 0x3c, 0x38, 0x67, 0x66, 0x3f, 0x00, 0x30, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x18, 0x18, 0x38, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x3c, 0x66, 0x06, 0x0c, 0x30, 0x60, 0x7e, 0x00, 0x3c, 0x66, 0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00, 0x06, 0x0e, 0x1e, 0x66, 0x7f, 0x06, 0x06, 0x00, 0x7e, 0x60, 0x7c, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x3c, 0x66, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00, 0x7e, 0x66, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x10, 0x08, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, 0x08, 0x10, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, 0x10, 0x08, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x3c, 0x66, 0x06, 0x0c, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x00, 0x7e, 0x60, 0x60, 0x78, 0x60, 0x60, 0x7e, 0x00, 0x7e, 0x60, 0x60, 0x78, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0x60, 0x6e, 0x66, 0x66, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x66, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x00, 0x63, 0x77, 0x7f, 0x6b, 0x63, 0x63, 0x63, 0x00, 0x66, 0x76, 0x7e, 0x7e, 0x6e, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x0e, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x78, 0x6c, 0x66, 0x00, 0x3c, 0x66, 0x60, 0x3c, 0x06, 0x66, 0x3c, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x63, 0x63, 0x63, 0x6b, 0x7f, 0x77, 0x63, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x7e, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x7e, 0x00, 0x08, 0x10, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x10, 0x08, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x18, 0x24, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00, 0x00, 0x6c, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x60, 0x60, 0x3c, 0x00, 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x00, 0x0e, 0x18, 0x3e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x7c, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x00, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, 0x3c, 0x00, 0x60, 0x60, 0x6c, 0x78, 0x6c, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x66, 0x7f, 0x7f, 0x6b, 0x63, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x7c, 0x66, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x00, 0x00, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x63, 0x6b, 0x7f, 0x3e, 0x36, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x0c, 0x78, 0x00, 0x00, 0x7e, 0x0c, 0x18, 0x30, 0x7e, 0x00, 0x10, 0x08, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x00, 0x10, 0x08, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x18, 0x24, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x08, 0x0c, 0x0e, 0xff, 0xff, 0x0e, 0x0c, 0x08, }; // Spanish Zak font. // FIXME: This is identical to germanCharsetDataV2 it seems?! static byte spanishCharsetDataV2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18, 0x3e, 0x03, 0x00, 0x80, 0xc0, 0x60, 0x30, 0x18, 0x7c, 0xc0, 0x00, 0x00, 0x03, 0x3e, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, 0xc0, 0x7c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x1f, 0x7f, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x60, 0x30, 0x18, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0c, 0x18, 0x18, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x07, 0x03, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x18, 0x66, 0xc3, 0xdb, 0xdb, 0xc3, 0x66, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0xff, 0x66, 0x66, 0x00, 0x18, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x18, 0x00, 0x62, 0x66, 0x0c, 0x18, 0x30, 0x66, 0x46, 0x00, 0x3c, 0x66, 0x3c, 0x38, 0x67, 0x66, 0x3f, 0x00, 0x30, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x18, 0x18, 0x38, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x3c, 0x66, 0x06, 0x0c, 0x30, 0x60, 0x7e, 0x00, 0x3c, 0x66, 0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00, 0x06, 0x0e, 0x1e, 0x66, 0x7f, 0x06, 0x06, 0x00, 0x7e, 0x60, 0x7c, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x3c, 0x66, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00, 0x7e, 0x66, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, 0x0e, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0e, 0x00, 0x7c, 0x82, 0xba, 0xa2, 0xa2, 0xba, 0x82, 0x7c, 0x70, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x70, 0x00, 0x3c, 0x66, 0x06, 0x0c, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x00, 0x7e, 0x60, 0x60, 0x78, 0x60, 0x60, 0x7e, 0x00, 0x7e, 0x60, 0x60, 0x78, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0x60, 0x6e, 0x66, 0x66, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x66, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x00, 0x63, 0x77, 0x7f, 0x6b, 0x63, 0x63, 0x63, 0x00, 0x66, 0x76, 0x7e, 0x7e, 0x6e, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x0e, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x78, 0x6c, 0x66, 0x00, 0x3c, 0x66, 0x60, 0x3c, 0x06, 0x66, 0x3c, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x63, 0x63, 0x63, 0x6b, 0x7f, 0x77, 0x63, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x7e, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x7e, 0x00, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x66, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0x00, 0x00, 0x10, 0x30, 0x7f, 0x7f, 0x30, 0x10, 0x00, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x60, 0x60, 0x3c, 0x00, 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x00, 0x0e, 0x18, 0x3e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x7c, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x00, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, 0x3c, 0x00, 0x60, 0x60, 0x6c, 0x78, 0x6c, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x66, 0x7f, 0x7f, 0x6b, 0x63, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x7c, 0x66, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x00, 0x00, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x63, 0x6b, 0x7f, 0x3e, 0x36, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x0c, 0x78, 0x00, 0x00, 0x7e, 0x0c, 0x18, 0x30, 0x7e, 0x00, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x66, 0x18, 0x3c, 0x66, 0x7e, 0x66, 0x66, 0x00, 0x42, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x1c, 0x36, 0x36, 0x7c, 0x66, 0x66, 0x7c, 0x40, 0x08, 0x0c, 0x0e, 0xff, 0xff, 0x0e, 0x0c, 0x08, }; #endif CharsetRendererV2::CharsetRendererV2(ScummEngine *vm, Common::Language language) : CharsetRendererV3(vm) { switch (language) { case Common::DE_DEU: _fontPtr = germanCharsetDataV2; break; case Common::FR_FRA: _fontPtr = frenchCharsetDataV2; break; case Common::IT_ITA: _fontPtr = italianCharsetDataV2; break; case Common::ES_ESP: _fontPtr = spanishCharsetDataV2; break; default: _fontPtr = englishCharsetDataV2; break; } #if 0 // Decompress weird encoding in which the Zak executable contains the font. // I leave the code around in case we need to use it again (e.g. we might // have to include different fonts for french/spanish/russian/... version // of MM / Zak // int count = 0, len; byte b; const byte *data = spanishCharsetDataV2; const int size = sizeof(spanishCharsetDataV2); for (int offset = 0; offset < size; offset++) { if (data[offset+1] == 0x00 && data[offset+2] == 0xB2 && data[offset+5] == 0x00 && data[offset+6] == 0xB0) { b = data[offset+3]; len = data[offset+4]; while (len--) { printf("0x%02x, ", b); count++; if (count % 8 == 0) printf("\n"); } offset += 6; } else { printf("0x%02x, ", data[offset]); count++; if (count % 8 == 0) printf("\n"); } } printf("\n"); _vm->_system->quit(); #endif } int CharsetRendererV3::getCharWidth(byte chr) { if (chr & 0x80 && _vm->_useCJKMode) return _vm->_2byteWidth / 2; int spacing = 0; spacing = *(_widthTable + chr); return spacing; } void CharsetRendererV3::setColor(byte color) { _color = color; _shadowColor = (_vm->_platform == Common::kPlatformFMTowns) ? 8 : 0; // FM-TOWNS version of Loom uses old colour method as well if ((_vm->_version >= 2) && (_vm->_features & GF_16COLOR || _vm->_gameId == GID_LOOM)) { _dropShadow = ((_color & 0xF0) != 0); _color &= 0x0f; } else if (_vm->_features & GF_OLD256) { _dropShadow = ((_color & 0x80) != 0); _color &= 0x7f; } else _dropShadow = false; translateColor(); } void CharsetRendererV3::printChar(int chr) { // Indy3 / Zak256 / Loom int width, height, origWidth, origHeight; VirtScreen *vs; byte *charPtr, *dst; int is2byte = (chr >= 0x80 && _vm->_useCJKMode) ? 1 : 0; checkRange(_vm->_numCharsets - 1, 0, _curId, "Printing with bad charset %d"); if ((vs = _vm->findVirtScreen(_top)) == NULL) return; if (chr == '@') return; if (is2byte) { charPtr = _vm->get2byteCharPtr(chr); width = _vm->_2byteWidth; height = _vm->_2byteHeight; } else { charPtr = _fontPtr + chr * 8; // width = height = 8; width = getCharWidth(chr); height = 8; } origWidth = width; origHeight = height; if (_dropShadow) { width++; height++; } if (_firstChar) { _str.left = _left; _str.top = _top; _str.right = _left; _str.bottom = _top; _firstChar = false; } int drawTop = _top - vs->topline; _vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height); if (!_ignoreCharsetMask) { _hasMask = true; _textScreenID = vs->number; } if (_ignoreCharsetMask || !vs->hasTwoBuffers) { dst = vs->getPixels(_left, drawTop); drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight); } else { dst = (byte *)_textSurface.pixels + _top * _textSurface.pitch + _left; drawBits1(_textSurface, dst, charPtr, drawTop, origWidth, origHeight); } if (_str.left > _left) _str.left = _left; _left += origWidth; if (_str.right < _left) { _str.right = _left; if (_dropShadow) _str.right++; } if (_str.bottom < _top + height) _str.bottom = _top + height; } void CharsetRendererV3::drawChar(int chr, const Graphics::Surface &s, int x, int y) { byte *charPtr, *dst; int width, height; int is2byte = (chr >= 0x80 && _vm->_useCJKMode) ? 1 : 0; if (is2byte) { charPtr = _vm->get2byteCharPtr(chr); width = _vm->_2byteWidth; height = _vm->_2byteHeight; } else { charPtr = _fontPtr + chr * 8; // width = height = 8; width = getCharWidth(chr); height = 8; } dst = (byte *)s.pixels + y * s.pitch + x; drawBits1(s, dst, charPtr, y, width, height); } void CharsetRenderer::translateColor() { // Based on disassembly if (_vm->_renderMode == Common::kRenderCGA) { static byte CGAtextColorMap[16] = {0, 3, 3, 3, 5, 5, 5, 15, 15, 3, 3, 3, 5, 5, 15, 15}; _color = CGAtextColorMap[_color & 0x0f]; } if (_vm->_renderMode == Common::kRenderHercA || _vm->_renderMode == Common::kRenderHercG) { static byte HercTextColorMap[16] = {0, 15, 2, 15, 15, 5, 15, 15, 8, 15, 15, 15, 15, 15, 15, 15}; _color = HercTextColorMap[_color & 0x0f]; } } void CharsetRendererClassic::printChar(int chr) { int width, height, origWidth, origHeight; int offsX, offsY; VirtScreen *vs; const byte *charPtr; int is2byte = (chr >= 0x80 && _vm->_useCJKMode) ? 1 : 0; checkRange(_vm->_numCharsets - 1, 1, _curId, "Printing with bad charset %d"); if ((vs = _vm->findVirtScreen(_top)) == NULL && (vs = _vm->findVirtScreen(_top + getFontHeight())) == NULL) return; if (chr == '@') return; translateColor(); _vm->_charsetColorMap[1] = _color; int type = *_fontPtr; if (is2byte) { _dropShadow = true; _shadowColor = (_vm->_platform == Common::kPlatformFMTowns) ? 8 : 0; charPtr = _vm->get2byteCharPtr(chr); width = _vm->_2byteWidth; height = _vm->_2byteHeight; offsX = offsY = 0; } else { uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4); assert(charOffs < 0x10000); if (!charOffs) return; charPtr = _fontPtr + charOffs; width = charPtr[0]; height = charPtr[1]; if (_disableOffsX) { offsX = 0; } else { offsX = (signed char)charPtr[2]; } offsY = (signed char)charPtr[3]; charPtr += 4; // Skip over char header } origWidth = width; origHeight = height; if (_dropShadow) { width++; height++; } if (_firstChar) { _str.left = 0; _str.top = 0; _str.right = 0; _str.bottom = 0; } _top += offsY; _left += offsX; if (_left + origWidth > _right + 1 || _left < 0) { _left += origWidth; _top -= offsY; return; } _disableOffsX = false; if (_firstChar) { _str.left = _left; _str.top = _top; _str.right = _left; _str.bottom = _top; _firstChar = false; } if (_left < _str.left) _str.left = _left; if (_top < _str.top) _str.top = _top; int drawTop = _top - vs->topline; _vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height); byte *dstPtr; byte *back = NULL; if (!_ignoreCharsetMask) { _hasMask = true; _textScreenID = vs->number; } if ((_vm->_heversion >= 71 && type >= 8) || (_vm->_heversion >= 90 && type == 0)) { #ifndef DISABLE_HE if (_ignoreCharsetMask || !vs->hasTwoBuffers) { dstPtr = vs->getPixels(0, 0); } else { dstPtr = (byte *)_textSurface.pixels; } if (_blitAlso && vs->hasTwoBuffers) { dstPtr = vs->getBackPixels(0, 0); } Common::Rect rScreen(vs->w, vs->h); if (type >= 8) { byte imagePalette[256]; memset(imagePalette, 0, sizeof(imagePalette)); memcpy(imagePalette, _vm->_charsetColorMap, 16); Wiz::copyWizImage(dstPtr, charPtr, vs->w, vs->h, _left, _top, origWidth, origHeight, &rScreen, imagePalette); } else { Wiz::copyWizImage(dstPtr, charPtr, vs->w, vs->h, _left, _top, origWidth, origHeight, &rScreen); } if (_blitAlso && vs->hasTwoBuffers) { Common::Rect dst(_left, _top, _left + origWidth, _top + origHeight); _vm->gdi.copyVirtScreenBuffers(dst); } #endif } else { Graphics::Surface dstSurface; Graphics::Surface backSurface; if (_ignoreCharsetMask || !vs->hasTwoBuffers) { dstSurface = *vs; dstPtr = vs->getPixels(_left, drawTop); } else { dstSurface = _textSurface; dstPtr = (byte *)_textSurface.pixels + (_top - _vm->_screenTop) * _textSurface.pitch + _left; } if (_blitAlso && vs->hasTwoBuffers) { backSurface = dstSurface; back = dstPtr; dstSurface = *vs; dstPtr = vs->getBackPixels(_left, drawTop); } if (!_ignoreCharsetMask && vs->hasTwoBuffers) { drawTop = _top - _vm->_screenTop; } if (is2byte) { drawBits1(dstSurface, dstPtr, charPtr, drawTop, origWidth, origHeight); } else { drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight); } if (_blitAlso && vs->hasTwoBuffers) { // FIXME: Revisiting this code, I think the _blitAlso mode is likely broken // right now -- we are copying stuff from "dstPtr" to "back", but "dstPtr" really // only conatains charset data... // One way to fix this: don't copy etc.; rather simply render the char twice, // once to each of the two buffers. That should hypothetically yield // identical results, though I didn't try it and right now I don't know // any spots where I can test this... if (!_ignoreCharsetMask) warning("This might be broken -- please report where you encountered this to Fingolfin"); // Perform some clipping int w = MIN(width, dstSurface.w - _left); int h = MIN(height, dstSurface.h - drawTop); if (_left < 0) { w += _left; back -= _left; dstPtr -= _left; } if (drawTop < 0) { h += drawTop; back -= drawTop * backSurface.pitch; dstPtr -= drawTop * dstSurface.pitch; } // Blit the image data if (w > 0) { while (h-- > 0) { memcpy(back, dstPtr, w); back += backSurface.pitch; dstPtr += dstSurface.pitch; } } } } _left += origWidth; if (_str.right < _left) { _str.right = _left; if (_dropShadow) _str.right++; } if (_str.bottom < _top + height) _str.bottom = _top + height; _top -= offsY; } void CharsetRendererClassic::drawChar(int chr, const Graphics::Surface &s, int x, int y) { const byte *charPtr; byte *dst; int width, height; int is2byte = (chr >= 0x80 && _vm->_useCJKMode) ? 1 : 0; if (is2byte) { _dropShadow = true; _shadowColor = (_vm->_platform == Common::kPlatformFMTowns) ? 8 : 0; charPtr = _vm->get2byteCharPtr(chr); width = _vm->_2byteWidth; height = _vm->_2byteHeight; } else { uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4); assert(charOffs < 0x10000); if (!charOffs) return; charPtr = _fontPtr + charOffs; width = charPtr[0]; height = charPtr[1]; charPtr += 4; // Skip over char header } dst = (byte *)s.pixels + y * s.pitch + x; if (is2byte) { drawBits1(s, dst, charPtr, y, width, height); } else { drawBitsN(s, dst, charPtr, *_fontPtr, y, width, height); } } void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height) { int y, x; int color; byte numbits, bits; assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8); bits = *src++; numbits = 8; for (y = 0; y < height && y + drawTop < s.h; y++) { for (x = 0; x < width; x++) { color = (bits >> (8 - bpp)) & 0xFF; if (color && y + drawTop >= 0) { *dst = _vm->_charsetColorMap[color]; } dst++; bits <<= bpp; numbits -= bpp; if (numbits == 0) { bits = *src++; numbits = 8; } } dst += s.pitch - width; } } void CharsetRendererCommon::drawBits1(const Graphics::Surface &s, byte *dst, const byte *src, int drawTop, int width, int height) { int y, x; byte bits = 0; for (y = 0; y < height && y + drawTop < s.h; y++) { for (x = 0; x < width; x++) { if ((x % 8) == 0) bits = *src++; if ((bits & revBitMask(x % 8)) && y + drawTop >= 0) { if (_dropShadow) { *(dst + 1) = _shadowColor; *(dst + s.pitch) = _shadowColor; *(dst + s.pitch + 1) = _shadowColor; } *dst = _color; } dst++; } dst += s.pitch - width; } } CharsetRendererNut::CharsetRendererNut(ScummEngine *vm) : CharsetRenderer(vm) { _current = 0; for (int i = 0; i < 5; i++) { char fontname[256]; if ((_vm->_gameId == GID_CMI) && (_vm->_features & GF_DEMO) && (i == 4)) break; sprintf(fontname, "font%d.nut", i); _fr[i] = new NutRenderer(_vm); if (!(_fr[i]->loadFont(fontname))) { delete _fr[i]; _fr[i] = NULL; } } } CharsetRendererNut::~CharsetRendererNut() { for (int i = 0; i < 5; i++) { if ((_vm->_gameId == GID_CMI) && (_vm->_features & GF_DEMO) && (i == 4)) break; delete _fr[i]; } } void CharsetRendererNut::setCurID(byte id) { assert(id < 5); _curId = id; _current = _fr[id]; assert(_current); } int CharsetRendererNut::getCharWidth(byte chr) { assert(_current); return _current->getCharWidth(chr); } int CharsetRendererNut::getFontHeight() { // FIXME / TODO: how to implement this properly??? assert(_current); return _current->getCharHeight('|'); } void CharsetRendererNut::printChar(int chr) { Common::Rect shadow; assert(_current); if (chr == '@') return; shadow.left = _left - 1; shadow.top = _top - 1; // Note that the character is drawn with a shadow, so it is slightly // larger than the advertised dimensions. See drawShadowChar() for // details. if (_firstChar) { _str.left = (shadow.left >= 0) ? shadow.left : 0; _str.top = (shadow.top >= 0) ? shadow.top : 0; _str.right = _str.left; _str.bottom = _str.top; _firstChar = false; } int width = _current->getCharWidth(chr); int height = _current->getCharHeight(chr); if (chr >= 256 && _vm->_useCJKMode) width = _vm->_2byteWidth; shadow.right = _left + width + 2; shadow.bottom = _top + height + 2; Graphics::Surface s; if (!_ignoreCharsetMask) { _hasMask = true; _textScreenID = kMainVirtScreen; } int drawTop = _top; if (_ignoreCharsetMask) { VirtScreen *vs = &_vm->virtscr[kMainVirtScreen]; s = *vs; s.pixels = vs->getPixels(0, 0); } else { s = _textSurface; drawTop -= _vm->_screenTop; } _current->drawShadowChar(s, chr, _left, drawTop, _color, _curId != 3); _vm->markRectAsDirty(kMainVirtScreen, shadow); if (_str.left > _left) _str.left = _left; _left += width; if (_str.right < shadow.right) _str.right = shadow.right; if (_str.bottom < shadow.bottom) _str.bottom = shadow.bottom; } CharsetRendererNES::CharsetRendererNES(ScummEngine *vm, Common::Language language) : CharsetRendererCommon(vm) { _trTable = NULL; // can't init it here, since resources aren't yet loaded! } void CharsetRendererNES::printChar(int chr) { int width, height, origWidth, origHeight; VirtScreen *vs; byte *charPtr, *dst; if (!_trTable) // have to init it here instead _trTable = _vm->getResourceAddress(rtCostume, 77) + 2; // HACK: how to set it properly? if (_top == 0) _top = 16; if ((vs = _vm->findVirtScreen(_top)) == NULL) return; if (chr == '@') return; charPtr = _vm->_NESPatTable[1] + _trTable[chr - 32] * 16; width = getCharWidth(chr); height = 8; origWidth = width; origHeight = height; if (_firstChar) { _str.left = _left; _str.top = _top; _str.right = _left; _str.bottom = _top; _firstChar = false; } int drawTop = _top - vs->topline; _vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height); if (!_ignoreCharsetMask) { _hasMask = true; _textScreenID = vs->number; } if (_ignoreCharsetMask || !vs->hasTwoBuffers) { dst = vs->getPixels(_left, drawTop); drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight); } else { dst = (byte *)_textSurface.pixels + _top * _textSurface.pitch + _left; drawBits1(_textSurface, dst, charPtr, drawTop, origWidth, origHeight); } if (_str.left > _left) _str.left = _left; _left += origWidth; if (_str.right < _left) { _str.right = _left; if (_dropShadow) _str.right++; } if (_str.bottom < _top + height) _str.bottom = _top + height; } void CharsetRendererNES::drawChar(int chr, const Graphics::Surface &s, int x, int y) { byte *charPtr, *dst; int width, height; if (!_trTable) _trTable = _vm->getResourceAddress(rtCostume, 77) + 2; charPtr = _vm->_NESPatTable[1] + _trTable[chr - 32] * 16; width = getCharWidth(chr); height = 8; dst = (byte *)s.pixels + y * s.pitch + x; drawBits1(s, dst, charPtr, y, width, height); } void CharsetRendererNES::drawBits1(const Graphics::Surface &s, byte *dst, const byte *src, int drawTop, int width, int height) { for (int i = 0; i < 8; i++) { byte c0 = src[i]; byte c1 = src[i + 8]; for (int j = 0; j < 8; j++) dst[j] = _vm->_NESPalette[0][((c0 >> (7 - j)) & 1) | (((c1 >> (7 - j)) & 1) << 1) | (_color ? 12 : 8)]; dst += s.pitch; } } } // End of namespace Scumm #ifdef __PALM_OS__ #include "scumm_globals.h" _GINIT(Charset) _GSETPTR(Scumm::germanCharsetDataV2, GBVARS_GERMANCHARSETDATAV2_INDEX, byte, GBVARS_SCUMM) _GSETPTR(Scumm::frenchCharsetDataV2, GBVARS_FRENCHCHARSETDATAV2_INDEX, byte, GBVARS_SCUMM) _GSETPTR(Scumm::englishCharsetDataV2, GBVARS_ENGLISHCHARSETDATAV2_INDEX, byte, GBVARS_SCUMM) _GSETPTR(Scumm::italianCharsetDataV2, GBVARS_ITALIANCHARSETDATAV2_INDEX, byte, GBVARS_SCUMM) _GSETPTR(Scumm::spanishCharsetDataV2, GBVARS_SPANISHCHARSETDATAV2_INDEX, byte, GBVARS_SCUMM) _GEND _GRELEASE(Charset) _GRELEASEPTR(GBVARS_GERMANCHARSETDATAV2_INDEX, GBVARS_SCUMM) _GRELEASEPTR(GBVARS_FRENCHCHARSETDATAV2_INDEX, GBVARS_SCUMM) _GRELEASEPTR(GBVARS_ENGLISHCHARSETDATAV2_INDEX, GBVARS_SCUMM) _GRELEASEPTR(GBVARS_ITALIANCHARSETDATAV2_INDEX, GBVARS_SCUMM) _GRELEASEPTR(GBVARS_SPANISHCHARSETDATAV2_INDEX, GBVARS_SCUMM) _GEND #endif