diff options
Diffstat (limited to 'engines/hopkins/font.cpp')
-rw-r--r-- | engines/hopkins/font.cpp | 497 |
1 files changed, 497 insertions, 0 deletions
diff --git a/engines/hopkins/font.cpp b/engines/hopkins/font.cpp new file mode 100644 index 0000000000..651d0d40f5 --- /dev/null +++ b/engines/hopkins/font.cpp @@ -0,0 +1,497 @@ +/* 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/system.h" +#include "common/file.h" +#include "common/textconsole.h" +#include "hopkins/font.h" +#include "hopkins/files.h" +#include "hopkins/globals.h" +#include "hopkins/graphics.h" +#include "hopkins/hopkins.h" +#include "hopkins/objects.h" + +namespace Hopkins { + +void FontManager::setParent(HopkinsEngine *vm) { + _vm = vm; +} + +void FontManager::clearAll() { + for (int idx = 0; idx < 11; ++idx) { + Txt[idx].textOn = false; + Txt[idx].lineCount = 0; + Txt[idx].field3FC = 0; + Txt[idx].field3FE = 0; + Txt[idx].textBlock = NULL; + Txt[idx].width = 0; + Txt[idx].height = 0; + Txt[idx].textLoaded = false; + + ListeTxt[idx].enabled = false; + } +} + +// Text On +void FontManager::TEXTE_ON(int idx) { + if ((idx - 5) > 11) + error("Attempted to display text > MAX_TEXT."); + + TxtItem &txt = Txt[idx - 5]; + txt.textOn = true; + txt.textLoaded = false; + + if (txt.textBlock != g_PTRNUL) { + _vm->_globals.dos_free2(txt.textBlock); + txt.textBlock = g_PTRNUL; + } +} + +// Text Off +void FontManager::TEXTE_OFF(int idx) { + if ((idx - 5) > 11) + error("Attempted to display text > MAX_TEXT."); + + TxtItem &txt = Txt[idx - 5]; + txt.textOn = false; + txt.textLoaded = false; + + if (txt.textBlock != g_PTRNUL) { + _vm->_globals.dos_free2(txt.textBlock); + txt.textBlock = g_PTRNUL; + } +} + +// Text Color +void FontManager::COUL_TXT(int idx, byte colByte) { + Txt[idx - 5].colour = colByte; +} + +// Text Optimal Color +void FontManager::OPTI_COUL_TXT(int idx1, int idx2, int idx3, int idx4) { + COUL_TXT(idx1, 255); + COUL_TXT(idx2, 255); + COUL_TXT(idx3, 255); + COUL_TXT(idx4, 253); +} + +// +void FontManager::DOS_TEXT(int idx, int messageId, const Common::String &filename, int xp, int yp, int a6, int a7, int a8, int a9, int colour) { + if ((idx - 5) > 11) + error("Attempted to display text > MAX_TEXT."); + + TxtItem &txt = Txt[idx - 5]; + txt.textOn = false; + txt.filename = filename; + txt.xp = xp; + txt.yp = yp; + txt.messageId = messageId; + txt.fieldE = a6; + txt.field10 = a7; + txt.field3FC = a8; + txt.field3FE = a9; + txt.colour = colour; +} + +// Box +void FontManager::BOITE(int idx, int messageId, const Common::String &filename, int xp, int yp) { + int filesize; + byte *v9; + const byte *v10; + int v11; + byte v13; + byte v14; + int v15; + byte v16; + int v17; + int v18; + int v19; + int v20; + int v21; + int v22; + int v23; + byte v24; + int v25; + int v27; + int v28; + int v29; + int v32; + int v34; + int v36; + int v37; + int ptrb; + int ptrc; + byte *ptrd; + byte *ptre; + Common::String s; + int v49; + int blockSize; + int v51; + int blockHeight; + int v53; + int blockWidth; + int v55; + int v56; + int lineSize; + int lineCount; + byte *v59; + byte *v60; + byte *v61; + int v62; + int v63; + int v64; + int v65; + int v66; + int v67; + int v68; + int v69; + int v70; + int v71; + int v73; + int i; + int v75; + Common::String file; + Common::File f; + + v73 = xp; + v70 = yp; + lineCount = 0; + if (idx < 0) + error("Bad number for text"); + _vm->_globals.police_l = 11; + + _vm->_globals.largeur_boite = 11 * Txt[idx].field3FE; + if (Txt[idx].textLoaded) { + v34 = Txt[idx].field3FC; + if (v34 != 6 && v34 != 1 && v34 != 3 && v34 != 5) { + int yCurrent = yp + 5; + if (Txt[idx].lineCount > 0) { + for (int lineNum = 0; lineNum < Txt[idx].lineCount; ++lineNum) { + TEXT_NOW1(xp + 5, yCurrent, Txt[idx].lines[lineNum], Txt[idx].colour); + yCurrent += _vm->_globals.police_h + 1; + } + } + } else { + v36 = Txt[idx].height; + v37 = Txt[idx].width; + _vm->_graphicsManager.Restore_Mem( + _vm->_graphicsManager.VESA_BUFFER, + Txt[idx].textBlock, + xp, + yp, + Txt[idx].width, + Txt[idx].height); + _vm->_graphicsManager.Ajoute_Segment_Vesa(xp, yp, xp + v37, yp + v36); + } + } else { + v62 = 0; + do { + TRIER_TEXT[v62++] = 0; + } while (v62 <= 19); + Txt[idx].textLoaded = true; + _vm->_fileManager.CONSTRUIT_FICHIER(_vm->_globals.HOPLINK, filename); + + file = _vm->_globals.NFICHIER; + if (strncmp(file.c_str(), oldname.c_str(), strlen(file.c_str())) != 0) { + // Starting to access a new file, so read in the index file for the file + oldname = file; + nom_index = Common::String(file.c_str(), file.size() - 3); + nom_index += "IND"; + + if (!f.open(nom_index)) + error("Error opening file - %s", nom_index.c_str()); + filesize = f.size(); + for (i = 0; i < (filesize / 4); ++i) + Index[i] = f.readUint32LE(); + f.close(); + } + if (filename[0] != 'Z' || filename[1] != 'O') { + if (!f.open(file)) + error("Error opening file - %s", nom_index.c_str()); + + v69 = 2048; + f.seek(Index[messageId]); + + texte_tmp = _vm->_globals.dos_malloc2(0x80Au); + if (texte_tmp == g_PTRNUL) + error("Error allocating text"); + + Common::fill(&texte_tmp[0], &texte_tmp[0x80a], 0); + f.read(texte_tmp, 0x800u); + f.close(); + _vm->_globals.texte_long = 2048; + } else { + v69 = 100; + _vm->_globals.texte_long = 100; + v9 = _vm->_globals.dos_malloc2(0x6Eu); + Common::fill(&v9[0], &v9[0x6e], 0); + + texte_tmp = v9; + v10 = _vm->_globals.BUF_ZONE + Index[messageId]; + memcpy(v9, v10, 0x60u); + v11 = 0; + WRITE_LE_UINT16((uint16 *)v9 + 48, (int16)READ_LE_UINT16(v10 + 96)); + } + v59 = texte_tmp; + v63 = 0; + if (!v69) + goto LABEL_43; + do { + v13 = *v59; + if ((byte)(*v59 + 46) > 0x1Bu) { + if ((byte)(v13 + 80) > 0x1Bu) { + if ((byte)(v13 - 65) <= 0x19u || (byte)(v13 - 97) <= 0x19u) + v13 = 32; + } else { + v13 -= 79; + } + } else { + v13 += 111; + } + *v59 = v13; + v59 = v59 + 1; + ++v63; + } while (v63 < v69); + + v60 = texte_tmp; + v64 = 0; + if (v69) { + while (1) { + v14 = *(v60 + v64); + if (v14 == '\r' || v14 == '\n') { + *(v60 + v64) = 0; + if (!Txt[idx].field3FE) + break; + } + ++v64; + if (v69 <= v64) + goto LABEL_43; + } + Txt[idx].field3FE = v64; + _vm->_globals.largeur_boite = 0; + + v15 = 0; + if (v64 + 1 > 0) { + do { + v16 = *(v60 + v15); + if ((byte)v16 <= 0x1Fu) + v16 = 32; + _vm->_globals.largeur_boite += _vm->_objectsManager.Get_Largeur(_vm->_globals.police, (byte)v16 - 32); + ++v15; + } while (v15 < v64 + 1); + } + _vm->_globals.largeur_boite += 2; + v17 = _vm->_globals.largeur_boite / 2; + if (v17 < 0) + v17 = -v17; + Txt[idx].xp = 320 - v17; + v73 = _vm->_eventsManager.start_x + 320 - v17; + lineCount = 1; + v18 = 0; + if (v64 + 1 > 0) { + Txt[idx].lines[0] = Common::String((const char *)v60, v64); + } + } else { +LABEL_43: + if (!_vm->_globals.largeur_boite) + _vm->_globals.largeur_boite = 240; + v65 = 0; + v61 = texte_tmp; + do { + v19 = 0; + ptrb = _vm->_globals.largeur_boite - 4; + while (1) { + lineSize = v19; + do + v11 = *(v61 + v65 + v19++); + while (v11 != 32 && v11 != 37); + if (v19 >= ptrb / _vm->_globals.police_l) + break; + if (v11 == '%') { + if (v19 < ptrb / _vm->_globals.police_l) + goto LABEL_55; + break; + } + } + if (v11 != '%') + goto LABEL_57; + v11 = 32; +LABEL_55: + if (v11 == '%') + lineSize = v19; +LABEL_57: + v20 = lineCount; + v21 = v11; + + // WORKAROUND: Perhaps due to the usage of ScummVM strings here, recalculate what the + // actual length of the line to be copied will be. Otherwise, you can see artifacts, + // such as a single character beyond the end of string NULL. + int actualSize = 0; + while (actualSize < lineSize && *(v61 + v65 + actualSize)) + ++actualSize; + + Txt[idx].lines[v20] = Common::String((const char *)v61 + v65, actualSize); + TRIER_TEXT[lineCount++] = lineSize; + + v65 += lineSize; + v11 = v21; + } while (v21 != 37); + v66 = 0; + do { + v22 = TRIER_TEXT[v66]; + if (v22 <= 0) { + TRIER_TEXT[v66] = 0; + } else { + ptrc = 0; + v23 = 0; + if (v22 - 1 > 0) { + do { + Common::String &line = Txt[idx].lines[v66]; + v24 = (v23 >= (int)line.size()) ? '\0' : line[v23]; + if ((byte)v24 <= 0x1Fu) + v24 = 32; + ptrc += _vm->_objectsManager.Get_Largeur(_vm->_globals.police, (byte)v24 - 32); + ++v23; + } while (v23 < TRIER_TEXT[v66] - 1); + } + TRIER_TEXT[v66] = ptrc; + } + ++v66; + } while (v66 <= 19); + v67 = 0; + do { + v25 = v67; + do { + ++v25; + if (v25 == 20) + v25 = 0; + if (TRIER_TEXT[v67] < TRIER_TEXT[v25]) + TRIER_TEXT[v67] = 0; + } while (v25 != (int16)v67); + ++v67; + } while (v67 <= 19); + v68 = 0; + do { + if (TRIER_TEXT[v68]) + _vm->_globals.largeur_boite = TRIER_TEXT[v68]; + ++v68; + } while (v68 <= 19); + + if ((uint16)(Txt[idx].field3FC - 2) > 1u) { + for (i = xp - _vm->_eventsManager.start_x; _vm->_globals.largeur_boite + i > 638 && i > -2 && Txt[idx].field3FC; i -= 2) + ; + Txt[idx].xp = i; + v73 = _vm->_eventsManager.start_x + i; + } else { + if (_vm->_globals.nbrligne == (SCREEN_WIDTH - 1)) { + while (_vm->_globals.largeur_boite + v73 > 638 && v73 > -2) + v73 -= 2; + } + if (_vm->_globals.nbrligne == (SCREEN_WIDTH * 2)) { + while (_vm->_globals.largeur_boite + v73 > 1278 && v73 > -2) + v73 -= 2; + } + Txt[idx].xp = v73; + } + } + _vm->_globals.hauteur_boite = (_vm->_globals.police_h + 1) * lineCount + 2; + v56 = v73; + v55 = yp; + v53 = _vm->_globals.largeur_boite + 10; + v51 = (_vm->_globals.police_h + 1) * lineCount + 12; + if (Txt[idx].field3FC == 6) { + v27 = v53 / 2; + if (v27 < 0) + v27 = -v27; + Txt[idx].xp = 315 - v27; + v28 = _vm->_eventsManager.start_x + 315 - v27; + v73 = _vm->_eventsManager.start_x + 315 - v27; + Txt[idx].yp = 50; + v70 = 50; + v55 = 50; + v56 = v28; + } + v29 = Txt[idx].field3FC; + if (v29 == 1 || v29 == 3 || (uint16)(v29 - 5) <= 1u) { + v49 = v51 * v53; + ptrd = _vm->_globals.dos_malloc2(v51 * v53); + if (ptrd == g_PTRNUL) { + error("Cutting a block for text box (%d)", v49); + } + _vm->_graphicsManager.Capture_Mem(_vm->_graphicsManager.VESA_BUFFER, ptrd, v56, v55, v53, v51); + _vm->_graphicsManager.Trans_bloc2(ptrd, _vm->_graphicsManager.TABLE_COUL, v49); + _vm->_graphicsManager.Restore_Mem(_vm->_graphicsManager.VESA_BUFFER, ptrd, v56, v55, v53, v51); + _vm->_globals.dos_free2(ptrd); + + _vm->_graphicsManager.Plot_Hline(_vm->_graphicsManager.VESA_BUFFER, v56, v55, v53, (byte)-2); + _vm->_graphicsManager.Plot_Hline(_vm->_graphicsManager.VESA_BUFFER, v56, v51 + v55, v53, (byte)-2); + _vm->_graphicsManager.Plot_Vline(_vm->_graphicsManager.VESA_BUFFER, v56, v70, v51, (byte)-2); + _vm->_graphicsManager.Plot_Vline(_vm->_graphicsManager.VESA_BUFFER, v53 + v56, v70, v51, (byte)-2); + } + Txt[idx].lineCount = lineCount; + v75 = v73 + 5; + v71 = v70 + 5; + + if (lineCount > 0) { + for (int lineNum = 0; lineNum < lineCount; ++lineNum) { + TEXT_NOW1(v75, v71, Txt[idx].lines[lineNum], Txt[idx].colour); + v71 += _vm->_globals.police_h + 1; + } + } + + blockWidth = v53 + 1; + blockHeight = v51 + 1; + + Txt[idx].width = blockWidth; + Txt[idx].height = blockHeight; + v32 = Txt[idx].field3FC; + if (v32 == 6 || v32 == 1 || v32 == 3 || v32 == 5) { + if (Txt[idx].textBlock != g_PTRNUL) + Txt[idx].textBlock = _vm->_globals.dos_free2(Txt[idx].textBlock); + blockSize = blockHeight * blockWidth; + ptre = _vm->_globals.dos_malloc2(blockSize + 20); + if (ptre == g_PTRNUL) + error("Cutting a block for text box (%d)", blockSize); + + Txt[idx].textBlock = ptre; + Txt[idx].width = blockWidth; + Txt[idx].height = blockHeight; + _vm->_graphicsManager.Capture_Mem(_vm->_graphicsManager.VESA_BUFFER, Txt[idx].textBlock, v56, v55, Txt[idx].width, blockHeight); + } + texte_tmp = _vm->_globals.dos_free2(texte_tmp); + } +} + +void FontManager::TEXT_NOW1(int xp, int yp, const Common::String &message, int colour) { + for (uint idx = 0; idx < message.size(); ++idx) { + char currentChar = message[idx]; + + if (currentChar > 31) { + int characterIndex = currentChar - 32; + _vm->_graphicsManager.Affiche_Fonte(_vm->_graphicsManager.VESA_BUFFER, _vm->_globals.police, + xp, yp, characterIndex, colour); + xp += _vm->_objectsManager.Get_Largeur(_vm->_globals.police, characterIndex); + } + } +} + +} // End of namespace Hopkins |