aboutsummaryrefslogtreecommitdiff
path: root/engines/hopkins/font.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/hopkins/font.cpp')
-rw-r--r--engines/hopkins/font.cpp497
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