1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "titanic/true_talk/dialogue_file.h"
24
25 namespace Titanic {
26
load(Common::SeekableReadStream & s)27 void DialogueIndexEntry::load(Common::SeekableReadStream &s) {
28 _v1 = s.readUint32LE();
29 _offset = s.readUint32LE();
30 }
31
32 /*------------------------------------------------------------------------*/
33
CDialogueFile(const CString & filename,uint count)34 CDialogueFile::CDialogueFile(const CString &filename, uint count) {
35 if (!_file.open(filename))
36 error("Could not locate dialogue file - %s", filename.c_str());
37
38 _cache.resize(count);
39
40 _file.readUint32LE(); // Skip over file Id
41 _index.resize(_file.readUint32LE());
42
43 // Read in the entries
44 for (uint idx = 0; idx < _index.size(); ++idx)
45 _index[idx].load(_file);
46 }
47
~CDialogueFile()48 CDialogueFile::~CDialogueFile() {
49 clear();
50 }
51
clear()52 void CDialogueFile::clear() {
53 _file.close();
54 }
55
addToCache(int index)56 DialogueResource *CDialogueFile::addToCache(int index) {
57 if (_index.size() == 0 || index < 0 || index >= (int)_index.size()
58 || _cache.empty())
59 return nullptr;
60
61 // Scan cache for a free slot
62 uint cacheIndex = 0;
63 while (cacheIndex < _cache.size() && _cache[cacheIndex]._active)
64 ++cacheIndex;
65 if (cacheIndex == _cache.size())
66 return nullptr;
67
68 DialogueIndexEntry &indexEntry = _index[index];
69 DialogueResource &res = _cache[cacheIndex];
70
71 res._active = true;
72 res._offset = indexEntry._offset;
73 res._bytesRead = 0;
74 res._entryPtr = &indexEntry;
75
76 // Figure out the size of the entry
77 if (index == ((int)_index.size() - 1)) {
78 res._size = _file.size() - indexEntry._offset;
79 } else {
80 res._size = _index[index + 1]._offset - indexEntry._offset;
81 }
82
83 // Return a pointer to the loaded entry
84 return &res;
85 }
86
closeEntry(DialogueResource * cacheEntry)87 bool CDialogueFile::closeEntry(DialogueResource *cacheEntry) {
88 if (!cacheEntry || !cacheEntry->_active)
89 return false;
90
91 cacheEntry->_active = false;
92 return true;
93 }
94
read(DialogueResource * cacheEntry,byte * buffer,size_t bytesToRead)95 bool CDialogueFile::read(DialogueResource *cacheEntry, byte *buffer, size_t bytesToRead) {
96 // Sanity checks that a valid record is passed, and the size can be read
97 if (!cacheEntry || !cacheEntry->_active || !bytesToRead
98 || (cacheEntry->_bytesRead + bytesToRead) > cacheEntry->_size)
99 return false;
100
101 // Move to the correct position in the file
102 _file.seek(cacheEntry->_offset + cacheEntry->_bytesRead);
103 bool result = _file.read(buffer, bytesToRead) == bytesToRead;
104 cacheEntry->_bytesRead += bytesToRead;
105
106 return result;
107 }
108
109 } // End of namespace Titanic
110