From 34cb79817f9084e66dc3f11f324d3855bb7de965 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 10 Apr 2022 20:25:20 +0300 Subject: [PATCH] CHEWY: More work on the text handling code --- engines/chewy/atds.cpp | 23 ++++++++++------ engines/chewy/atds.h | 6 ++--- engines/chewy/dialogs/inventory.cpp | 4 +-- engines/chewy/sprite.cpp | 4 ++- engines/chewy/t_event.cpp | 3 ++- engines/chewy/text.cpp | 42 ++++++++++++++++++++++------- engines/chewy/text.h | 10 ++++--- 7 files changed, 65 insertions(+), 27 deletions(-) diff --git a/engines/chewy/atds.cpp b/engines/chewy/atds.cpp index cb9e0f16acc..770a43da2de 100644 --- a/engines/chewy/atds.cpp +++ b/engines/chewy/atds.cpp @@ -442,6 +442,8 @@ void Atdsys::set_ats_mem(int16 mode) { } bool Atdsys::start_ats(int16 txtNr, int16 txtMode, int16 color, int16 mode, int16 *vocNr) { + assert(mode == ATS_DATA || mode == INV_USE_DATA || mode == INV_USE_DEF); + *vocNr = -1; set_ats_mem(mode); @@ -451,7 +453,7 @@ bool Atdsys::start_ats(int16 txtNr, int16 txtMode, int16 color, int16 mode, int1 //const uint8 roomNum = _G(room)->_roomInfo->_roomNr; int16 txt_anz; _atsv._ptr = ats_get_txt(txtNr, txtMode, &txt_anz, mode); - //_atsv._ptr = (char *)getTextEntry(roomNum, txtNr, txtMode).c_str(); + //Common::StringArray tmp = getTextArray(roomNum, txtNr, mode, txtMode); if (_atsv._ptr) { _atsv.shown = g_engine->_sound->subtitlesEnabled(); @@ -567,6 +569,8 @@ void Atdsys::print_ats(int16 x, int16 y, int16 scrX, int16 scrY) { char *Atdsys::ats_get_txt(int16 txtNr, int16 txtMode, int16 *retNr, int16 mode) { char *str_ = nullptr; + + assert(mode == ATS_DATA || mode == INV_USE_DATA || mode == INV_USE_DEF); set_ats_mem(mode); _atsv._txtMode = txtMode; @@ -1247,10 +1251,13 @@ void Atdsys::show_item(int16 diaNr, int16 blockNr, int16 itemNr) { _dialogResource->setItemShown(diaNr, blockNr, itemNr, true); } -int16 Atdsys::calc_inv_no_use(int16 curInv, int16 testNr, int16 mode) { - assert(mode <= 255 && testNr <= 65535); +int16 Atdsys::calc_inv_no_use(int16 curInv, int16 testNr) { + if (curInv != -1) + _invBlockNr = curInv + 1; - const uint32 key = (mode & 0xff) << 16 | testNr; + assert(curInv <= 255 && testNr <= 65535); + + const uint32 key = (curInv & 0xff) << 16 | testNr; return (_itemUseWithDesc.contains(key)) ? _itemUseWithDesc[key] : -1; } @@ -1270,16 +1277,16 @@ uint32 Atdsys::getAtdsStreamSize() const { return _dialogResource->getStreamSize(); } -Common::StringArray Atdsys::getTextArray(uint dialogNum, uint entryNum, int type) { +Common::StringArray Atdsys::getTextArray(uint dialogNum, uint entryNum, int type, int subEntry) { if (!getControlBit(entryNum, ATS_ACTIVE_BIT)) - return _text->getTextArray(dialogNum, entryNum, type); + return _text->getTextArray(dialogNum, entryNum, type, subEntry); else return Common::StringArray(); } -Common::String Atdsys::getTextEntry(uint dialogNum, uint entryNum, int type) { +Common::String Atdsys::getTextEntry(uint dialogNum, uint entryNum, int type, int subEntry) { if (!getControlBit(entryNum, ATS_ACTIVE_BIT)) - return _text->getTextEntry(dialogNum, entryNum, type); + return _text->getTextEntry(dialogNum, entryNum, type, subEntry); else return Common::String(); } diff --git a/engines/chewy/atds.h b/engines/chewy/atds.h index 493cb9fc10b..f34120e35fb 100644 --- a/engines/chewy/atds.h +++ b/engines/chewy/atds.h @@ -268,7 +268,7 @@ public: void ads_search_block(int16 blockNr, char **ptr); void ads_search_item(int16 itemNr, char **blkAdr); int16 start_ads_auto_dia(char *itemAdr); - int16 calc_inv_no_use(int16 curInv, int16 testNr, int16 mode); + int16 calc_inv_no_use(int16 curInv, int16 testNr); int8 getStereoPos(int16 x); void enableEvents(bool nr) { _atdsv._eventsEnabled = nr; @@ -278,8 +278,8 @@ public: void loadAtdsStream(Common::SeekableReadStream *stream); uint32 getAtdsStreamSize() const; - Common::StringArray getTextArray(uint dialogNum, uint entryNum, int type); - Common::String getTextEntry(uint dialogNum, uint entryNum, int type); + Common::StringArray getTextArray(uint dialogNum, uint entryNum, int type, int subEntry = -1); + Common::String getTextEntry(uint dialogNum, uint entryNum, int type, int subEntry = -1); private: void init(); diff --git a/engines/chewy/dialogs/inventory.cpp b/engines/chewy/dialogs/inventory.cpp index 212e5711ca3..5be01e06ee1 100644 --- a/engines/chewy/dialogs/inventory.cpp +++ b/engines/chewy/dialogs/inventory.cpp @@ -411,10 +411,10 @@ int16 Inventory::look(int16 invent_nr, int16 mode, int16 ats_nr) { if (ats_nr >= 15000) { txt_adr = _G(atds)->ats_get_txt(ats_nr - 15000, TXT_MARK_USE, &lineCount, INV_USE_DEF); - //itemDesc = _G(atds)->getTextArray(ats_nr - 15000, TXT_MARK_USE, INV_USE_DEF); + //itemDesc = _G(atds)->getTextArray(0, ats_nr - 15000, INV_USE_DEF, TXT_MARK_USE); } else { txt_adr = _G(atds)->ats_get_txt(ats_nr, TXT_MARK_USE, &lineCount, INV_USE_DATA); - //itemDesc = _G(atds)->getTextArray(ats_nr, TXT_MARK_USE, INV_USE_DATA); + //itemDesc = _G(atds)->getTextArray(0, ats_nr, TXT_MARK_USE, INV_USE_DATA); } if (!txt_adr) { endLoop = true; diff --git a/engines/chewy/sprite.cpp b/engines/chewy/sprite.cpp index c6875e3b4c7..6c2f344bb6c 100644 --- a/engines/chewy/sprite.cpp +++ b/engines/chewy/sprite.cpp @@ -485,8 +485,10 @@ void start_aad(int16 diaNr) { bool startAtsWait(int16 txtNr, int16 txtMode, int16 col, int16 mode) { bool shown = false; - const int16 oldMouseLeftClick = _G(mouseLeftClick); + + assert(mode == ATS_DATA || mode == INV_USE_DATA || mode == INV_USE_DEF); + _G(mouseLeftClick) = false; _G(minfo)._button = 0; diff --git a/engines/chewy/t_event.cpp b/engines/chewy/t_event.cpp index 491c995ec61..0ac00391216 100644 --- a/engines/chewy/t_event.cpp +++ b/engines/chewy/t_event.cpp @@ -2298,6 +2298,7 @@ static void calc_inv_get_text(int16 cur_inv, int16 test_nr) { int16 txt_anz; const char *s = _G(atds)->ats_get_txt(31, TXT_MARK_USE, &txt_anz, INV_USE_DEF); + //Common::String tmp = _G(atds)->getTextEntry(0, 31, INV_USE_DEF, TXT_MARK_USE); _G(calc_inv_text_str1) = Common::String::format("%s ", s); _G(calc_inv_text_str1) += _G(atds)->getTextEntry(cur_inv, TXT_MARK_NAME, INV_ATS_DATA); @@ -2341,7 +2342,7 @@ bool calc_inv_no_use(int16 test_nr, int16 mode) { } if (inv_mode != -1) { - int16 txt_nr = _G(atds)->calc_inv_no_use(_G(gameState).AkInvent, test_nr, inv_mode); + int16 txt_nr = _G(atds)->calc_inv_no_use(_G(gameState).AkInvent, test_nr); if (txt_nr != -1) { if (!_G(flags).InventMenu) { if (txt_nr >= 15000) { diff --git a/engines/chewy/text.cpp b/engines/chewy/text.cpp index 3c20cc66054..bea90db3bfb 100644 --- a/engines/chewy/text.cpp +++ b/engines/chewy/text.cpp @@ -81,7 +81,7 @@ TextEntryList *Text::getDialog(uint chunk, uint entry) { return l; } -TextEntry *Text::getText(uint chunk, uint entry, int type) { +TextEntry *Text::getText(uint chunk, uint entry, int type, int subEntry) { bool isText = false; bool isAutoDialog = false; bool isInvDesc = false; @@ -117,24 +117,38 @@ TextEntry *Text::getText(uint chunk, uint entry, int type) { byte *data = getChunkData(chunk); byte *ptr = data; uint entryId = 0; + uint16 headerBytes, txtNum; + int curSubEntry = -1; + + //Common::hexdump(data, _chunkList[chunk].size); if (isAutoDialog) ptr += 3; while (true) { ptr += 3; - uint16 headerBytes = READ_LE_UINT16(ptr); + headerBytes = READ_LE_UINT16(ptr); ptr += 2; + + if (headerBytes == 0xFEF2) { + // Start of subchunk + curSubEntry = *ptr; + ptr++; + headerBytes = READ_LE_UINT16(ptr); + ptr += 2; + } + if (headerBytes != 0xFEF0) break; - uint16 txtNum = !isInvDesc ? READ_LE_UINT16(ptr) : entryId++; + + txtNum = !isInvDesc ? READ_LE_UINT16(ptr) : entryId++; ptr += 2; ptr += 6; d->_speechId = READ_LE_UINT16(ptr) - VOICE_OFFSET; ptr += 2; do { - if (txtNum == entry) + if (txtNum == entry && curSubEntry == subEntry) d->_text += *ptr++; else ptr++; @@ -144,6 +158,16 @@ TextEntry *Text::getText(uint chunk, uint entry, int type) { } } while (*ptr); + // FIXME: Skip other embedded strings for now + if (*(ptr + 1) == kEndText && *(ptr + 2) == 0xf1 && *(ptr + 3) == 0xfe) { + ptr += 5; + do { + ptr++; + if (*ptr == 0 && *(ptr + 1) != kEndText) + ptr++; + } while (*ptr); + } + if (*(ptr + 1) != kEndText || *(ptr + 2) != kEndChunk) { warning("Invalid text resource - %d, %d", chunk, entry); @@ -158,7 +182,7 @@ TextEntry *Text::getText(uint chunk, uint entry, int type) { if (isAutoDialog) ptr += 3; - if (txtNum == entry) { + if (txtNum == entry && curSubEntry == subEntry) { // Found delete[] data; return d; @@ -172,8 +196,8 @@ TextEntry *Text::getText(uint chunk, uint entry, int type) { return nullptr; } -Common::StringArray Text::getTextArray(uint chunk, uint entry, int type) { - TextEntry *textData = getText(chunk, entry, type); +Common::StringArray Text::getTextArray(uint chunk, uint entry, int type, int subEntry) { + TextEntry *textData = getText(chunk, entry, type, subEntry); Common::StringArray res; Common::String txt = textData ? textData->_text : ""; char *text = new char[txt.size() + 1]; @@ -191,8 +215,8 @@ Common::StringArray Text::getTextArray(uint chunk, uint entry, int type) { return res; } -Common::String Text::getTextEntry(uint chunk, uint entry, int type) { - Common::StringArray res = getTextArray(chunk, entry, type); +Common::String Text::getTextEntry(uint chunk, uint entry, int type, int subEntry) { + Common::StringArray res = getTextArray(chunk, entry, type, subEntry); return res.size() > 0 ? res[0] : ""; } diff --git a/engines/chewy/text.h b/engines/chewy/text.h index cfbbf59934a..0ef63cc10b1 100644 --- a/engines/chewy/text.h +++ b/engines/chewy/text.h @@ -81,10 +81,14 @@ public: * - auto dialog (AAD) - 600 - 699 * - inventory text (INV) - 700 - 799 * - use text (USE) - 800 - 899 + * + * A chunk can contain multiple subchunks with + * the same entry IDs per subchunk: + * 0 - name, 1 - look, 2 - use, 3 - walk, 4 - talk */ - TextEntry *getText(uint chunk, uint entry, int type); - Common::StringArray getTextArray(uint chunk, uint entry, int type); - Common::String getTextEntry(uint chunk, uint entry, int type); + TextEntry *getText(uint chunk, uint entry, int type, int subEntry = -1); + Common::StringArray getTextArray(uint chunk, uint entry, int type, int subEntry = -1); + Common::String getTextEntry(uint chunk, uint entry, int type, int subEntry = -1); void crypt(char *txt, uint32 size); const char *strPos(const char *txtAdr, int16 pos);