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 "hopkins/computer.h"
24
25 #include "hopkins/font.h"
26 #include "hopkins/files.h"
27 #include "hopkins/globals.h"
28 #include "hopkins/graphics.h"
29 #include "hopkins/hopkins.h"
30 #include "hopkins/objects.h"
31
32 #include "common/system.h"
33 #include "common/file.h"
34 #include "common/textconsole.h"
35
36 namespace Hopkins {
37
ComputerManager(HopkinsEngine * vm)38 ComputerManager::ComputerManager(HopkinsEngine *vm) {
39 _vm = vm;
40
41 for (int i = 0; i < ARRAYSIZE(_menuText); i++) {
42 _menuText[i]._lineSize = 0;
43 memset(_menuText[i]._line, 0, ARRAYSIZE(_menuText[0]._line));
44 }
45 Common::fill(&_inputBuf[0], &_inputBuf[200], '\0');
46 _breakoutSpr = NULL;
47 _textColor = 0;
48 _breakoutLevel = (int16 *)NULL;
49 _breakoutBrickNbr = 0;
50 _breakoutScore = 0;
51 _breakoutLives = 0;
52 _breakoutSpeed = 0;
53 _ballRightFl = false;
54 _ballUpFl = false;
55 _breakoutLevelNbr = 0;
56 _padPositionX = 0;
57 _minBreakoutMoveSpeed = 0;
58 _maxBreakoutMoveSpeed = 0;
59 _lastBreakoutMoveSpeed = 0;
60 _lowestHiScore = 0;
61 }
62
63 /**
64 * Sets up textual entry mode. Used by the code for Hopkins computer.
65 */
setVideoMode()66 void ComputerManager::setVideoMode() {
67 setTextMode();
68 }
69
70 /**
71 * Sets up Textual entry mode
72 */
setTextMode()73 void ComputerManager::setTextMode() {
74 _vm->_graphicsMan->clearPalette();
75 _vm->_graphicsMan->clearScreen();
76
77 _vm->_graphicsMan->_lineNbr = SCREEN_WIDTH;
78 _vm->_fontMan->_font = _vm->_globals->freeMemory(_vm->_fontMan->_font);
79
80 Common::String filename = "STFONT.SPR";
81 Common::File f;
82 if (!f.exists(filename))
83 filename = "FONTE.SPR"; // Used by the BeOS and OS/2 versions as an alternative
84 _vm->_fontMan->_font = _vm->_fileIO->loadFile(filename);
85 _vm->_fontMan->_fontFixedWidth = 8;
86 _vm->_fontMan->_fontFixedHeight = 8;
87
88 _vm->_graphicsMan->loadImage("WINTEXT");
89 _vm->_graphicsMan->fadeInLong();
90 loadMenu();
91 _vm->_events->_mouseFl = false;
92 }
93
94 /**
95 * Clear the screen
96 */
clearScreen()97 void ComputerManager::clearScreen() {
98 _vm->_graphicsMan->loadImage("WINTEXT");
99 _vm->_graphicsMan->fadeInLong();
100 }
101
102 /**
103 * Sets the text mode color
104 */
setTextColor(int col)105 void ComputerManager::setTextColor(int col) {
106 _textColor = col;
107 }
108
109 /**
110 * Sets the text position.
111 * @param yp Y position
112 * @param xp X position
113 * @remarks Yes, the reverse co-ordinate pair is really like that in the original game.
114 */
setTextPosition(int yp,int xp)115 void ComputerManager::setTextPosition(int yp, int xp) {
116 _textPosition.x = xp << 3;
117 _textPosition.y = yp << 4;
118 }
119
120 /**
121 * Show a computer in the FBI office
122 * @param mode Which computer to display
123 */
showComputer(ComputerEnum mode)124 void ComputerManager::showComputer(ComputerEnum mode) {
125 _vm->_events->_escKeyFl = false;
126 _vm->_graphicsMan->resetDirtyRects();
127 setVideoMode();
128 setTextColor(4);
129 setTextPosition(2, 4);
130 if (mode == COMPUTER_HOPKINS)
131 outText(Common::String(_menuText[0]._line));
132 else if (mode == COMPUTER_SAMANTHA)
133 outText(Common::String(_menuText[1]._line));
134 else // COMPUTER_PUBLIC
135 outText(Common::String(_menuText[2]._line));
136
137 setTextColor(1);
138 if (mode == COMPUTER_PUBLIC) {
139 setTextPosition(10, 8);
140 outText(Common::String(_menuText[3]._line));
141 }
142 setTextPosition(12, 28);
143 outText(Common::String(_menuText[4]._line));
144 setTextPosition(14, 35);
145
146 displayMessage(280, 224, 8);
147 bool passwordMatch = false;
148 if ((mode == COMPUTER_HOPKINS) && !strcmp(_inputBuf, "HOPKINS"))
149 passwordMatch = true;
150 else if ((mode == COMPUTER_SAMANTHA) && !strcmp(_inputBuf, "328MHZA"))
151 passwordMatch = true;
152 else if ((mode == COMPUTER_PUBLIC) && !strcmp(_inputBuf, "ALLFREE"))
153 passwordMatch = true;
154
155 if (passwordMatch) {
156 while (!_vm->shouldQuit()) {
157 _vm->_events->_escKeyFl = false;
158 clearScreen();
159 setTextColor(4);
160 setTextPosition(2, 4);
161 if (mode == COMPUTER_HOPKINS)
162 outText(Common::String(_menuText[0]._line));
163 else if (mode == COMPUTER_SAMANTHA)
164 outText(Common::String(_menuText[1]._line));
165 else if (mode == COMPUTER_PUBLIC)
166 outText(Common::String(_menuText[2]._line));
167 setTextColor(15);
168 setTextPosition(8, 25);
169 setTextColor(15);
170 outText2(Common::String(_menuText[6]._line));
171 setTextPosition(20, 25);
172 outText2(Common::String(_menuText[7]._line));
173 if (mode == COMPUTER_HOPKINS) {
174 setTextPosition(10, 25);
175 outText2(Common::String(_menuText[8]._line));
176 setTextPosition(12, 25);
177 outText2(Common::String(_menuText[9]._line));
178 setTextPosition(14, 25);
179 outText2(Common::String(_menuText[10]._line));
180 setTextPosition(16, 25);
181 outText2(Common::String(_menuText[11]._line));
182 } else if (mode == COMPUTER_SAMANTHA) {
183 setTextPosition(10, 25);
184 // outText2(Common::String(_menuText[0x95A])); <=== CHECKME: Unexpected value! replaced by the following line, for consistancy
185 outText2(Common::String(_menuText[12]._line));
186 setTextPosition(12, 25);
187 outText2(Common::String(_menuText[13]._line));
188 setTextPosition(14, 25);
189 outText2(Common::String(_menuText[14]._line));
190 setTextPosition(16, 25);
191 outText2(Common::String(_menuText[15]._line));
192 setTextPosition(18, 25);
193 outText2(Common::String(_menuText[16]._line));
194 }
195
196 bool numericFlag = false;
197 char keyPressed;
198 do {
199 keyPressed = _vm->_events->waitKeyPress();
200 if (_vm->shouldQuit())
201 return;
202
203 if ((keyPressed >= '0') && (keyPressed <= '9'))
204 numericFlag = true;
205 } while (!numericFlag);
206
207 // 0 - Quit
208 if (keyPressed == '0')
209 break;
210 // 1 - Games
211 if (keyPressed == '1') {
212 displayGamesSubMenu();
213 } else if (mode == COMPUTER_HOPKINS) {
214 clearScreen();
215 setTextColor(4);
216 setTextPosition(2, 4);
217 outText(Common::String(_menuText[0]._line));
218 setTextColor(15);
219 switch (keyPressed) {
220 case '2':
221 readText(1);
222 break;
223 case '3':
224 readText(2);
225 break;
226 case '4':
227 readText(3);
228 break;
229 case '5':
230 readText(4);
231 break;
232 default:
233 break;
234 }
235 } else if (mode == COMPUTER_SAMANTHA) {
236 clearScreen();
237 setTextColor(4);
238 setTextPosition(2, 4);
239 outText(Common::String(_menuText[1]._line));
240 setTextColor(15);
241 switch (keyPressed) {
242 case '2':
243 readText(6);
244 break;
245 case '3':
246 readText(7);
247 break;
248 case '4':
249 readText(8);
250 break;
251 case '5':
252 readText(9);
253 break;
254 case '6':
255 readText(10);
256 _vm->_globals->_saveData->_data[svField270] = 4;
257 break;
258 default:
259 break;
260 }
261 }
262 }
263 _vm->_graphicsMan->clearScreen();
264 _vm->_graphicsMan->updateScreen();
265 restoreFBIRoom();
266 } else {
267 // Password doesn't match - Access Denied
268 setTextColor(4);
269 setTextPosition(16, 25);
270 outText(Common::String(_menuText[5]._line));
271 _vm->_events->refreshScreenAndEvents();
272 _vm->_events->delay(1000);
273
274 memset(_vm->_graphicsMan->_frontBuffer, 0, 307199);
275 _vm->_graphicsMan->clearScreen();
276 _vm->_graphicsMan->updateScreen();
277 restoreFBIRoom();
278 _vm->_events->mouseOff();
279 }
280
281 if (mode == COMPUTER_HOPKINS)
282 _vm->_globals->_exitId = 13;
283 else // Free access or Samantha
284 _vm->_globals->_exitId = 14;
285
286 _vm->_graphicsMan->resetDirtyRects();
287 }
288
289 static const char _englishText[] =
290 "% ****** FBI COMPUTER NUMBER 4985 ****** J.HOPKINS COMPUTER ******\n"
291 "% ****** FBI COMPUTER NUMBER 4998 ****** S.COLLINS COMPUTER ******\n"
292 "% ****** FBI COMPUTER NUMBER 4997 ****** ACCES FREE COMPUTER ******\n"
293 "% PASSWORD IS: ALLFREE\n% ENTER CURRENT PASSWORD\n"
294 "% ****** ACCES DENIED ******\n"
295 "% 1) *** GAME ***\n"
296 "% 0) QUIT COMPUTER\n"
297 "% 2) STRANGE CADAVER\n"
298 "% 3) STRANGE CADAVER\n"
299 "% 4) SENATOR FERGUSSON\n"
300 "% 5) DOG KILLER\n"
301 "% 2) SCIENTIST KIDNAPPED.\n"
302 "% 3) SCIENTIST KIDNAPPED (next).\n"
303 "% 4) SCIENTIST KIDNAPPED (next).\n"
304 "% 5) SCIENTIST KIDNAPPED (next).\n"
305 "% 6) SCIENTIST KIDNAPPED (next).\n"
306 "%% fin\n";
307
308 static const char _frenchText[] =
309 "% ****** FBI COMPUTER NUMBER 4985 ****** J.HOPKINS COMPUTER ******\n"
310 "% ****** FBI COMPUTER NUMBER 4998 ****** S.COLLINS COMPUTER ******\n"
311 "% ****** FBI COMPUTER NUMBER 4997 ****** ACCES FREE COMPUTER ******\n"
312 "% PASSWORD IS: ALLFREE\n"
313 "% ENTER CURRENT PASSWORD\n"
314 "% ****** ACCES DENIED ******\n"
315 "% 1) *** CASSE BRIQUE ***\n"
316 "% 0) QUITTER L'ORDINATEUR\n"
317 "% 2) CADAVRE SANS TETE\n"
318 "% 3) CADAVRE SANS TETE\n"
319 "% 4) AGRESSION DU SENATEUR\n"
320 "% 5) LES CHIENS TUEURS\n"
321 "% 2) DISPARITIONS DE CHERCHEURS.\n"
322 "% 3) DISPARITIONS (suite).\n"
323 "% 4) DISPARITIONS (suite).\n"
324 "% 5) DISPARITIONS (suite).\n"
325 "% 6) DISPARITIONS (suite).\n"
326 "%% fin\n";
327
328 static const char _spanishText[] =
329 "% **** ORDENADOR DEL FBI NUMERO 4985 **** ORDENADOR J.HOPKINS *****\n"
330 "% **** ORDENADOR DEL FBI NUMERO 4998 **** ORDENADOR S.COLLINS *****\n"
331 "% *** ORDENADOR DEL FBI NUMERO 4997 *** ORDENADOR DE ACCESO LIBRE ***\n"
332 "% LA CONTRASE\xA5" "A ES: ALLFREE\n"
333 "% ESCRIBE CONTRASE\xA5" "A ACTUAL\n"
334 "% **** ACCESO DENEGADO ****\n"
335 "% 1) *** JUEGO ***\n"
336 "% 0) SALIR DEL ORDENADOR\n"
337 "% 2) CADAVER EXTRA\xA5" "O\n"
338 "% 3) CADAVER EXTRA\xA5" "O\n"
339 "% 4) SENADOR FERGUSSON\n"
340 "% 5) MATAPERROS\n"
341 "% 2) CIENTIFICO SECUESTRADO.\n"
342 "% 3) CIENTIFICO SECUESTRADO (siguiente).\n"
343 "% 4) CIENTIFICO SECUESTRADO (siguiente).\n"
344 "% 5) CIENTIFICO SECUESTRADO (siguiente).\n"
345 "% 6) CIENTIFICO SECUESTRADO (siguiente).\n"
346 "%% fin\n";
347
348 /**
349 * Load Menu data
350 */
loadMenu()351 void ComputerManager::loadMenu() {
352 debug(9, "ComputerManager::loadMenu()");
353 char *ptr;
354 if (_vm->_fileIO->fileExists("COMPUTAN.TXT")) {
355 ptr = (char *)_vm->_fileIO->loadFile("COMPUTAN.TXT");
356 } else {
357 switch (_vm->_globals->_language) {
358 case LANG_FR:
359 ptr = (char *)_vm->_globals->allocMemory(sizeof(_frenchText));
360 Common::strlcpy(ptr, _frenchText, sizeof(_frenchText));
361 break;
362 case LANG_SP:
363 ptr = (char *)_vm->_globals->allocMemory(sizeof(_spanishText));
364 Common::strlcpy(ptr, _spanishText, sizeof(_spanishText));
365 break;
366 default:
367 ptr = (char *)_vm->_globals->allocMemory(sizeof(_englishText));
368 Common::strlcpy(ptr, _englishText, sizeof(_englishText));
369 break;
370 }
371 }
372
373 char *tmpPtr = ptr;
374 int lineNum = 0;
375
376 const char lineSep = tmpPtr[0];
377
378 while (tmpPtr[0] != '\0' && lineNum < ARRAYSIZE(_menuText)) {
379 if (tmpPtr[0] == '%' && tmpPtr[1] == '%') {
380 // End of file marker found - Break out of parse loop
381 break;
382 }
383
384 if (tmpPtr[0] == lineSep) {
385 int strPos = 0;
386 while (strPos < ARRAYSIZE(_menuText[0]._line)) {
387 char curChar = tmpPtr[strPos + 2];
388 if (curChar == '\0' || curChar == lineSep || curChar == 0x0a) // Line Feed
389 break;
390 _menuText[lineNum]._line[strPos++] = curChar;
391 }
392
393 if (strPos < ARRAYSIZE(_menuText[0]._line)) {
394 _menuText[lineNum]._line[strPos] = 0;
395 _menuText[lineNum]._lineSize = strPos - 1;
396 }
397
398 if (strPos != 0) {
399 debug(9, "_menuText[%d]._line (size: %d): \"%s\"", lineNum, _menuText[lineNum]._lineSize, _menuText[lineNum]._line);
400 ++lineNum;
401 }
402 }
403 ++tmpPtr;
404 }
405
406 _vm->_globals->freeMemory((byte *)ptr);
407 }
408
displayMessage(int xp,int yp,int textIdx)409 void ComputerManager::displayMessage(int xp, int yp, int textIdx) {
410 char curChar;
411
412 int x1 = xp;
413 int x2 = 0;
414
415 int textIndex = 0;
416 bool oldMouseFlag = _vm->_events->_mouseFl;
417 _vm->_events->_mouseFl = false;
418
419 _vm->_fontMan->displayTextVesa(xp, yp, "_", 252);
420 do {
421 curChar = _vm->_events->waitKeyPress();
422 if (_vm->shouldQuit())
423 return;
424
425 char mappedChar = '*';
426
427 if ((curChar == '-') || ((curChar >= '0') && (curChar <= '9')) || ((curChar >= 'A') && (curChar <= 'Z')))
428 mappedChar = curChar;
429 else if ((curChar >= 'a') && (curChar <= 'z'))
430 mappedChar = curChar - 32;
431
432 // BackSpace
433 if (curChar == 8 && textIndex > 0) {
434 _inputBuf[textIndex--] = 0;
435 x1 -= _vm->_fontMan->_fontFixedWidth;
436 x2 = x1 + 2 * _vm->_fontMan->_fontFixedWidth;
437 _vm->_graphicsMan->copyRect(_vm->_graphicsMan->_backBuffer, x1, yp, 3 * _vm->_fontMan->_fontFixedWidth, 12, _vm->_graphicsMan->_frontBuffer, x1, yp);
438 _vm->_graphicsMan->addDirtyRect(x1, yp, x2, yp + 12);
439 _vm->_fontMan->displayTextVesa(x1, yp, "_", 252);
440 }
441 if (mappedChar != '*') {
442 char newChar = mappedChar;
443 _vm->_graphicsMan->copyRect(_vm->_graphicsMan->_backBuffer, x1, yp, _vm->_fontMan->_fontFixedWidth, 12, _vm->_graphicsMan->_frontBuffer, x1, yp);
444 _vm->_graphicsMan->addDirtyRect(x1, yp, _vm->_fontMan->_fontFixedWidth + x1, yp + 12);
445 _inputBuf[textIndex] = newChar;
446
447 Common::String charString = Common::String::format("%c_", newChar);
448 _vm->_fontMan->displayTextVesa(x1, yp, charString, 252);
449 ++textIndex;
450 x1 += _vm->_fontMan->_fontFixedWidth;
451 }
452 _vm->_events->refreshScreenAndEvents();
453 } while (textIndex != textIdx && curChar != 13);
454
455 _vm->_graphicsMan->copyRect(_vm->_graphicsMan->_backBuffer, x1, yp, _vm->_fontMan->_fontFixedWidth, 12, _vm->_graphicsMan->_frontBuffer, x1, yp);
456 _vm->_graphicsMan->addDirtyRect(x1, yp, _vm->_fontMan->_fontFixedWidth + x1, yp + 12);
457
458 _vm->_events->refreshScreenAndEvents();
459 _inputBuf[textIndex] = 0;
460 _vm->_events->_mouseFl = oldMouseFlag;
461 }
462
463 /**
464 * Outputs a text string
465 */
outText(const Common::String & msg)466 void ComputerManager::outText(const Common::String &msg) {
467 _vm->_fontMan->renderTextDisplay(_textPosition.x, _textPosition.y, msg, _textColor);
468 }
469
470 /**
471 * Outputs a text string
472 */
outText2(const Common::String & msg)473 void ComputerManager::outText2(const Common::String &msg) {
474 _vm->_fontMan->displayTextVesa(_textPosition.x, _textPosition.y, msg, _textColor);
475 }
476
477 /**
478 * Restores the scene for the FBI headquarters room
479 */
restoreFBIRoom()480 void ComputerManager::restoreFBIRoom() {
481 _vm->_graphicsMan->fadeOutShort();
482
483 _vm->_globals->freeMemory(_vm->_fontMan->_font);
484 _vm->_fontMan->_font = _vm->_fileIO->loadFile("FONTE3.SPR");
485 _vm->_fontMan->_fontFixedWidth = 12;
486 _vm->_fontMan->_fontFixedHeight = 21;
487
488 _vm->_events->_mouseFl = true;
489 }
490
491 /**
492 * Display texts for the given menu entry
493 */
readText(int idx)494 void ComputerManager::readText(int idx) {
495 _vm->_events->_escKeyFl = false;
496
497 Common::String filename;
498 switch (_vm->_globals->_language) {
499 case LANG_EN:
500 filename = "THOPKAN.TXT";
501 break;
502 case LANG_FR:
503 filename = "THOPK.TXT";
504 break;
505 case LANG_SP:
506 filename = "THOPKES.TXT";
507 break;
508 default:
509 break;
510 }
511
512 byte *ptr = _vm->_fileIO->loadFile(filename);
513 uint16 fileSize = _vm->_fileIO->fileSize(filename);
514 int pos;
515 for (pos = 0; pos < fileSize; pos++) {
516 if (ptr[pos] == '%') {
517 Common::String numStr = Common::String::format("%c%c", ptr[pos + 1], ptr[pos + 2]);
518 if (idx == atol(numStr.c_str()))
519 break;
520 }
521 }
522 if (pos > fileSize - 3)
523 error("Error with Hopkins computer file");
524
525 pos += 3;
526 int lineNum = 5;
527 Common::String curStr = "";
528 byte curChar;
529 do {
530 curChar = ptr[pos];
531 if (curChar == 13) {
532 setTextPosition(lineNum, 1);
533 outText(curStr);
534
535 ++lineNum;
536 _vm->_events->refreshScreenAndEvents();
537 curStr = "";
538 } else if (curChar != '%') {
539 curStr += curChar;
540 }
541 ++pos;
542 assert(pos <= fileSize);
543 } while (curChar != '%');
544
545 _vm->_events->waitKeyPress();
546 ptr = _vm->_globals->freeMemory(ptr);
547 }
548
549 /**
550 * Display breakout when Games sub-menu is selected
551 */
displayGamesSubMenu()552 void ComputerManager::displayGamesSubMenu() {
553 const byte *oldSpriteData = _vm->_objectsMan->_sprite[0]._spriteData;
554 uint oldSpeed = _vm->_globals->_speed;
555
556 _vm->_globals->_speed = 1;
557 _vm->_events->changeMouseCursor(0);
558 _breakoutSpr = NULL;
559 _vm->_events->_breakoutFl = true;
560 _breakoutLevel = (int16 *)NULL;
561 _breakoutBrickNbr = 0;
562 _breakoutScore = 0;
563 _breakoutLives = 5;
564 _breakoutSpeed = 1;
565 _ballRightFl = false;
566 _ballUpFl = false;
567 _breakoutLevelNbr = 0;
568 _vm->_graphicsMan->_minY = 0;
569 _vm->_graphicsMan->_maxX = 320;
570 _vm->_graphicsMan->_maxY = 200;
571 _vm->_soundMan->loadSample(1, "SOUND37.WAV");
572 _vm->_soundMan->loadSample(2, "SOUND38.WAV");
573 _vm->_soundMan->loadSample(3, "SOUND39.WAV");
574 _breakoutSpr = _vm->_fileIO->loadFile("CASSE.SPR");
575 loadHiscore();
576 setModeVGA256();
577
578 newLevel();
579 _vm->_graphicsMan->updateScreen();
580
581 playBreakout();
582 _vm->_graphicsMan->resetDirtyRects();
583 _breakoutSpr = _vm->_globals->freeMemory(_breakoutSpr);
584 _breakoutLevel = (int16 *)_vm->_globals->freeMemory((byte *)_breakoutLevel);
585 _vm->_objectsMan->_sprite[0]._spriteData = oldSpriteData;
586
587 _vm->_soundMan->removeSample(1);
588 _vm->_soundMan->removeSample(2);
589 _vm->_soundMan->removeSample(3);
590 _vm->_globals->_speed = oldSpeed;
591 _vm->_events->_breakoutFl = false;
592 setVideoMode();
593 setTextColor(15);
594 clearScreen();
595 _vm->_graphicsMan->_maxX = 680;
596 _vm->_graphicsMan->_minY = 0;
597 _vm->_graphicsMan->_maxY = 460;
598 }
599
600 /**
601 * Load Highscore from file
602 */
loadHiscore()603 void ComputerManager::loadHiscore() {
604 byte *ptr = _vm->_globals->allocMemory(100);
605 memset(ptr, 0, 100);
606
607 if (_vm->_saveLoad->saveExists(_vm->getTargetName() + "-highscore.dat"))
608 _vm->_saveLoad->load(_vm->getTargetName() + "-highscore.dat", ptr);
609
610 for (int scoreIndex = 0; scoreIndex < 6; ++scoreIndex) {
611 _score[scoreIndex]._name = " ";
612 _score[scoreIndex]._score = " ";
613
614 for (int i = 0; i < 6; ++i) {
615 char nextChar = ptr[(16 * scoreIndex) + i];
616 if (!nextChar)
617 nextChar = ' ';
618 _score[scoreIndex]._name.setChar(nextChar, i);
619 }
620
621 for (int i = 0; i < 9; ++i) {
622 char nextChar = ptr[(scoreIndex * 16) + 6 + i];
623 if (!nextChar)
624 nextChar = '0';
625 _score[scoreIndex]._score.setChar(nextChar, i);
626 }
627 }
628
629 _lowestHiScore = atol(_score[5]._score.c_str());
630 _vm->_globals->freeMemory(ptr);
631 }
632
633 /**
634 * VGA 256 col
635 */
setModeVGA256()636 void ComputerManager::setModeVGA256() {
637 _vm->_graphicsMan->clearScreen();
638 _vm->_graphicsMan->clearPalette();
639 _vm->_graphicsMan->setScreenWidth(320);
640 }
641
642 /**
643 * Load new level
644 */
newLevel()645 void ComputerManager::newLevel() {
646 _vm->_objectsMan->removeSprite(0);
647 _vm->_objectsMan->removeSprite(1);
648 ++_breakoutLives;
649 if (_breakoutLives > 11)
650 _breakoutLives = 11;
651 _vm->_graphicsMan->loadVgaImage("CASSEF.PCX");
652 displayLives();
653 _breakoutLevel = (int16 *)_vm->_globals->freeMemory((byte *)_breakoutLevel);
654
655 ++_breakoutLevelNbr;
656 Common::String file;
657 Common::File f;
658 while (!_vm->shouldQuit()) {
659 file = Common::String::format("TAB%d.TAB", _breakoutLevelNbr);
660 if (f.open(file))
661 break;
662
663 _breakoutLevelNbr = 1;
664 }
665 f.close();
666
667 _breakoutLevel = (int16 *)_vm->_fileIO->loadFile(file);
668 displayBricks();
669
670 _vm->_objectsMan->addStaticSprite(_breakoutSpr, Common::Point(150, 192), 0, 13, 0, false, 0, 0);
671 _vm->_objectsMan->addStaticSprite(_breakoutSpr, Common::Point(164, 187), 1, 14, 0, false, 0, 0);
672
673 _ballPosition = Common::Point(164, 187);
674 _padPositionX = 150;
675 _vm->_objectsMan->animateSprite(0);
676 _vm->_objectsMan->animateSprite(1);
677
678 _vm->_events->mouseOn();
679 _vm->_soundMan->playSample(3, 5);
680 }
681
682 /**
683 * Display bricks in breakout game
684 */
displayBricks()685 void ComputerManager::displayBricks() {
686 _breakoutBrickNbr = 0;
687 _breakoutSpeed = 1;
688 int16 *level = _breakoutLevel;
689
690 for (int levelIdx = 0; ; levelIdx += 6) {
691 int cellLeft = (int16)FROM_LE_16(level[levelIdx]);
692 if (cellLeft == -1)
693 break;
694 int cellTop = FROM_LE_16(level[levelIdx + 1]);
695 int cellType = FROM_LE_16(level[levelIdx + 4]);
696
697 if (cellType <= 6)
698 ++_breakoutBrickNbr;
699
700 switch (cellType) {
701 case 1:
702 _vm->_graphicsMan->fastDisplay2(_breakoutSpr, cellLeft, cellTop, 21);
703 break;
704 case 2:
705 _vm->_graphicsMan->fastDisplay2(_breakoutSpr, cellLeft, cellTop, 22);
706 break;
707 case 3:
708 _vm->_graphicsMan->fastDisplay2(_breakoutSpr, cellLeft, cellTop, 17);
709 break;
710 case 4:
711 _vm->_graphicsMan->fastDisplay2(_breakoutSpr, cellLeft, cellTop, 20);
712 break;
713 case 5:
714 _vm->_graphicsMan->fastDisplay2(_breakoutSpr, cellLeft, cellTop, 19);
715 break;
716 case 6:
717 _vm->_graphicsMan->fastDisplay2(_breakoutSpr, cellLeft, cellTop, 18);
718 break;
719 case 31:
720 _vm->_graphicsMan->fastDisplay2(_breakoutSpr, cellLeft, cellTop, 23);
721 break;
722 default:
723 break;
724 }
725 }
726
727 displayScore();
728
729 // Refresh the entire screen
730 _vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
731 _vm->_graphicsMan->updateScreen();
732 }
733
734 /**
735 * Display Lives in breakout game
736 */
displayLives()737 void ComputerManager::displayLives() {
738 for (int i = 0, xp = 10; i <= 11; i++, xp += 7)
739 _vm->_graphicsMan->fastDisplay2(_breakoutSpr, xp, 10, 15);
740
741 for (int i = 0, xp = 10; i < _breakoutLives - 1; i++, xp += 7)
742 _vm->_graphicsMan->fastDisplay2(_breakoutSpr, xp, 10, 14);
743
744 _vm->_graphicsMan->updateScreen();
745 }
746
747 /**
748 * Main function for breakout game
749 */
playBreakout()750 void ComputerManager::playBreakout() {
751 int lastBreakoutEvent = 0;
752 while (!_vm->shouldQuit()) {
753 while (!_vm->shouldQuit()) {
754 // Set up the racket and ball
755 _vm->_events->mouseOff();
756 _ballPosition = Common::Point(_padPositionX + 14, 187);
757 _vm->_objectsMan->setSpriteY(1, 187);
758 _vm->_objectsMan->setSpriteX(1, _ballPosition.x);
759
760 _vm->_graphicsMan->resetDirtyRects();
761 _vm->_events->refreshScreenAndEvents();
762 _vm->_graphicsMan->fadeInBreakout();
763
764 // Wait for mouse press to start playing
765 do {
766 _padPositionX = _vm->_events->getMouseX();
767 if (_vm->_events->_mousePos.x <= 4)
768 _padPositionX = 5;
769 if (_padPositionX > 282)
770 _padPositionX = 282;
771 _vm->_objectsMan->setSpriteX(0, _padPositionX);
772 _vm->_objectsMan->setSpriteX(1, _padPositionX + 14);
773 _vm->_objectsMan->setSpriteY(1, 187);
774 _vm->_events->refreshScreenAndEvents();
775 } while (!_vm->shouldQuit() && _vm->_events->getMouseButton() != 1);
776
777 _breakoutSpeed = 1;
778 _ballPosition = Common::Point(_padPositionX + 14, 187);
779 _ballRightFl = (_padPositionX > 135);
780 _ballUpFl = false;
781
782 // Play loop
783 do {
784 _vm->_soundMan->checkSounds();
785
786 _padPositionX = _vm->_events->getMouseX();
787 if (_vm->_events->_mousePos.x <= 4)
788 _padPositionX = 5;
789 if (_padPositionX > 282)
790 _padPositionX = 282;
791 _vm->_objectsMan->setSpriteX(0, _padPositionX);
792 lastBreakoutEvent = moveBall();
793 _vm->_events->refreshScreenAndEvents();
794 } while (!_vm->shouldQuit() && !lastBreakoutEvent);
795 if (lastBreakoutEvent != 1)
796 break;
797
798 --_breakoutLives;
799
800 if (_breakoutLives) {
801 displayLives();
802 if (_breakoutLives)
803 continue;
804 }
805
806 _vm->_graphicsMan->fadeOutBreakout();
807 _vm->_events->mouseOn();
808 _vm->_objectsMan->removeSprite(0);
809 _vm->_objectsMan->removeSprite(1);
810 if (_breakoutScore > _lowestHiScore)
811 getScoreName();
812 if (displayHiscores() != 1)
813 break;
814
815 _breakoutBrickNbr = 0;
816 _breakoutScore = 0;
817 _breakoutLives = 4;
818 _breakoutSpeed = 1;
819 _ballRightFl = false;
820 _ballUpFl = false;
821 _breakoutLevelNbr = 0;
822 loadHiscore();
823 newLevel();
824 }
825 if (lastBreakoutEvent != 2)
826 return;
827 _vm->_graphicsMan->fadeOutBreakout();
828 newLevel();
829 }
830 }
831
832 /**
833 * Show the high scores for the Breakout game
834 * @return The selected button index: 1 = Game, 2 = Quit
835 */
displayHiscores()836 int ComputerManager::displayHiscores() {
837 _vm->_graphicsMan->resetDirtyRects();
838 loadHiscore();
839 _vm->_graphicsMan->loadVgaImage("HISCORE.PCX");
840 byte *ptr = _vm->_fileIO->loadFile("ALPHA.SPR");
841 _vm->_graphicsMan->setColorPercentage(252, 100, 100, 100);
842 _vm->_graphicsMan->setColorPercentage(253, 100, 100, 100);
843 _vm->_graphicsMan->setColorPercentage(251, 100, 100, 100);
844 _vm->_graphicsMan->setColorPercentage(254, 0, 0, 0);
845
846 int yp;
847 // Loop for displaying the scores
848 for (int scoreIndex = 0; scoreIndex <= 5; scoreIndex++) {
849 yp = 19 * scoreIndex;
850 yp += 46;
851
852 // Display the characters of the name
853 for (int i = 0; i < 6; i++)
854 displayHiscoreLine(ptr, 9 * i + 69, yp, _score[scoreIndex]._name[i]);
855
856 // Display the digits of the score
857 for (int i = 0; i < 9; i++)
858 displayHiscoreLine(ptr, 9 * i + 199, yp, _score[scoreIndex]._score[i]);
859 }
860
861 _vm->_graphicsMan->fadeInBreakout();
862 _vm->_graphicsMan->resetDirtyRects();
863 int buttonIndex = 0;
864 do {
865 _vm->_events->refreshEvents();
866 int xp = _vm->_events->getMouseX();
867 yp = _vm->_events->getMouseY();
868
869 if (_vm->_events->getMouseButton() == 1 && ABS(xp - 79) <= 33 && ABS(yp - 396) <= 13)
870 buttonIndex = 1;
871 else if (_vm->_events->getMouseButton() == 1 && ABS(xp - 583) <= 32 && ABS(yp - 396) <= 13)
872 buttonIndex = 2;
873
874 _vm->_events->refreshScreenAndEvents();
875 } while (!buttonIndex && !_vm->shouldQuit());
876
877 _vm->_events->mouseOff();
878 _vm->_graphicsMan->fadeOutBreakout();
879 _vm->_globals->freeMemory(ptr);
880 return buttonIndex;
881 }
882
883 /**
884 * Display a screen to enter player name in the case of a new hiscore
885 */
getScoreName()886 void ComputerManager::getScoreName() {
887 _vm->_graphicsMan->loadVgaImage("NAME.PCX");
888 _vm->_graphicsMan->setColorPercentage(252, 100, 100, 100);
889 _vm->_graphicsMan->setColorPercentage(253, 100, 100, 100);
890 _vm->_graphicsMan->setColorPercentage(251, 100, 100, 100);
891 _vm->_graphicsMan->setColorPercentage(254, 0, 0, 0);
892 byte *ptr = _vm->_fileIO->loadFile("ALPHA.SPR");
893 _vm->_graphicsMan->fadeInBreakout();
894
895 // Figure out the line to put the new high score on
896 int scoreLine = 0;
897 while (scoreLine < 5 && _breakoutScore < atol(_score[scoreLine]._score.c_str()))
898 ++scoreLine;
899
900 // If it's not the lasat line, move the lines down
901 for (int line = 5; line > scoreLine; --line) {
902 _score[line]._name = _score[line - 1]._name;
903 _score[line]._score = _score[line - 1]._score;
904 }
905
906 // Get the name for the new high score
907 for (int strPos = 0; strPos <= 4; strPos++) {
908 displayHiscoreLine(ptr, 9 * strPos + 140, 78, 1);
909
910 char curChar = toupper(_vm->_events->waitKeyPress());
911 if ((curChar < '0') || (curChar > 'Z'))
912 curChar = ' ';
913 if ((curChar > '9') && (curChar < 'A'))
914 curChar = ' ';
915
916 _score[scoreLine]._name.setChar(curChar, strPos);
917 displayHiscoreLine(ptr, 9 * strPos + 140, 78, curChar);
918
919 for (int idx = 0; idx < 12; ++idx)
920 _vm->_events->refreshScreenAndEvents();
921 }
922
923 // Set up the new score
924 _score[scoreLine]._score = " ";
925
926 char score[16];
927 sprintf(score, "%d", _breakoutScore);
928 int scoreLen = 0;
929 do {
930 ++scoreLen;
931 } while (score[scoreLen]);
932
933 for (int i = scoreLen - 1, scorePos = 8; i >= 0; i--) {
934 _score[scoreLine]._score.setChar(score[i], scorePos--);
935 }
936 _vm->_graphicsMan->fadeOutBreakout();
937 _vm->_globals->freeMemory(ptr);
938 saveScore();
939 }
940
941 /**
942 * Display current score
943 */
displayScore()944 void ComputerManager::displayScore() {
945 Common::String scoreStr = Common::String::format("%d", _breakoutScore);
946 int strSize = scoreStr.size();
947 for (int i = strSize - 1, idx = 0; i >= 0; i--) {
948 displayScoreChar(idx++, scoreStr[i]);
949 }
950 }
951
952 /**
953 * Display a character of the score
954 */
displayScoreChar(int charPos,int charDisp)955 void ComputerManager::displayScoreChar(int charPos, int charDisp) {
956 int xp;
957 switch (charPos) {
958 case 1:
959 xp = 190;
960 break;
961 case 2:
962 xp = 180;
963 break;
964 case 3:
965 xp = 167;
966 break;
967 case 4:
968 xp = 157;
969 break;
970 case 5:
971 xp = 147;
972 break;
973 case 9:
974 xp = 134;
975 break;
976 default:
977 xp = 200;
978 break;
979 }
980
981 int idx = 3;
982 if (charDisp >= '0' && charDisp <= '9')
983 idx = charDisp - 45;
984
985 _vm->_graphicsMan->fastDisplay2(_breakoutSpr, xp, 11, idx);
986 }
987
988 /**
989 * Save Hiscore in file
990 */
saveScore()991 void ComputerManager::saveScore() {
992 int scores[6];
993 // Load high scores in an array
994 for (int i = 0; i <= 5; i++) {
995 scores[i] = atol(_score[i]._score.c_str());
996 if (!scores[i])
997 scores[i] = 5;
998 }
999
1000 int scorePlace[6];
1001 // order high scores
1002 for (int scorePlaceIdx = 0; scorePlaceIdx <= 5; scorePlaceIdx++) {
1003 for(int i = 0;;i++) {
1004 int curScore = scores[i];
1005 if (curScore && scores[0] <= curScore && scores[1] <= curScore && scores[2] <= curScore && scores[3] <= curScore
1006 && scores[4] <= curScore && scores[5] <= curScore) {
1007 scorePlace[scorePlaceIdx] = i;
1008 scores[i] = 0;
1009 break;
1010 }
1011 }
1012 }
1013
1014 byte *ptr = _vm->_globals->allocMemory(100);
1015 memset(ptr, 0, 100);
1016 for (int scorePlaceIdx = 0; scorePlaceIdx <= 5; scorePlaceIdx++) {
1017 int curBufPtr = 16 * scorePlaceIdx;
1018 for (int namePos = 0; namePos < 6; namePos++) {
1019 char curChar = _score[scorePlace[scorePlaceIdx]]._name[namePos];
1020 if (!curChar)
1021 curChar = ' ';
1022 ptr[curBufPtr + namePos] = curChar;
1023 };
1024
1025 ptr[curBufPtr + 5] = 0;
1026
1027 for (int scorePos = 0; scorePos <= 8; scorePos++) {
1028 char curChar = _score[scorePlace[scorePlaceIdx]]._score[scorePos];
1029 if (!curChar)
1030 curChar = '0';
1031 ptr[curBufPtr + 6 + scorePos] = curChar;
1032 };
1033 ptr[curBufPtr + 15] = 0;
1034 }
1035
1036 _vm->_saveLoad->saveFile(_vm->getTargetName() + "-highscore.dat", ptr, 100);
1037 _vm->_globals->freeMemory(ptr);
1038 }
1039
1040 /**
1041 * Display parts of the hiscore line
1042 */
displayHiscoreLine(const byte * objectData,int x,int y,int curChar)1043 void ComputerManager::displayHiscoreLine(const byte *objectData, int x, int y, int curChar) {
1044 int idx = 36;
1045
1046 if (curChar == 100)
1047 idx = 0;
1048 else if (curChar >= '0' && curChar <= '9')
1049 idx = curChar - '0';
1050 else if (curChar >= 'A' && curChar <= 'Z')
1051 idx = curChar - 'A' + 10;
1052 else if (curChar == 1)
1053 idx = 37;
1054 _vm->_graphicsMan->fastDisplay2(objectData, x, y, idx);
1055 }
1056
1057 /**
1058 * Handle ball moves
1059 */
moveBall()1060 int ComputerManager::moveBall() {
1061 //(signed int)(6.0 * (long double)_vm->getRandomNumber( rand() / 2147483648.0) + 1;
1062 // TODO: Figure out random number
1063 int randVal = _vm->getRandomNumber(6);
1064 switch (_breakoutSpeed) {
1065 case 1:
1066 _minBreakoutMoveSpeed = 1;
1067 _maxBreakoutMoveSpeed = 1;
1068 break;
1069 case 2:
1070 _minBreakoutMoveSpeed = 1;
1071 _maxBreakoutMoveSpeed = 2;
1072 break;
1073 case 3:
1074 _minBreakoutMoveSpeed = 2;
1075 _maxBreakoutMoveSpeed = 2;
1076 break;
1077 case 4:
1078 _minBreakoutMoveSpeed = 3;
1079 _maxBreakoutMoveSpeed = 2;
1080 break;
1081 default:
1082 break;
1083 }
1084
1085 int moveSpeed = _minBreakoutMoveSpeed;
1086 if (_lastBreakoutMoveSpeed == _minBreakoutMoveSpeed)
1087 moveSpeed = _maxBreakoutMoveSpeed;
1088
1089 if (_ballUpFl)
1090 _ballPosition.y += moveSpeed;
1091 else
1092 _ballPosition.y -= moveSpeed;
1093
1094 if (_ballRightFl)
1095 _ballPosition.x += moveSpeed;
1096 else
1097 _ballPosition.x -= moveSpeed;
1098
1099 _lastBreakoutMoveSpeed = moveSpeed;
1100 if (_ballPosition.x <= 6) {
1101 _vm->_soundMan->playSample(2, 6);
1102 _ballPosition.x = randVal + 6;
1103 _ballRightFl = !_ballRightFl;
1104 } else if (_ballPosition.x > 307) {
1105 _vm->_soundMan->playSample(2, 6);
1106 _ballPosition.x = 307 - randVal;
1107 _ballRightFl = !_ballRightFl;
1108 }
1109
1110 if (_ballPosition.y <= 6) {
1111 _vm->_soundMan->playSample(2, 6);
1112 _ballPosition.y = randVal + 7;
1113 _ballUpFl = !_ballUpFl;
1114 } else if (_ballPosition.y >= 186 && _ballPosition.y <= 194) {
1115 _vm->_soundMan->playSample(2, 6);
1116 int ballPosXRight = _ballPosition.x + 6;
1117 if ((_ballPosition.x > _padPositionX - 2) && (ballPosXRight < _padPositionX + 36)) {
1118 _ballUpFl = false;
1119 if (ballPosXRight <= _padPositionX + 15) {
1120 _ballRightFl = false;
1121 if (_ballPosition.x >= _padPositionX && ballPosXRight <= _padPositionX + 5)
1122 _ballPosition.x -= 4;
1123 if (_ballPosition.x >= _padPositionX + 5 && _ballPosition.x + 6 <= _padPositionX + 10)
1124 _ballPosition.x -= 2;
1125 }
1126 if (_ballPosition.x >= _padPositionX + 19 && _ballPosition.x + 6 <= _padPositionX + 36) {
1127 _ballRightFl = true;
1128 if (_ballPosition.x >= _padPositionX + 29)
1129 _ballPosition.x += 4;
1130 if (_ballPosition.x >= _padPositionX + 24 && _ballPosition.x + 6 <= _padPositionX + 29)
1131 _ballPosition.x += 2;
1132 }
1133 }
1134 }
1135
1136 int retVal = 0;
1137 if (_ballPosition.y > 194)
1138 retVal = 1;
1139 checkBallCollisions();
1140 _vm->_objectsMan->setSpriteX(1, _ballPosition.x);
1141 _vm->_objectsMan->setSpriteY(1, _ballPosition.y);
1142 if (!_breakoutBrickNbr)
1143 retVal = 2;
1144 return retVal;
1145 }
1146
1147 /**
1148 * Check ball collision with bricks
1149 */
checkBallCollisions()1150 void ComputerManager::checkBallCollisions() {
1151 int cellLeft;
1152
1153 bool brickDestroyedFl = false;
1154 // TODO: Check if correct
1155 int randVal = _vm->getRandomNumber(6) + 1;
1156 int ballLeft = _ballPosition.x;
1157 int ballTop = _ballPosition.y;
1158 int ballRight = _ballPosition.x + 6;
1159 int ballBottom = _ballPosition.y + 6;
1160 int16 *level = _breakoutLevel;
1161 uint16 levelIdx = 0;
1162 do {
1163 cellLeft = level[levelIdx];
1164 int cellUp = level[levelIdx + 1];
1165 int cellRight = level[levelIdx + 2];
1166 int cellBottom = level[levelIdx + 3];
1167 int cellType = level[levelIdx + 4];
1168 if (level[levelIdx + 5] == 1 && cellLeft != -1) {
1169 bool collisionFl = false;
1170 if (ballTop <= cellBottom && ballBottom >= cellBottom) {
1171 if (ballLeft >= cellLeft && ballRight <= cellRight) {
1172 collisionFl = true;
1173 _ballUpFl = true;
1174 }
1175 if ((ballRight >= cellLeft) && (ballLeft <= cellLeft)) {
1176 collisionFl = true;
1177 _ballUpFl = true;
1178 _ballRightFl = false;
1179 if (cellType == 31)
1180 _ballPosition.x -= randVal;
1181 }
1182 if ((ballLeft <= cellRight) && (ballRight >= cellRight)) {
1183 collisionFl = true;
1184 _ballUpFl = true;
1185 _ballRightFl = true;
1186 if (cellType == 31)
1187 _ballPosition.x += randVal;
1188 }
1189 }
1190 if (ballBottom >= cellUp && ballTop <= cellUp) {
1191 if (ballLeft >= cellLeft && ballRight <= cellRight) {
1192 collisionFl = true;
1193 _ballUpFl = false;
1194 }
1195 if ((ballRight >= cellLeft) && (ballLeft <= cellLeft)) {
1196 collisionFl = true;
1197 _ballUpFl = false;
1198 _ballRightFl = false;
1199 if (cellType == 31)
1200 _ballPosition.x -= 2;
1201 }
1202 if ((ballLeft <= cellRight) && (ballRight >= cellRight)) {
1203 collisionFl = true;
1204 _ballUpFl = false;
1205 _ballRightFl = true;
1206 if (cellType == 31)
1207 _ballPosition.x += randVal;
1208 }
1209 }
1210 if ((ballTop >= cellUp) && (ballBottom <= cellBottom)) {
1211 if ((ballRight >= cellLeft) && (ballLeft <= cellLeft)) {
1212 collisionFl = true;
1213 _ballRightFl = false;
1214 if (cellType == 31)
1215 _ballPosition.x -= randVal;
1216 }
1217 if ((ballLeft <= cellRight) && (ballRight >= cellRight)) {
1218 collisionFl = true;
1219 _ballRightFl = true;
1220 if (cellType == 31)
1221 _ballPosition.x += randVal;
1222 }
1223 }
1224 if (collisionFl) {
1225 if (cellType == 31) {
1226 _vm->_soundMan->playSample(2, 6);
1227 } else {
1228 _vm->_soundMan->playSample(1, 5);
1229 _vm->_graphicsMan->fastDisplay2(_breakoutSpr, cellLeft, cellUp, 16);
1230 switch (cellType) {
1231 case 1:
1232 _breakoutScore += 10;
1233 break;
1234 case 2:
1235 _breakoutScore += 5;
1236 break;
1237 case 3:
1238 _breakoutScore += 50;
1239 if (_breakoutSpeed <= 1)
1240 _breakoutSpeed = 2;
1241 if (_breakoutBrickNbr <= 19)
1242 _breakoutSpeed = 3;
1243 break;
1244 case 4:
1245 _breakoutScore += 20;
1246 break;
1247 case 5:
1248 _breakoutScore += 30;
1249 if (_breakoutSpeed <= 1)
1250 _breakoutSpeed = 2;
1251 break;
1252 case 6:
1253 _breakoutScore += 40;
1254 break;
1255 default:
1256 break;
1257 }
1258 displayScore();
1259 --_breakoutBrickNbr;
1260 level[levelIdx + 5] = 0;
1261 brickDestroyedFl = true;
1262 }
1263 }
1264 }
1265
1266 if (brickDestroyedFl)
1267 cellLeft = -1;
1268 levelIdx += 6;
1269 } while (cellLeft != -1);
1270 }
1271
1272 } // End of namespace Hopkins
1273