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 "access/resources.h"
24 #include "access/martian/martian_game.h"
25 #include "access/martian/martian_resources.h"
26 #include "access/martian/martian_room.h"
27 #include "access/martian/martian_scripts.h"
28 #include "access/amazon/amazon_resources.h"
29
30 namespace Access {
31
32 namespace Martian {
33
MartianEngine(OSystem * syst,const AccessGameDescription * gameDesc)34 MartianEngine::MartianEngine(OSystem *syst, const AccessGameDescription *gameDesc) : AccessEngine(syst, gameDesc) {
35 }
36
~MartianEngine()37 MartianEngine::~MartianEngine() {
38 _introObjects = _spec7Objects = nullptr;
39 _skipStart = false;
40 _creditsStream = nullptr;
41 }
42
initObjects()43 void MartianEngine::initObjects() {
44 _room = new MartianRoom(this);
45 _scripts = new MartianScripts(this);
46 }
47
configSelect()48 void MartianEngine::configSelect() {
49 // No implementation required in MM
50 }
51
initVariables()52 void MartianEngine::initVariables() {
53 warning("TODO: initVariables");
54
55 // Set player room and position
56 _player->_roomNumber = 7;
57
58 _inventory->_startInvItem = 0;
59 _inventory->_startInvBox = 0;
60 Common::fill(&_objectsTable[0], &_objectsTable[100], (SpriteResource *)nullptr);
61 _player->_playerOff = false;
62
63 // Setup timers
64 const int TIMER_DEFAULTS[] = { 4, 10, 8, 1, 1, 1, 1, 2 };
65 for (int i = 0; i < 32; ++i) {
66 TimerEntry te;
67 te._initTm = te._timer = (i < 8) ? TIMER_DEFAULTS[i] : 1;
68 te._flag = 1;
69
70 _timers.push_back(te);
71 }
72
73 _player->_playerX = _player->_rawPlayer.x = _res->ROOMTBL[_player->_roomNumber]._travelPos.x;
74 _player->_playerY = _player->_rawPlayer.y = _res->ROOMTBL[_player->_roomNumber]._travelPos.y;
75 _room->_selectCommand = -1;
76 _events->setNormalCursor(CURSOR_CROSSHAIRS);
77 _mouseMode = 0;
78 _numAnimTimers = 0;
79
80 for (int i = 0; i < 60; i++)
81 _travel[i] = 0;
82 _travel[7] = 1;
83
84 for (int i = 0; i < 40; i++)
85 _ask[i] = 0;
86 _ask[33] = 1;
87 }
88
setNoteParams()89 void MartianEngine::setNoteParams() {
90 _events->hideCursor();
91
92 _screen->_orgX1 = 58;
93 _screen->_orgY1 = 124;
94 _screen->_orgX2 = 297;
95 _screen->_orgY2 = 199;
96 _screen->_lColor = 51;
97 _screen->drawRect();
98
99 _events->showCursor();
100 }
101
displayNote(const Common::String & msg)102 void MartianEngine::displayNote(const Common::String &msg) {
103 _fonts._charSet._lo = 1;
104 _fonts._charSet._hi = 8;
105 _fonts._charFor._lo = 0;
106 _fonts._charFor._hi = 255;
107
108 _screen->_maxChars = 40;
109 _screen->_printOrg = _screen->_printStart = Common::Point(59, 124);
110
111 setNoteParams();
112
113 Common::String lines = msg;
114 Common::String line;
115 int width = 0;
116 bool lastLine = false;
117 do {
118 lastLine = _fonts._font1->getLine(lines, _screen->_maxChars * 6, line, width);
119 _bubbleBox->printString(line);
120 _screen->_printOrg = Common::Point(_screen->_printStart.x, _screen->_printOrg.y + 6);
121
122 if (_screen->_printOrg.y == 196) {
123 _events->waitKeyMouse();
124 setNoteParams();
125 _screen->_printOrg = _screen->_printStart;
126 }
127 } while (!lastLine);
128 _events->waitKeyMouse();
129 }
130
doSpecial5(int param1)131 void MartianEngine::doSpecial5(int param1) {
132 warning("TODO: Push midi song");
133 _midi->stopSong();
134 _midi->_byte1F781 = false;
135 _midi->loadMusic(47, 4);
136 _midi->midiPlay();
137 _screen->setDisplayScan();
138 _events->clearEvents();
139 _screen->forceFadeOut();
140 _events->hideCursor();
141 _files->loadScreen("DATA.SC");
142 _events->showCursor();
143 _screen->setIconPalette();
144 _screen->forceFadeIn();
145
146 Resource *cellsRes = _files->loadFile("CELLS00.LZ");
147 _objectsTable[0] = new SpriteResource(this, cellsRes);
148 delete cellsRes;
149
150 _timers[20]._timer = _timers[20]._initTm = 30;
151 Resource *notesRes = _files->loadFile("NOTES.DAT");
152 notesRes->_stream->skip(param1 * 2);
153 int pos = notesRes->_stream->readUint16LE();
154 notesRes->_stream->seek(pos);
155 Common::String msg = "";
156 byte c;
157 while ((c = (char)notesRes->_stream->readByte()) != '\0')
158 msg += c;
159
160 displayNote(msg);
161
162 _midi->stopSong();
163 _midi->freeMusic();
164
165 warning("TODO: Pop Midi");
166 // _midi->_byte1F781 = true;
167 }
168
playGame()169 void MartianEngine::playGame() {
170 // Initialize Martian Memorandum game-specific objects
171 initObjects();
172
173 // Setup the game
174 setupGame();
175 configSelect();
176
177 if (_loadSaveSlot == -1) {
178 // Do introduction
179 doCredits();
180 if (shouldQuit())
181 return;
182
183 // Display Notes screen
184 doSpecial5(4);
185 if (shouldQuit())
186 return;
187 _screen->forceFadeOut();
188 }
189
190 do {
191 _restartFl = false;
192 _screen->clearScreen();
193 _screen->setPanel(0);
194 _screen->forceFadeOut();
195 _events->showCursor();
196
197 initVariables();
198
199 // If there's a pending savegame to load, load it
200 if (_loadSaveSlot != -1) {
201 loadGameState(_loadSaveSlot);
202 _loadSaveSlot = -1;
203 }
204
205 // Execute the room
206 _room->doRoom();
207 } while (_restartFl);
208 }
209
showCredits()210 bool MartianEngine::showCredits() {
211 _events->hideCursor();
212 _screen->clearScreen();
213 _destIn = _screen;
214
215 int posX = _creditsStream->readSint16LE();
216 int posY = 0;
217
218 while(posX != -1) {
219 posY = _creditsStream->readSint16LE();
220 int frameNum = _creditsStream->readSint16LE();
221 _screen->plotImage(_introObjects, frameNum, Common::Point(posX, posY));
222
223 posX = _creditsStream->readSint16LE();
224 }
225
226 posY = _creditsStream->readSint16LE();
227 if (posY == -1) {
228 _events->showCursor();
229 _screen->forceFadeOut();
230 return true;
231 }
232
233 _screen->forceFadeIn();
234 _timers[3]._timer = _timers[3]._initTm = posY;
235
236 while (!shouldQuit() && !_events->isKeyMousePressed() && _timers[3]._timer) {
237 _events->pollEventsAndWait();
238 }
239
240 _events->showCursor();
241 _screen->forceFadeOut();
242
243 if (_events->_rightButton)
244 return true;
245 else
246 return false;
247 }
248
doCredits()249 void MartianEngine::doCredits() {
250 _midi->_byte1F781 = false;
251 _midi->loadMusic(47, 3);
252 _midi->midiPlay();
253 _screen->setDisplayScan();
254 _events->hideCursor();
255 _screen->forceFadeOut();
256 Resource *data = _files->loadFile(41, 1);
257 _introObjects = new SpriteResource(this, data);
258 delete data;
259
260 _files->loadScreen(41, 0);
261 _buffer2.copyFrom(*_screen);
262 _buffer1.copyFrom(*_screen);
263 _events->showCursor();
264 _creditsStream = new Common::MemoryReadStream(CREDIT_DATA, 180);
265
266 if (!showCredits()) {
267 _screen->copyFrom(_buffer2);
268 _screen->forceFadeIn();
269
270 _events->_vbCount = 550;
271 while (!shouldQuit() && !_events->isKeyMousePressed() && _events->_vbCount > 0)
272 _events->pollEventsAndWait();
273
274 _screen->forceFadeOut();
275 while (!shouldQuit() && !_events->isKeyMousePressed()&& !showCredits())
276 _events->pollEventsAndWait();
277
278 warning("TODO: Free word_21E2B");
279 _midi->freeMusic();
280 }
281 }
282
setupGame()283 void MartianEngine::setupGame() {
284 // Load death list
285 _deaths.resize(_res->DEATHS.size());
286 for (uint idx = 0; idx < _deaths.size(); ++idx) {
287 _deaths[idx]._screenId = _res->DEATHS[idx]._screenId;
288 _deaths[idx]._msg = _res->DEATHS[idx]._msg;
289 }
290
291 // Setup timers
292 const int TIMER_DEFAULTS[] = { 4, 10, 8, 1, 1, 1, 1, 2 };
293 for (int i = 0; i < 32; ++i) {
294 TimerEntry te;
295 te._initTm = te._timer = (i < 8) ? TIMER_DEFAULTS[i] : 1;
296 te._flag = 1;
297
298 _timers.push_back(te);
299 }
300
301 // Miscellaneous
302 Martian::MartianResources &res = *((Martian::MartianResources *)_res);
303 _fonts.load(res._font6x6, res._font3x5);
304
305 // Set player room and position
306 _player->_roomNumber = 7;
307 _player->_playerX = _player->_rawPlayer.x = _res->ROOMTBL[_player->_roomNumber]._travelPos.x;
308 _player->_playerY = _player->_rawPlayer.y = _res->ROOMTBL[_player->_roomNumber]._travelPos.y;
309 }
310
showDeathText(Common::String msg)311 void MartianEngine::showDeathText(Common::String msg) {
312 Common::String line = "";
313 int width = 0;
314 bool lastLine;
315 do {
316 lastLine = _fonts._font2->getLine(msg, _screen->_maxChars * 6, line, width);
317 // Draw the text
318 _bubbleBox->printString(line);
319
320 _screen->_printOrg.y += 6;
321 _screen->_printOrg.x = _screen->_printStart.x;
322
323 if (_screen->_printOrg.y == 180) {
324 _events->waitKeyMouse();
325 _screen->copyBuffer(&_buffer2);
326 _screen->_printOrg.y = _screen->_printStart.y;
327 }
328 } while (!lastLine);
329 _events->waitKeyMouse();
330 }
331
dead(int deathId)332 void MartianEngine::dead(int deathId) {
333 // Load and display death screen
334 _events->hideCursor();
335 _screen->forceFadeOut();
336 _files->loadScreen(48, _deaths[deathId]._screenId);
337 _screen->setIconPalette();
338 _buffer2.copyBuffer(_screen);
339 _screen->forceFadeIn();
340 _events->showCursor();
341
342 // Setup fonts
343 _fonts._charSet._hi = 10;
344 _fonts._charSet._lo = 1;
345 _fonts._charFor._lo = 247;
346 _fonts._charFor._hi = 255;
347 _screen->_maxChars = 50;
348 _screen->_printOrg = Common::Point(24, 18);
349 _screen->_printStart = Common::Point(24, 18);
350
351 // Display death message
352 showDeathText(_deaths[deathId]._msg);
353
354 _screen->forceFadeOut();
355 _room->clearRoom();
356 freeChar();
357
358 // The original was jumping to the restart label in main
359 _restartFl = true;
360 _events->pollEvents();
361 }
362
363 } // End of namespace Martian
364
365 } // End of namespace Access
366