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