From 0692d261eeea7dd9260e00dc6bc43dda963a41d4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 7 May 2016 10:49:56 -0400 Subject: TITANIC: Implement reading dialogue string --- engines/titanic/true_talk/dialogue_file.cpp | 42 +++++++++++-------- engines/titanic/true_talk/dialogue_file.h | 33 ++++++++------- engines/titanic/true_talk/title_engine.cpp | 2 +- engines/titanic/true_talk/title_engine.h | 3 +- engines/titanic/true_talk/true_talk_manager.cpp | 55 ++++++++++++++++++++++--- engines/titanic/true_talk/true_talk_manager.h | 9 +++- 6 files changed, 103 insertions(+), 41 deletions(-) diff --git a/engines/titanic/true_talk/dialogue_file.cpp b/engines/titanic/true_talk/dialogue_file.cpp index 1d1d789188..34eb164779 100644 --- a/engines/titanic/true_talk/dialogue_file.cpp +++ b/engines/titanic/true_talk/dialogue_file.cpp @@ -24,7 +24,7 @@ namespace Titanic { -void DialogueFileIndexEntry::load(Common::SeekableReadStream &s) { +void DialogueIndexEntry::load(Common::SeekableReadStream &s) { _v1 = s.readUint32LE(); _offset = s.readUint32LE(); } @@ -38,11 +38,11 @@ CDialogueFile::CDialogueFile(const CString &filename, uint count) { _cache.resize(count); _file.readUint32LE(); // Skip over file Id - _entries.resize(_file.readUint32LE()); + _index.resize(_file.readUint32LE()); // Read in the entries - for (uint idx = 0; idx < _entries.size(); ++idx) - _entries[idx].load(_file); + for (uint idx = 0; idx < _index.size(); ++idx) + _index[idx].load(_file); } CDialogueFile::~CDialogueFile() { @@ -53,8 +53,8 @@ void CDialogueFile::clear() { _file.close(); } -DialogueFileCacheEntry *CDialogueFile::addToCache(int index) { - if (_entries.size() == 0 || index < 0 || index >= (int)_entries.size() +DialogueResource *CDialogueFile::addToCache(int index) { + if (_index.size() == 0 || index < 0 || index >= (int)_index.size() || _cache.empty()) return nullptr; @@ -65,26 +65,34 @@ DialogueFileCacheEntry *CDialogueFile::addToCache(int index) { if (cacheIndex == _cache.size()) return nullptr; - DialogueFileIndexEntry &entry = _entries[index]; - DialogueFileCacheEntry &cacheEntry = _cache[cacheIndex]; + DialogueIndexEntry &indexEntry = _index[index]; + DialogueResource &res = _cache[cacheIndex]; - cacheEntry._active = true; - cacheEntry._offset = entry._offset; - cacheEntry._bytesRead = 0; - cacheEntry._entryPtr = &entry; + res._active = true; + res._offset = indexEntry._offset; + res._bytesRead = 0; + res._entryPtr = &indexEntry; // Figure out the size of the entry - if (index == ((int)_entries.size() - 1)) { - cacheEntry._size = _file.size() - entry._offset; + if (index == ((int)_index.size() - 1)) { + res._size = _file.size() - indexEntry._offset; } else { - cacheEntry._size = _entries[index + 1]._offset - entry._offset; + res._size = _index[index + 1]._offset - indexEntry._offset; } // Return a pointer to the loaded entry - return &cacheEntry; + return &res; } -bool CDialogueFile::read(DialogueFileCacheEntry *cacheEntry, byte *buffer, size_t bytesToRead) { +bool CDialogueFile::closeEntry(DialogueResource *cacheEntry) { + if (!cacheEntry || !cacheEntry->_active) + return false; + + cacheEntry->_active = false; + return true; +} + +bool CDialogueFile::read(DialogueResource *cacheEntry, byte *buffer, size_t bytesToRead) { // Sanity checks that a valid record is passed, and the size can be read if (!cacheEntry || !cacheEntry->_active || !bytesToRead || (cacheEntry->_bytesRead + bytesToRead) > cacheEntry->_size) diff --git a/engines/titanic/true_talk/dialogue_file.h b/engines/titanic/true_talk/dialogue_file.h index 5db91d9c4c..299d01daa8 100644 --- a/engines/titanic/true_talk/dialogue_file.h +++ b/engines/titanic/true_talk/dialogue_file.h @@ -28,37 +28,37 @@ namespace Titanic { -struct DialogueFileIndexEntry { +struct DialogueIndexEntry { uint _v1, _offset; - DialogueFileIndexEntry() : _v1(0), _offset(0) {} + DialogueIndexEntry() : _v1(0), _offset(0) {} void load(Common::SeekableReadStream &s); }; -struct DialogueFileCacheEntry { +struct DialogueResource { bool _active; uint _offset, _bytesRead, _size; - DialogueFileIndexEntry *_entryPtr; + DialogueIndexEntry *_entryPtr; - DialogueFileCacheEntry() : _active(false), _offset(0), + DialogueResource() : _active(false), _offset(0), _bytesRead(0), _size(0), _entryPtr(nullptr) {} /** * Return the size of a cache entry */ - int size() const { return _active ? _size : 0; } + size_t size() const { return _active ? _size : 0; } }; class CDialogueFile { private: Common::File _file; - Common::Array _entries; - Common::Array _cache; + Common::Array _index; + Common::Array _cache; private: /** * Add a dialogue file entry to the active cache */ - DialogueFileCacheEntry *addToCache(int index); + DialogueResource *addToCache(int index); public: CDialogueFile(const CString &filename, uint count); ~CDialogueFile(); @@ -69,23 +69,28 @@ public: void clear(); /** - * Add a dialogue file entry to the active cache + * Sets up a text entry within the dialogue file for access */ - DialogueFileCacheEntry *addToCacheDouble(int index) { + DialogueResource *openTextEntry(int index) { return addToCache(index * 2); } /** - * Add a dialogue file entry to the active cache + * Sets up a wave (sound) entry within the dialogue file for access */ - DialogueFileCacheEntry *addToCacheDouble1(int index) { + DialogueResource *openWaveEntry(int index) { return addToCache(index * 2 + 1); } + /** + * Removes an entry from the cache + */ + bool closeEntry(DialogueResource *cacheEntry); + /** * Read data for a resource */ - bool read(DialogueFileCacheEntry *cacheEntry, byte *buffer, size_t bytesToRead); + bool read(DialogueResource *cacheEntry, byte *buffer, size_t bytesToRead); }; } // End of namespace Titanic diff --git a/engines/titanic/true_talk/title_engine.cpp b/engines/titanic/true_talk/title_engine.cpp index 528c4b12b0..5b8e8d9ef9 100644 --- a/engines/titanic/true_talk/title_engine.cpp +++ b/engines/titanic/true_talk/title_engine.cpp @@ -48,7 +48,7 @@ STtitleEngine::~STtitleEngine() { void STtitleEngine::reset() { _field58 = 0; - _array.clear(); + _indexes.clear(); } void STtitleEngine::setup(int val1, int val2) { diff --git a/engines/titanic/true_talk/title_engine.h b/engines/titanic/true_talk/title_engine.h index e9bc6249eb..ab541ec6f8 100644 --- a/engines/titanic/true_talk/title_engine.h +++ b/engines/titanic/true_talk/title_engine.h @@ -69,7 +69,8 @@ private: Common::PEResources _resources; Common::SeekableReadStream *_stream; int _field58; - Common::Array _array; +public: + Common::Array _indexes; Common::Array _data; public: STtitleEngine(); diff --git a/engines/titanic/true_talk/true_talk_manager.cpp b/engines/titanic/true_talk/true_talk_manager.cpp index 58d92539a5..6552a5db5c 100644 --- a/engines/titanic/true_talk/true_talk_manager.cpp +++ b/engines/titanic/true_talk/true_talk_manager.cpp @@ -44,7 +44,7 @@ CTrueTalkNPC *CTrueTalkManager::_currentNPC; CTrueTalkManager::CTrueTalkManager(CGameManager *owner) : _gameManager(owner), _scripts(&_titleEngine), _currentCharId(0), - _dialogueFile(nullptr), _field14(0) { + _dialogueFile(nullptr), _dialogueIndex(0) { } CTrueTalkManager::~CTrueTalkManager() { @@ -213,7 +213,7 @@ void CTrueTalkManager::start(CTrueTalkNPC *npc, uint id, CViewItem *view) { _titleEngine._scriptHandler->setup(npcScript, roomScript, charId); _currentNPC = nullptr; - setView(npcScript, roomScript, view); + setDialogue(npcScript, roomScript, view); } TTNamedScript *CTrueTalkManager::getTalker(const CString &name) const { @@ -282,7 +282,7 @@ void CTrueTalkManager::loadAssets(CTrueTalkNPC *npc, int charId) { if (!detailsMsg._filename.empty()) { _dialogueFile = new CDialogueFile(detailsMsg._filename, 20); - _field14 = detailsMsg._numValue + 1; + _dialogueIndex = detailsMsg._numValue + 1; } } @@ -298,14 +298,57 @@ void CTrueTalkManager::processInput(CTrueTalkNPC *npc, CTextInputMsg *msg, CView _currentNPC = nullptr; loadAssets(npc, npcScript->charId()); - setView(npcScript, roomScript, view); + setDialogue(npcScript, roomScript, view); } _currentNPC = nullptr; } -void CTrueTalkManager::setView(TTNamedScript *npcScript, TTRoomScript *roomScript, CViewItem *view) { - warning("TODO: CTrueTalkManager::setView"); +void CTrueTalkManager::setDialogue(TTNamedScript *npcScript, TTRoomScript *roomScript, CViewItem *view) { + warning("TODO: CTrueTalkManager::setDialogue"); +} + +#define STRING_BUFFER_SIZE 2048 + +CString CTrueTalkManager::readDialogueString() { + byte buffer[STRING_BUFFER_SIZE]; + CString result; + + for (uint idx = 0; idx < _titleEngine._indexes.size(); ++idx) { + if (idx != 0) + result += " "; + + // Open a text entry from the dialogue file for access + DialogueResource *textRes = _dialogueFile->openTextEntry( + _titleEngine._indexes[idx] - _dialogueIndex); + if (!textRes) + continue; + + size_t entrySize = textRes->size(); + byte *tempBuffer = (entrySize < STRING_BUFFER_SIZE) ? buffer : + new byte[entrySize + 1]; + + _dialogueFile->read(textRes, tempBuffer, entrySize); + buffer[entrySize] = '\0'; + + // Close the resource + _dialogueFile->closeEntry(textRes); + + // Strip off any non-printable characters + for (byte *p = buffer; *p != '\0'; ++p) { + if (*p < 32 || *p > 127) + *p = ' '; + } + + // Add string to result + result += CString((const char *)buffer); + + // Free buffer if one was allocated + if (entrySize >= STRING_BUFFER_SIZE) + delete[] tempBuffer; + } + + return result; } } // End of namespace Titanic diff --git a/engines/titanic/true_talk/true_talk_manager.h b/engines/titanic/true_talk/true_talk_manager.h index c3c25a33e7..3843483e5a 100644 --- a/engines/titanic/true_talk/true_talk_manager.h +++ b/engines/titanic/true_talk/true_talk_manager.h @@ -43,7 +43,7 @@ private: TTScripts _scripts; int _currentCharId; CDialogueFile *_dialogueFile; - int _field14; + int _dialogueIndex; private: /** * Loads the statics for the class @@ -80,7 +80,12 @@ private: */ void loadAssets(CTrueTalkNPC *npc, int charId); - void setView(TTNamedScript *npcScript, TTRoomScript *roomScript, CViewItem *view); + void setDialogue(TTNamedScript *npcScript, TTRoomScript *roomScript, CViewItem *view); + + /** + * Read in a string from the resource + */ + CString readDialogueString(); public: static int _v1; static int _v2; -- cgit v1.2.3