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 * CD/drive handling functions
22 */
23
24 #include "common/textconsole.h"
25 #include "tinsel/drives.h"
26 #include "tinsel/scene.h"
27 #include "tinsel/tinsel.h"
28 #include "tinsel/sched.h"
29 #include "tinsel/strres.h"
30
31 namespace Tinsel {
32
33 // FIXME: Avoid non-const global vars
34
35 char g_currentCD = '1';
36
37 static bool g_bChangingCD = false;
38 static char g_nextCD = '\0';
39
40 static uint32 g_lastTime = 0;
41 extern LANGUAGE g_sampleLanguage;
42
43
CdCD(CORO_PARAM)44 void CdCD(CORO_PARAM) {
45 CORO_BEGIN_CONTEXT;
46 CORO_END_CONTEXT(_ctx);
47
48 CORO_BEGIN_CODE(_ctx);
49
50 while (g_bChangingCD) {
51 if (CoroScheduler.getCurrentProcess()) {
52 // FIXME: CdCD gets passed a Common::nullContext in RegisterGlobals() and
53 // PrimeSceneHopper(), because I didn't know how to get a proper
54 // context without converting the whole calling stack to CORO'd
55 // functions. If these functions really get called while a CD
56 // change is requested, this needs to be resolved.
57 if (coroParam == Common::nullContext)
58 error("CdCD needs context");
59 CORO_SLEEP(1);
60 } else
61 error("No current process in CdCD()");
62 }
63
64 CORO_END_CODE;
65 }
66
GetCurrentCD()67 int GetCurrentCD() {
68 // count from 1
69 return (g_currentCD - '1' + 1);
70 }
71
72 static const uint32 cdFlags[] = { fCd1, fCd2, fCd3, fCd4, fCd5, fCd6, fCd7, fCd8 };
73
SetCD(int flags)74 void SetCD(int flags) {
75 if (flags & cdFlags[g_currentCD - '1'])
76 return;
77
78 error("SetCD() problem");
79 }
80
GetCD(int flags)81 int GetCD(int flags) {
82 int i;
83 char cd = '\0';
84
85 if (flags & cdFlags[g_currentCD - '1'])
86 return GetCurrentCD();
87
88 for (i = 0; i < 8; i++) {
89 if (flags & cdFlags[i]) {
90 cd = (char)(i + '1');
91 break;
92 }
93 }
94 assert(i != 8);
95
96 g_nextCD = cd;
97 return cd;
98 }
99
DoCdChange()100 void DoCdChange() {
101 if (g_bChangingCD && (g_system->getMillis() > (g_lastTime + 1000))) {
102 g_lastTime = g_system->getMillis();
103 _vm->_sound->closeSampleStream();
104
105 // Use the filesize of the sample file to determine, for Discworld 2, which CD it is
106 if (TinselV2) {
107 TinselFile f;
108 if (!f.open(_vm->getSampleFile(g_sampleLanguage)))
109 // No CD present
110 return;
111
112 char sampleCdNumber = (f.size() >= (200 * 1024 * 1024)) ? '1' : '2';
113
114 f.close();
115
116 if (g_currentCD != sampleCdNumber)
117 return;
118 }
119
120 _vm->_sound->openSampleFiles();
121 ChangeLanguage(TextLanguage());
122 g_bChangingCD = false;
123 }
124 }
125
SetNextCD(int cdNumber)126 void SetNextCD(int cdNumber) {
127 assert(cdNumber == 1 || cdNumber == 2);
128
129 g_nextCD = (char)(cdNumber + '1' - 1);
130 }
131
GotoCD()132 bool GotoCD() {
133 // WORKAROUND: Somehow, CdDoChange() is called twice... Hopefully, this guard helps
134 if (g_currentCD == g_nextCD)
135 return false;
136
137 g_currentCD = g_nextCD;
138
139 /* if (bNoCD) {
140 strcpy(cdDirectory, hdDirectory);
141 cdLastBit[3] = currentCD;
142 strcat(cdDirectory, cdLastBit);
143 }
144 */
145 g_bChangingCD = true;
146
147 return true;
148 }
149
150 bool TinselFile::_warningShown = false;
151
TinselFile()152 TinselFile::TinselFile() : ReadStreamEndian(TinselV1Mac) {
153 _stream = NULL;
154 }
155
~TinselFile()156 TinselFile::~TinselFile() {
157 delete _stream;
158 }
159
openInternal(const Common::String & filename)160 bool TinselFile::openInternal(const Common::String &filename) {
161 _stream = SearchMan.createReadStreamForMember(filename);
162 if (!_stream)
163 _stream = SearchMan.createReadStreamForMember(filename + ".");
164 return _stream != 0;
165 }
166
open(const Common::String & filename)167 bool TinselFile::open(const Common::String &filename) {
168 if (openInternal(filename))
169 return true;
170
171 if (!TinselV2)
172 return false;
173
174 // Check if the file being requested is the *1.* or *2.* files
175 const char *fname = filename.c_str();
176 const char *p = strchr(fname, '1');
177 if (!p)
178 p = strchr(fname, '2');
179 if (!p || (*(p + 1) != '.'))
180 return false;
181
182 // Form a filename without the CD number character
183 char newFilename[50];
184 strncpy(newFilename, fname, p - fname);
185 strcpy(newFilename + (p - fname), p + 1);
186
187 return openInternal(newFilename);
188 }
189
close()190 void TinselFile::close() {
191 delete _stream;
192 _stream = NULL;
193 }
194
pos() const195 int32 TinselFile::pos() const {
196 assert(_stream);
197 return _stream->pos();
198 }
199
size() const200 int32 TinselFile::size() const {
201 assert(_stream);
202 return _stream->size();
203 }
204
seek(int32 offset,int whence)205 bool TinselFile::seek(int32 offset, int whence) {
206 assert(_stream);
207 return _stream->seek(offset, whence);
208 }
209
eos() const210 bool TinselFile::eos() const {
211 assert(_stream);
212 return _stream->eos();
213 }
214
err() const215 bool TinselFile::err() const {
216 assert(_stream);
217 return _stream->err();
218 }
219
clearErr()220 void TinselFile::clearErr() {
221 assert(_stream);
222 _stream->clearErr();
223 }
224
read(void * dataPtr,uint32 dataSize)225 uint32 TinselFile::read(void *dataPtr, uint32 dataSize) {
226 assert(_stream);
227 return _stream->read(dataPtr, dataSize);
228 }
229
230
231
232
233 } // End of namespace Tinsel
234