scummvm/engines/agi/preagi_mickey.cpp

2076 lines
47 KiB
C++
Raw Normal View History

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/stdafx.h"
#include "common/events.h"
#include "agi/preagi_mickey.h"
#include "agi/graphics.h"
// default attributes
#define IDA_DEFAULT 0x0F
#define IDA_DEFAULT_REV 0xF0
namespace Agi {
int Mickey::getDat(int iRoom) {
if (((iRoom > 0) && (iRoom < 24)) || iRoom == 154 || iRoom == 155) return IDI_MSA_PLANET_EARTH;
if ((iRoom >= 30) && (iRoom <= 39)) return IDI_MSA_PLANET_VENUS;
if ((iRoom >= 40) && (iRoom <= 69)) return IDI_MSA_PLANET_NEPTUNE;
if ((iRoom >= 70) && (iRoom <= 82)) return IDI_MSA_PLANET_MERCURY;
if ((iRoom >= 83) && (iRoom <= 92)) return IDI_MSA_PLANET_SATURN;
if ((iRoom >= 93) && (iRoom <= 103)) return IDI_MSA_PLANET_PLUTO;
if ((iRoom >= 106) && (iRoom <= 120)) return IDI_MSA_PLANET_JUPITER;
if ((iRoom >= 121) && (iRoom <= 132)) return IDI_MSA_PLANET_MARS;
if ((iRoom >= 133) && (iRoom <= 145)) return IDI_MSA_PLANET_URANUS;
return IDI_MSA_PLANET_SPACESHIP;
}
void Mickey::readExe(int ofs, uint8 *buffer, long buflen) {
Common::File infile;
if (!infile.open(IDS_MSA_PATH_EXE))
return;
infile.seek(ofs, SEEK_SET);
infile.read(buffer, buflen);
infile.close();
}
void Mickey::getDatFileName(int iRoom, char *szFile) {
sprintf(szFile, IDS_MSA_PATH_DAT, IDS_MSA_NAME_DAT[getDat(iRoom)]);
}
void Mickey::readDatHdr(char *szFile, MSA_DAT_HEADER *hdr) {
Common::File infile;
if (!infile.open(szFile))
return;
hdr->filelen = infile.readByte();
hdr->filelen += infile.readByte() * 0x100;
for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
hdr->ofsRoom[i] = infile.readByte();
hdr->ofsRoom[i] += infile.readByte() * 0x100;
}
for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
hdr->ofsDesc[i] = infile.readByte();
hdr->ofsDesc[i] += infile.readByte() * 0x100;
}
for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
hdr->ofsStr[i] = infile.readByte();
hdr->ofsStr[i] += infile.readByte() * 0x100;
}
infile.close();
}
void Mickey::readDesc(int iRoom, char *buffer, long buflen) {
MSA_DAT_HEADER hdr;
char szFile[256] = {0};
getDatFileName(iRoom, szFile);
readDatHdr(szFile, &hdr);
Common::File infile;
if (!infile.open(szFile))
return;
memset(buffer, 0, buflen);
infile.seek(hdr.ofsDesc[iRoom - 1] + IDI_MSA_OFS_DAT, SEEK_SET);
infile.read(buffer, buflen);
infile.close();
}
void Mickey::readMenu(int iRoom, char *buffer) {
MSA_DAT_HEADER hdr;
char szFile[256] = {0};
getDatFileName(iRoom, szFile);
readDatHdr(szFile, &hdr);
Common::File infile;
if (!infile.open(szFile))
return;
infile.seek(hdr.ofsRoom[iRoom - 1] + IDI_MSA_OFS_DAT, SEEK_SET);
infile.read((uint8 *)buffer, sizeof(MSA_MENU));
infile.close();
}
void Mickey::readDatStr(int iDat, int iStr, char *buffer, long buflen) {
MSA_DAT_HEADER hdr;
char szFile[256] = {0};
sprintf(szFile, IDS_MSA_PATH_DAT, IDS_MSA_NAME_DAT[iDat]);
readDatHdr(szFile, &hdr);
Common::File infile;
if (!infile.open(szFile))
return;
infile.seek(hdr.ofsStr[iStr] + IDI_MSA_OFS_DAT, SEEK_SET);
infile.read((uint8 *)buffer, buflen);
infile.close();
}
void Mickey::readOfsData(int offset, int iItem, uint8 *buffer, long buflen) {
uint16 ofs[256];
readExe(offset, buffer, buflen);
// memcpy(ofs, buffer, sizeof(ofs));
for (int i = 0; i < 256; i++)
ofs[i] = buffer[i*2] + 256 * buffer[i*2+1];
readExe(ofs[iItem] + IDI_MSA_OFS_EXE, buffer, buflen);
}
// User Interface
bool Mickey::chooseY_N(int ofsPrompt, bool fErrorMsg) {
printExeStr(ofsPrompt);
int a = _vm->getSelection(0);
for (;;) {
switch (a) {
case 0: return false;
case 1: return true;
default: if (fErrorMsg) {
printExeStr(IDO_MSA_PRESS_YES_OR_NO);
_vm->waitAnyKey();
printExeStr(ofsPrompt);
}
break;
}
a = _vm->getSelection(0);
}
}
int Mickey::choose1to9(int ofsPrompt) {
printExeStr(ofsPrompt);
int a = _vm->getSelection(1);
for (;;) {
if (a == 10) {
printExeStr(IDO_MSA_PRESS_1_TO_9);
if (!_vm->waitAnyKeyChoice())
return 0;
printExeStr(ofsPrompt);
} else return a;
a = _vm->getSelection(1);
}
}
void Mickey::printStr(char *buffer) {
int pc = 1;
int nRows, iCol, iRow;
nRows = *buffer + IDI_MSA_ROW_MENU_0;
//clearTextArea(); // TODO
for (iRow = IDI_MSA_ROW_MENU_0; iRow < nRows; iRow++) {
iCol = *(buffer + pc++);
// drawStr(iRow, iCol, buffer + pc); // TODO
pc += strlen(buffer + pc) + 1;
}
}
void Mickey::printExeStr(int ofs) {
uint8 buffer[256] = {0};
if (!ofs)
return;
readExe(ofs, buffer, sizeof(buffer));
printStr((char *)buffer);
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
}
void Mickey::printExeMsg(int ofs) {
if (!ofs)
return;
printExeStr(ofs);
_vm->waitAnyKeyAnim();
}
void Mickey::printDatStr(int iDat, int iStr) {
char *buffer = (char *)malloc(256);
readDatStr(iDat, iStr, buffer, 256);
printStr(buffer);
free(buffer);
}
void Mickey::printDesc(int iRoom) {
char *buffer = (char *)malloc(256);
readDesc(iRoom, buffer, 256);
printStr(buffer);
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
free(buffer);
}
void Mickey::drawMenu(MSA_MENU menu, int sel0, int sel1) {
int iWord;
int iRow;
int sel;
uint8 attr;
// draw menu
// clearTextArea(); // TODO
for (iRow = 0; iRow < 2; iRow++) {
for (iWord = 0; iWord < menu.row[iRow].count; iWord++) {
if (iRow)
sel = sel1;
else
sel = sel0;
if (iWord == sel)
attr = IDA_DEFAULT_REV;
else
attr = IDA_DEFAULT;
// TODO
//drawStrAttr(IDI_MSA_ROW_MENU_0 + iRow, menu.row[iRow].entry[iWord].x0,
// attr, (char *)menu.row[iRow].entry[iWord].szText);
}
}
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
}
void Mickey::getMouseMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow, int x, int y) {
int iWord;
int *sel = 0;
switch(iRow) {
case 0:
if (y != IDI_MSA_ROW_MENU_0) return;
sel = sel0;
break;
case 1:
if (y != IDI_MSA_ROW_MENU_1) return;
sel = sel1;
break;
}
for (iWord = 0; iWord < menu.row[iRow].count; iWord++) {
if ((x >= menu.row[iRow].entry[iWord].x0) &&
(x < (int)(menu.row[iRow].entry[iWord].x0 +
strlen((char *)menu.row[iRow].entry[iWord].szText)))) {
*sel = iWord;
break;
}
}
}
bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
Common::Event event;
int *sel = 0;
int nWords;
int x, y;
switch(iRow) {
case 0:
sel = sel0;
break;
case 1:
sel = sel1;
break;
}
nWords = menu.row[iRow].count;
drawMenu(menu, *sel0, *sel1);
for (;;) {
while (_vm->_system->getEventManager()->pollEvent(event)) {
switch(event.type) {
case Common::EVENT_QUIT:
exit(0);
case Common::EVENT_MOUSEMOVE:
if (iRow < 2) {
// TODO
x = y = 0; // TODO: remove this
//x = event.mouse.x / getFontWidth();
//y = event.mouse.y / getFontHeight();
getMouseMenuSelRow(menu, sel0, sel1, iRow, x, y);
drawMenu(menu, *sel0, *sel1);
}
break;
case Common::EVENT_LBUTTONUP:
return true;
//FIXME: ScummVM does not support middle button
/*case Common::EVENT_MBUTTONUP:
inventory();
drawRoom();
*sel0 = 0; *sel1 = -1;
return false;*/
case Common::EVENT_RBUTTONUP:
*sel0 = 0; *sel1 = -1;
return false;
case Common::EVENT_WHEELUP:
if (iRow < 2) {
*sel -= 1;
if (*sel < 0) *sel = nWords - 1;
drawMenu(menu, *sel0, *sel1);
}
break;
case Common::EVENT_WHEELDOWN:
if (iRow < 2) {
*sel += 1;
if (*sel == nWords) *sel = 0;
drawMenu(menu, *sel0, *sel1);
}
break;
case Common::EVENT_KEYDOWN:
switch (event.kbd.keycode) {
case Common::KEYCODE_F11:
//flipCGA(); // TODO
drawRoom();
drawMenu(menu, *sel0, *sel1);
break;
case Common::KEYCODE_F12:
//flipDblSize(); // TODO
drawRoom();
drawMenu(menu, *sel0, *sel1);
break;
case Common::KEYCODE_2:
hidden();
break;
case Common::KEYCODE_8:
if (event.kbd.flags & Common::KBD_CTRL) {
*sel0 = 0; *sel1 = -1; return false;
}
break;
case Common::KEYCODE_ESCAPE:
*sel0 = 0; *sel1 = -1; return false;
case Common::KEYCODE_s:
//flipSound(); // TODO
break;
case Common::KEYCODE_c:
inventory();
drawRoom();
*sel0 = 0; *sel1 = -1; return false;
case Common::KEYCODE_b:
printRoomDesc();
drawMenu(menu, *sel0, *sel1);
*sel0 = 0; *sel1 = -1; return false;
case Common::KEYCODE_LEFT:
case Common::KEYCODE_KP4:
case Common::KEYCODE_4:
if (iRow < 2) {
*sel -= 1;
if (*sel < 0) *sel = nWords - 1;
drawMenu(menu, *sel0, *sel1);
}
break;
case Common::KEYCODE_RIGHT:
case Common::KEYCODE_SPACE:
case Common::KEYCODE_KP6:
case Common::KEYCODE_6:
if (iRow < 2) {
*sel += 1;
if (*sel == nWords) *sel = 0;
drawMenu(menu, *sel0, *sel1);
}
break;
case Common::KEYCODE_RETURN:
//FIXME:
//case SDLK_KP_ENTER:
return true;
default:
break;
}
break;
default:
break;
}
animate();
drawMenu(menu, *sel0, *sel1);
}
animate();
drawMenu(menu, *sel0, *sel1);
}
}
void Mickey::getMenuSel(char *buffer, int *sel0, int *sel1) {
MSA_MENU menu;
memcpy(&menu, buffer, sizeof(MSA_MENU));
*sel0 = 0;
*sel1 = -1;
for (;;) {
for (;;) {
if (getMenuSelRow(menu, sel0, sel1, 0)) {
*sel1 = 0;
if (getMenuSelRow(menu, sel0, sel1, 1)) {
break;
}
}
}
if (getMenuSelRow(menu, sel0, sel1, 2)) {
break;
}
}
}
void Mickey::centerMenu(MSA_MENU *menu) {
int iWord;
int iRow;
int w, x;
for (iRow = 0; iRow < 2; iRow++) {
w = 0;
for (iWord = 0; iWord < menu->row[iRow].count; iWord++) {
w += strlen((char *)menu->row[iRow].entry[iWord].szText);
}
w += menu->row[iRow].count - 1;
x = (40 - w) / 2; // FIX
for (iWord = 0; iWord < menu->row[iRow].count; iWord++) {
menu->row[iRow].entry[iWord].x0 = x;
x += strlen((char *)menu->row[iRow].entry[iWord].szText) + 1;
}
}
}
void Mickey::patchMenu(MSA_MENU *menu) {
uint8 buffer[512];
uint8 menubuf[sizeof(MSA_MENU)];
int nPatches;
int pBuf = 0;
// change planet name in ship airlock menu
if (game.iRoom == IDI_MSA_PIC_SHIP_AIRLOCK) {
strcpy((char *)menu->row[1].entry[2].szText, IDS_MSA_NAME_PLANET[game.iPlanet]);
}
// exit if fix unnecessary
if (!game.iRmMenu[game.iRoom]) {
centerMenu(menu);
return;
}
// copy menu to menubuf
memcpy(menubuf, menu, sizeof(menubuf));
// read patches
readOfsData(
IDOFS_MSA_MENU_PATCHES,
game.nRmMenu[game.iRoom] + game.iRmMenu[game.iRoom] - 1,
buffer, sizeof(buffer)
);
// get number of patches
nPatches = buffer[pBuf++];
// patch menubuf
for (int iPatch = 0; iPatch < nPatches; iPatch++) {
if (buffer[pBuf] > sizeof(menubuf)) {
// patch address out of bounds
}
menubuf[buffer[pBuf]] = buffer[pBuf + 1];
pBuf += 2;
}
// copy menubuf back to menu
memcpy(menu, menubuf, sizeof(MSA_MENU));
// center menu
centerMenu(menu);
}
void Mickey::printDatString(int iStr) {
printDatStr(getDat(game.iRoom), iStr);
}
void Mickey::printDatMessage(int iStr) {
printDatString(iStr);
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
_vm->waitAnyKeyAnim();
}
// Sound
// TODO
/*
void Mickey::_PlayNote(MSA_SND_NOTE note) {
if (!note.counter)
playNote(1, 0, note.length / IDI_SND_TIMER_RESOLUTION);
else
playNote(1, IDI_SND_OSCILLATOR_FREQUENCY / note.counter,
note.length / IDI_SND_TIMER_RESOLUTION / IDI_SND_PITCH);
}
void Mickey::PlaySound(ENUM_MSA_SOUND iSound) {
if (!GetSound())
return;
SDL_Event event;
MSA_SND_NOTE note;
uint8 *buffer = new uint8[1024];
int pBuf = 1;
switch(iSound) {
case IDI_MSA_SND_XL30:
for (int iNote = 0; iNote < 6; iNote++) {
note.counter = _vm->Rnd(59600) + 59;
note.length = 4;
_PlayNote(note);
}
break;
default:
readOfsData(IDOFS_MSA_SOUND_DATA, iSound, buffer, 1024);
for (;;) {
memcpy(&note, buffer + pBuf, sizeof(note));
if (!note.counter && !note.length)
break;
_PlayNote(note);
pBuf += 3;
if (iSound == IDI_MSA_SND_THEME) {
while (SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_QUIT:
exit(0);
case SDL_MOUSEBUTTONUP:
case SDL_KEYDOWN:
delete [] buffer;
return;
}
}
}
}
break;
}
delete [] buffer;
}
*/
void Mickey::debug() {
char szLine[41] = {0};
//ClearScreen(IDA_DEFAULT); // TODO
sprintf(szLine, IDS_MSA_DEBUG_ROOM, game.iRoom);
//drawStr(5, 10, szLine); // TODO
if (game.iRoom < IDI_MSA_MAX_PIC_ROOM) {
if (game.iRmObj[game.iRoom] != IDI_MSA_OBJECT_NONE) {
sprintf(szLine, IDS_MSA_DEBUG_OBJ, game.iRmObj[game.iRoom]);
//drawStr(7, 10, szLine); // TODO
}
} else {
sprintf(szLine, IDS_MSA_DEBUG_OBJ, 32);
//drawStr(7, 10, szLine); // TODO
}
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
}
// Graphics
void Mickey::drawObj(ENUM_MSA_OBJECT iObj, int x0, int y0) {
uint8 *buffer = new uint8[4096];
char szFile[255] = {0};
sprintf(szFile, IDS_MSA_PATH_OBJ, IDS_MSA_NAME_OBJ[iObj]);
Common::File infile;
if(!infile.open(szFile))
return;
infile.read(buffer, infile.size());
// TODO
/*
if (iObj == IDI_MSA_OBJECT_CRYSTAL) {
AGI_DrawPic(IDI_MSA_PIC_X0 + x0, IDI_MSA_PIC_Y0 + y0, IDF_AGI_PIC_V2 | IDF_AGI_STEP, buffer);
} else {
AGI_DrawPic(IDI_MSA_PIC_X0 + x0, IDI_MSA_PIC_Y0 + y0, IDF_AGI_PIC_V2, buffer);
}
*/
infile.close();
delete [] buffer;
}
void Mickey::drawPic(int iPic) {
_vm->preAgiLoadResource(rPICTURE, iPic);
_vm->_picture->decodePicture(iPic, true);
_vm->_picture->showPic();
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
/*
int w = IDI_MSA_PIC_WIDTH, h = IDI_MSA_PIC_HEIGHT;
int flags = IDF_AGI_PIC_V2;
if (iPic == IDI_MSA_PIC_STAR_MAP) {
w++;
h++;
flags |= IDF_AGI_CIRCLE;
}
ClearScreenAGI(w, h, IDI_MSA_PIC_X0, IDI_MSA_PIC_Y0, flags);
if (iPic) {
uint8 *buffer = new uint8[4096];
char szFile[255] = {0};
sprintf(szFile, IDS_MSA_PATH_PIC, iPic);
Common::File infile;
if (!infile.open(szFile))
return;
infile.read(buffer, infile.size());
infile.close();
AGI_DrawPic(IDI_MSA_PIC_X0, IDI_MSA_PIC_Y0, flags, buffer);
delete [] buffer;
}
*/
}
void Mickey::drawRoomPicture() {
if (false) { // (getDebug()) { // TODO
drawPic(0);
debug();
} else {
if (game.iRoom == IDI_MSA_PIC_TITLE) {
drawPic(IDI_MSA_PIC_TITLE);
} else {
drawPic(game.iRmPic[game.iRoom]);
}
}
}
void Mickey::drawRoomObjects() {
if (game.iRoom >= IDI_MSA_MAX_PIC_ROOM)
return;
uint8 buffer[256];
int pBuf = 0;
int nObjs;
// draw ship control room window
if (game.iRoom == IDI_MSA_PIC_SHIP_CONTROLS) {
if (game.fFlying) {
drawObj(IDI_MSA_OBJECT_W_SPACE, 0, 0);
} else {
drawObj((ENUM_MSA_OBJECT)(IDI_MSA_OBJECT_W_EARTH + game.iPlanet), 0, 1);
}
}
// draw objects
if (game.iRmObj[game.iRoom] != IDI_MSA_OBJECT_NONE) {
readOfsData(IDO_MSA_ROOM_OBJECT_XY_OFFSETS,
game.iRmObj[game.iRoom], buffer, sizeof(buffer));
nObjs = buffer[pBuf++];
for (int iObj = 0; iObj < nObjs; iObj++) {
drawObj((ENUM_MSA_OBJECT)buffer[pBuf], buffer[pBuf + 1], buffer[pBuf + 2]);
pBuf += 3;
}
}
}
void Mickey::drawRoomAnimation() {
uint8 objLight[] = {
0xF0, 1, 0xF9, 2, 53, 45, 0xFF
};
switch(game.iRoom) {
case IDI_MSA_PIC_EARTH_SHIP:
case IDI_MSA_PIC_VENUS_SHIP:
case IDI_MSA_PIC_NEPTUNE_SHIP:
case IDI_MSA_PIC_MERCURY_SHIP:
case IDI_MSA_PIC_SATURN_SHIP:
case IDI_MSA_PIC_PLUTO_SHIP:
case IDI_MSA_PIC_JUPITER_SHIP:
case IDI_MSA_PIC_MARS_SHIP:
case IDI_MSA_PIC_URANUS_SHIP:
case IDI_MSA_PIC_SHIP_VENUS:
case IDI_MSA_PIC_SHIP_NEPTUNE:
case IDI_MSA_PIC_SHIP_MERCURY:
case IDI_MSA_PIC_SHIP_SATURN:
case IDI_MSA_PIC_SHIP_PLUTO:
case IDI_MSA_PIC_SHIP_JUPITER:
case IDI_MSA_PIC_SHIP_MARS:
case IDI_MSA_PIC_SHIP_URANUS:
// draw blinking ship lights
int iColor;
for (int i = 0; i < 12; i++) {
iColor = game.nFrame + i;
if (iColor > 15) iColor -= 15;
objLight[1] = iColor;
objLight[4] += 7;
// TODO
//AGI_DrawPic(0, 0, IDF_AGI_PIC_V2 | IDF_AGI_CIRCLE, (uint8 *)objLight);
}
game.nFrame--;
if (game.nFrame < 0) game.nFrame = 15;
// TODO
//PlaySound(IDI_MSA_SND_PRESS_BLUE);
break;
case IDI_MSA_PIC_SHIP_CONTROLS:
// draw XL30 screen
if (game.fAnimXL30) {
if (game.nFrame > 5) game.nFrame = 0;
drawObj((ENUM_MSA_OBJECT)(IDI_MSA_OBJECT_XL31 + game.nFrame), 0, 4);
game.nFrame++;
};
break;
default:
// draw crystal
if (game.iRoom == IDI_MSA_XTAL_ROOM_XY[game.iPlanet][0]) {
if (!game.fHasXtal) {
switch(game.iPlanet) {
case IDI_MSA_PLANET_VENUS:
if (game.iRmMenu[game.iRoom] != 2) break;
default:
drawObj(
IDI_MSA_OBJECT_CRYSTAL,
IDI_MSA_XTAL_ROOM_XY[game.iPlanet][1],
IDI_MSA_XTAL_ROOM_XY[game.iPlanet][2]
);
break;
}
}
}
break;
}
}
void Mickey::drawRoom() {
drawRoomPicture();
drawRoomObjects();
drawRoomAnimation();
}
void Mickey::drawLogo() {
char szFile[256] = {0};
uint8 *buffer = new uint8[16384];
// read in logos.bcg
sprintf(szFile, IDS_MSA_PATH_LOGO);
Common::File infile;
if (!infile.open(szFile))
return;
infile.read(buffer, infile.size());
infile.close();
// draw logo bitmap
//drawPictureBCG(buffer); // TODO
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
delete [] buffer;
}
void Mickey::animate() {
// TODO
/* if ((int)SDL_GetTicks() > (game.nTicks + IDI_MSA_ANIM_DELAY)) {
game.nTicks = SDL_GetTicks();
drawRoomAnimation();
}
*/
}
void Mickey::printRoomDesc() {
// print room description
printDesc(game.iRoom);
_vm->waitAnyKeyAnim();
// print extended room description
if (game.fRmTxt[game.iRoom]) {
printExeMsg(game.oRmTxt[game.iRoom] + IDI_MSA_OFS_EXE);
}
}
bool Mickey::loadGame() {
Common::File infile;
char szFile[256] = {0};
bool diskerror = true;
int sel;
while (diskerror) {
sel = choose1to9(IDO_MSA_LOAD_GAME[1]);
if (!sel)
return false;
// load game
//sprintf(szFile, "%s.s%2d", target, sel); // TODO
if (!infile.open(szFile)) {
printExeStr(IDO_MSA_CHECK_DISK_DRIVE);
if (!_vm->waitAnyKeyChoice())
return false;
} else {
//infile->read(game, sizeof(MSA_GAME));
diskerror = false;
infile.close();
}
}
printExeMsg(IDO_MSA_LOAD_GAME[2]);
return true;
}
void Mickey::saveGame() {
Common::File outfile;
//char szFile[256] = {0};
bool diskerror = true;
int sel;
bool fOldDisk = chooseY_N(IDO_MSA_SAVE_GAME[0], false);
if (fOldDisk)
printExeStr(IDO_MSA_SAVE_GAME[1]);
else
printExeStr(IDO_MSA_SAVE_GAME[2]);
if (!_vm->waitAnyKeyChoice())
return;
while (diskerror) {
sel = choose1to9(IDO_MSA_SAVE_GAME[3]);
if (!sel)
return;
if (fOldDisk)
printExeStr(IDO_MSA_SAVE_GAME[5]);
else
printExeStr(IDO_MSA_SAVE_GAME[4]);
if (!_vm->waitAnyKeyChoice())
return;
// save game
// TODO
/*
sprintf(szFile, "%s.s%2d", target, sel);
if (!outfile.open(szFile)) {
printExeStr(IDO_MSA_CHECK_DISK_DRIVE);
if (!_vm->waitAnyKeyChoice())
return;
} else {
//outfile->write(game, sizeof(MSA_GAME))
diskerror = false;
outfile.close();
}
*/
}
printExeMsg(IDO_MSA_SAVE_GAME[6]);
}
void Mickey::showPlanetInfo() {
for (int i = 0; i < IDI_MSA_MAX_PLANET_INFO; i++) {
printExeStr(IDO_MSA_PLANET_INFO[game.iPlanet][i]);
_vm->waitAnyKey();
}
}
void Mickey::printStory() {
char buffer[IDI_MSA_LEN_STORY] = {0};
char szLine[41] = {0};
int iRow;
int pBuf = 0;
readExe(IDO_MSA_GAME_STORY, (uint8 *)buffer, sizeof(buffer));
//ClearScreen(IDA_DEFAULT); // TODO
for (iRow = 0; iRow < 25; iRow++) {
strcpy(szLine, buffer + pBuf);
//drawStr(iRow, 0, szLine); // TODO
pBuf += strlen(szLine) + 1;
}
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
_vm->waitAnyKey();
//ClearScreen(IDA_DEFAULT); // TODO
for (iRow = 0; iRow < 21; iRow++) {
strcpy(szLine, buffer + pBuf);
//drawStr(iRow, 0, szLine); // TODO
pBuf += strlen(szLine) + 1;
}
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
_vm->waitAnyKey();
drawRoom();
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
game.fStoryShown = true;
}
void Mickey::hidden() {
if (game.iRoom == IDI_MSA_PIC_MERCURY_CAVE_0) {
for (int i = 0; i < 5; i++) {
//printExeMsg(IDO_MSA_HIDDEN_MSG[i]); // TODO
}
// clearTextArea(); // TODO
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
_vm->waitAnyKey();
}
}
int Mickey::getPlanet() {
if (!game.nButtons)
return -1;
for (int iPlanet = 0; iPlanet < IDI_MSA_MAX_DAT; iPlanet++) {
if (!strcmp(IDS_MSA_ADDR_PLANET[iPlanet], game.szAddr)) {
return iPlanet;
}
}
return -1;
}
void Mickey::pressOB(int iButton) {
char szButtons[12] = {0};
// check if too many buttons pressed
if (game.nButtons == IDI_MSA_MAX_BUTTON) {
game.nButtons = 0;
memset(game.szAddr, 0, sizeof(game.szAddr));
printExeMsg(IDO_MSA_TOO_MANY_BUTTONS_PRESSED);
return;
}
// add button press to address
game.nButtons++;
game.szAddr[game.nButtons - 1] = (char)iButton;
// format buttons string
for (int i = 0; i < IDI_MSA_MAX_BUTTON; i++) {
szButtons[i * 2] = game.szAddr[i];
if (game.szAddr[i + 1]) szButtons[(i * 2) + 1] = ',';
}
// print pressed buttons
printExeStr(IDO_MSA_MICKEY_HAS_PRESSED);
//drawStr(IDI_MSA_ROW_BUTTONS, IDI_MSA_COL_BUTTONS, szButtons); // TODO
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
_vm->waitAnyKey();
}
void Mickey::checkAirSupply(bool fSuit, int *iSupply) {
if (fSuit) {
*iSupply -= 1;
for (int i = 0; i < 4; i++) {
if (*iSupply == IDI_MSA_AIR_SUPPLY[i]) {
//playSound(IDI_MSA_SND_XL30); // TODO
printExeMsg(IDO_MSA_XL30_SPEAKING);
printExeMsg(IDO_MSA_AIR_SUPPLY[i]);
if (i == 3) {
exit(0);
}
}
}
} else {
*iSupply = IDI_MSA_MAX_AIR_SUPPLY;
}
}
void Mickey::insertDisk(int iDisk) {
//clearTextArea(); // TODO
// TODO
//drawStr(IDI_MSA_ROW_INSERT_DISK, IDI_MSA_COL_INSERT_DISK, (char *)IDS_MSA_INSERT_DISK[iDisk]);
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
_vm->waitAnyKey();
}
void Mickey::gameOver() {
drawPic(IDI_MSA_PIC_EARTH_SHIP_LEAVING);
printExeMsg(IDO_MSA_GAME_OVER[3]);
//playSound(IDI_MSA_SND_GAME_OVER); // TODO
if (game.fItemUsed[IDI_MSA_ITEM_LETTER]) {
drawPic(IDI_MSA_PIC_EARTH_MINNIE);
printExeMsg(IDO_MSA_GAME_OVER[4]);
printExeMsg(IDO_MSA_GAME_OVER[5]);
} else {
printExeMsg(IDO_MSA_GAME_OVER[6]);
printExeMsg(IDO_MSA_GAME_OVER[7]);
}
_vm->waitAnyKey();
exit(0);
}
void Mickey::flipSwitch() {
if (game.fHasXtal || game.nXtals) {
if (!game.fStoryShown) {
printStory();
randomize();
}
// activate screen animation
game.fAnimXL30 = true;
// clearTextArea(); // TODO
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
//playSound(IDI_MSA_SND_XL30); // TODO
printExeMsg(IDO_MSA_XL30_SPEAKING);
if (game.fHasXtal) {
game.fHasXtal = false;
printExeMsg(IDO_MSA_CRYSTAL_PIECE_FOUND);
}
if (game.nXtals == IDI_MSA_MAX_PLANET) {
printExeMsg(IDO_MSA_GAME_OVER[0]);
printExeMsg(IDO_MSA_GAME_OVER[1]);
printExeMsg(IDO_MSA_GAME_OVER[2]);
#ifdef _DEBUG
strcpy(game.szAddr, (char *)IDS_MSA_ADDR_PLANET[IDI_MSA_PLANET_EARTH]);
game.nButtons = strlen(game.szAddr);
#endif
} else {
printExeStr(game.iClue[game.nXtals]);
#ifdef _DEBUG
// TODO
//drawStr(24, 12, (char *)IDS_MSA_NAME_PLANET_2[game.iPlanetXtal[game.nXtals]]);
//drawStr(24, 22, (char *)IDS_MSA_ADDR_PLANET[game.iPlanetXtal[game.nXtals]]);
strcpy(game.szAddr, (char *)IDS_MSA_ADDR_PLANET[game.iPlanetXtal[game.nXtals]]);
game.nButtons = strlen(game.szAddr);
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
#endif
_vm->waitAnyKeyAnim();
}
} else {
printStory();
}
}
void Mickey::inventory() {
//int iRow = IDI_MSA_ROW_INV_ITEMS;
char szCrystals[12] = {0};
sprintf(szCrystals, IDS_MSA_CRYSTALS, IDS_MSA_CRYSTAL_NO[game.nXtals]);
// TODO
/*
ClearScreen(IDA_DEFAULT);
drawStr(IDI_MSA_ROW_INV_TITLE, IDI_MSA_COL_INV_TITLE, IDS_MSA_INVENTORY);
drawStr(IDI_MSA_ROW_INV_CRYSTALS, IDI_MSA_COL_INV_ITEMS, szCrystals);
*/
for (int iItem = 0; iItem < IDI_MSA_MAX_ITEM; iItem++) {
if (game.fItem[game.iItem[iItem]] && (game.iItem[iItem] != IDI_MSA_OBJECT_NONE)) {
//drawStr(iRow++, IDI_MSA_COL_INV_ITEMS, (char *)IDS_MSA_NAME_ITEM[game.iItem[iItem]]); // TODO
}
}
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
_vm->waitAnyKey();
//ClearScreen(IDA_DEFAULT); // TODO
}
void Mickey::randomize() {
int iPlanet = 0;
int iHint = 0;
bool done;
// TODO
memset(game.iPlanetXtal, 0, sizeof(game.iPlanetXtal));
memset(game.iClue, 0, sizeof(game.iClue));
game.iPlanetXtal[0] = IDI_MSA_PLANET_EARTH;
game.iPlanetXtal[8] = IDI_MSA_PLANET_URANUS;
for (int i = 1; i < 9; i++) {
if (i == 8) {
iPlanet = IDI_MSA_PLANET_URANUS;
} else {
done = false;
while (!done) {
//iPlanet = _vm->rnd(IDI_MSA_MAX_PLANET); // TODO
done = true;
for (int j = 0; j < IDI_MSA_MAX_PLANET; j++) {
if (game.iPlanetXtal[j] == iPlanet) {
done = false;
break;
}
}
}
}
game.iPlanetXtal[i] = iPlanet;
done = false;
while (!done) {
//iHint = _vm->rnd(5); // TODO
done = true;
}
game.iClue[i] = IDO_MSA_NEXT_PIECE[iPlanet][iHint];
}
}
void Mickey::flashScreen() {
//playSound(IDI_MSA_SND_PRESS_BLUE); // TODO
//clearGfxScreen(15); // TODO
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
drawRoom();
printDesc(game.iRoom);
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
}
void Mickey::intro() {
// draw sierra logo
drawLogo();
// draw title picture
game.iRoom = IDI_MSA_PIC_TITLE;
drawRoom();
// show copyright and play theme
printExeMsg(IDO_MSA_COPYRIGHT);
//playSound(IDI_MSA_SND_THEME); // TODO
// load game
game.fIntro = true;
if (chooseY_N(IDO_MSA_LOAD_GAME[0], true)) {
if (loadGame()) {
game.iPlanet = IDI_MSA_PLANET_EARTH;
game.fIntro = false;
game.iRoom = IDI_MSA_PIC_SHIP_CORRIDOR;
return;
}
}
// play spaceship landing scene
game.iPlanet = IDI_MSA_PLANET_EARTH;
game.iRoom = IDI_MSA_PIC_EARTH_ROAD_4;
drawRoom();
printRoomDesc();
#ifdef _DEBUG
PlaySound(IDI_MSA_SND_SHIP_LAND);
#endif
flashScreen();
flashScreen();
flashScreen();
printExeMsg(IDO_MSA_INTRO);
}
void Mickey::getItem(ENUM_MSA_ITEM iItem) {
game.fItem[iItem] = true;
game.iItem[game.nItems++] = iItem;
game.fRmTxt[game.iRoom] = 0;
//playSound(IDI_MSA_SND_TAKE); // TODO
drawRoom();
}
void Mickey::getXtal(int iStr) {
game.fRmTxt[game.iRoom] = 0;
game.fHasXtal = true;
game.nXtals++;
//playSound(IDI_MSA_SND_CRYSTAL); // TODO
drawRoom();
printDatMessage(iStr);
}
bool Mickey::parse(int cmd, int arg) {
switch(cmd) {
// BASIC
case IDI_MSA_ACTION_GOTO_ROOM:
game.iRoom = arg;
return true;
case IDI_MSA_ACTION_SHOW_INT_STR:
printExeMsg(IDO_MSA_ERROR[arg]);
break;
case IDI_MSA_ACTION_SHOW_DAT_STR:
printDatMessage(arg);
break;
// GENERAL
case IDI_MSA_ACTION_PLANET_INFO:
showPlanetInfo();
break;
case IDI_MSA_ACTION_SAVE_GAME:
saveGame();
break;
case IDI_MSA_ACTION_LOOK_MICKEY:
printExeMsg(IDO_MSA_YOU_CAN_SEE_MICKEY_ALREADY);
break;
// EARTH
case IDI_MSA_ACTION_GET_ROPE:
if (game.iRmMenu[game.iRoom] == 2) {
game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
game.iRmMenu[game.iRoom] = 3;
getItem(IDI_MSA_ITEM_ROPE);
printExeMsg(IDO_MSA_ERROR[7]);
} else {
game.iRmMenu[game.iRoom] = 1;
printDatMessage(11);
}
break;
case IDI_MSA_ACTION_UNTIE_ROPE:
game.iRmPic[game.iRoom] = IDI_MSA_PIC_EARTH_TIRE_SWING_1;
game.iRmObj[game.iRoom] = 0;
game.iRmMenu[game.iRoom] = 2;
drawRoom();
printDatMessage(12);
break;
case IDI_MSA_ACTION_GET_BONE:
game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
game.iRmMenu[game.iRoom] = 1;
getItem(IDI_MSA_ITEM_BONE);
printDatMessage(arg);
break;
case IDI_MSA_ACTION_GET_XTAL_EARTH:
game.iRmMenu[game.iRoom] = 1;
getXtal(arg);
break;
case IDI_MSA_ACTION_LOOK_DESK:
game.iRmMenu[game.iRoom] = 1;
game.iRmObj[game.iRoom] = 2;
drawRoom();
printDatMessage(arg);
break;
case IDI_MSA_ACTION_WRITE_LETTER:
game.iRmMenu[game.iRoom] = 3;
game.iRmMenu[IDI_MSA_PIC_EARTH_MAILBOX] = 1;
game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
getItem(IDI_MSA_ITEM_LETTER);
printDatMessage(arg);
break;
case IDI_MSA_ACTION_MAIL_LETTER:
game.fItemUsed[IDI_MSA_ITEM_LETTER] = true;
game.fItem[IDI_MSA_ITEM_LETTER] = false;
game.iRmMenu[game.iRoom] = 0;
printDatMessage(arg);
break;
case IDI_MSA_ACTION_OPEN_MAILBOX:
if (game.fItemUsed[IDI_MSA_ITEM_LETTER]) {
printDatMessage(110);
} else {
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_OPEN_CUPBOARD:
if (game.iRmMenu[game.iRoom]) {
if (game.iRmObj[game.iRoom] == IDI_MSA_OBJECT_NONE) {
printDatMessage(78);
} else {
printDatMessage(arg);
}
} else {
game.iRmMenu[game.iRoom] = 1;
game.iRmPic[game.iRoom] = IDI_MSA_PIC_EARTH_KITCHEN_1;
game.iRmObj[game.iRoom] = 3;
drawRoom();
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_FLASHLIGHT:
if (game.fItem[IDI_MSA_ITEM_FLASHLIGHT]) {
printDatMessage(90);
} else {
game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
getItem(IDI_MSA_ITEM_FLASHLIGHT);
drawRoom();
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_OPEN_CABINET:
if (game.iRmMenu[game.iRoom]) {
printDatMessage(109);
} else {
game.iRmMenu[game.iRoom] = 1;
game.iRmPic[game.iRoom] = IDI_MSA_PIC_EARTH_GARAGE_1;
game.iRmObj[game.iRoom] = 15;
drawRoom();
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_CROWBAR:
if (game.fItem[IDI_MSA_ITEM_CROWBAR]) {
printDatMessage(90);
} else {
game.iRmObj[game.iRoom]--;
getItem(IDI_MSA_ITEM_CROWBAR);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_WRENCH:
if (game.fItem[IDI_MSA_ITEM_WRENCH]) {
printDatMessage(90);
} else {
game.iRmObj[game.iRoom] -= 2;
getItem(IDI_MSA_ITEM_WRENCH);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_OPEN_CLOSET:
if (game.iRmMenu[game.iRoom]) {
printDatMessage(99);
} else {
game.iRmMenu[game.iRoom] = 1;
game.iRmPic[game.iRoom] = IDI_MSA_PIC_EARTH_BEDROOM_1;
game.iRmObj[game.iRoom] = 7;
drawRoom();
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_MATTRESS:
if (game.fItem[IDI_MSA_ITEM_MATTRESS]) {
printDatMessage(90);
} else {
game.iRmObj[game.iRoom]--;
getItem(IDI_MSA_ITEM_MATTRESS);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_SCARF:
if (game.fItem[IDI_MSA_ITEM_SCARF]) {
printDatMessage(90);
} else {
game.iRmObj[game.iRoom] -= 2;
getItem(IDI_MSA_ITEM_SCARF);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_SUNGLASSES:
if (game.fItem[IDI_MSA_ITEM_SUNGLASSES]) {
printDatMessage(90);
} else {
game.iRmObj[game.iRoom]--;
getItem(IDI_MSA_ITEM_SUNGLASSES);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_SCALE:
if (game.fItem[IDI_MSA_ITEM_SCALE]) {
printDatMessage(90);
} else {
game.iRmMenu[IDI_MSA_PIC_VENUS_WEIGH] = 1;
game.iRmMenu[IDI_MSA_PIC_NEPTUNE_WEIGH] = 1;
game.iRmMenu[IDI_MSA_PIC_MERCURY_WEIGH] = 1;
game.iRmMenu[IDI_MSA_PIC_SATURN_WEIGH] = 1;
game.iRmMenu[IDI_MSA_PIC_PLUTO_WEIGH] = 1;
game.iRmMenu[IDI_MSA_PIC_JUPITER_WEIGH] = 1;
game.iRmMenu[IDI_MSA_PIC_MARS_WEIGH] = 1;
game.iRmMenu[IDI_MSA_PIC_URANUS_WEIGH] = 1;
game.iRmObj[game.iRoom] -= 2;
getItem(IDI_MSA_ITEM_SCALE);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GOTO_SPACESHIP:
game.iRoom = IDI_MSA_PIC_SHIP_AIRLOCK;
if (game.iPlanet != IDI_MSA_PLANET_EARTH)
insertDisk(0);
return true;
// VENUS
case IDI_MSA_ACTION_DOWN_CHASM:
if (game.fItem[IDI_MSA_ITEM_ROPE]) {
game.iRmMenu[game.iRoom] = 1;
}
printDatMessage(arg);
break;
case IDI_MSA_ACTION_DOWN_ROPE:
if (game.fItemUsed[IDI_MSA_ITEM_ROPE]) {
game.iRoom = IDI_MSA_PIC_VENUS_PROBE;
return true;
} else {
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_USE_ROPE:
if (game.fItemUsed[IDI_MSA_ITEM_ROPE]) {
printDatMessage(22);
} else {
game.fItemUsed[IDI_MSA_ITEM_ROPE] = true;
game.fItem[IDI_MSA_ITEM_ROPE] = false;
game.iRmPic[game.iRoom] = IDI_MSA_PIC_VENUS_CHASM_1;
drawRoom();
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_OPEN_HATCH:
if (game.fItemUsed[IDI_MSA_ITEM_WRENCH]) {
if ((game.iRmMenu[game.iRoom] == 3) || (game.iRmPic[game.iRoom] == IDI_MSA_PIC_VENUS_PROBE_1))
printDatMessage(39);
else {
game.iRmMenu[game.iRoom] = 2;
game.iRmPic[game.iRoom] = IDI_MSA_PIC_VENUS_PROBE_1;
drawRoom();
printDatMessage(24);
}
} else {
if (game.fItem[IDI_MSA_ITEM_WRENCH]) {
game.iRmMenu[game.iRoom] = 1;
}
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_USE_WRENCH:
game.fItemUsed[IDI_MSA_ITEM_WRENCH] = true;
printDatString(arg);
if (game.iRmPic[game.iRoom] == IDI_MSA_PIC_VENUS_PROBE_1) {
//ClearRow(22); // TODO
}
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
_vm->waitAnyKey();
break;
case IDI_MSA_ACTION_GET_XTAL_VENUS:
game.iRmMenu[game.iRoom] = 3;
getXtal(arg);
break;
// TRITON (NEPTUNE)
case IDI_MSA_ACTION_LOOK_CASTLE:
if (!game.iRmMenu[game.iRoom]) {
game.iRmMenu[game.iRoom] = 1;
}
printDatMessage(arg);
break;
case IDI_MSA_ACTION_ENTER_OPENING:
if (game.fItemUsed[IDI_MSA_ITEM_CROWBAR]) {
game.iRoom = IDI_MSA_PIC_NEPTUNE_CASTLE_4;
return true;
} else {
if (game.fItem[IDI_MSA_ITEM_CROWBAR]) {
game.iRmMenu[game.iRoom] = 2;
}
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_USE_CROWBAR:
game.fItemUsed[IDI_MSA_ITEM_CROWBAR] = true;
game.iRmMenu[game.iRoom] = 1;
game.iRmPic[game.iRoom] = IDI_MSA_PIC_NEPTUNE_ENTRANCE_1;
drawRoom();
printDatMessage(arg);
break;
case IDI_MSA_ACTION_GET_XTAL_NEPTUNE:
if (game.fHasXtal) {
printDatMessage(71);
} else {
if (game.fItem[IDI_MSA_ITEM_SCARF]) {
game.iRmMenu[game.iRoom] = 1;
}
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_TALK_LEADER:
game.iRoom = IDI_MSA_PIC_NEPTUNE_ENTRYWAY;
printDatMessage(arg);
return true;
case IDI_MSA_ACTION_GIVE_SCARF:
game.iRmObj[game.iRoom] = 18;
getXtal(arg);
game.fItem[IDI_MSA_ITEM_SCARF] = false;
game.iRmMenu[game.iRoom] = 0;
game.iRmMenu[IDI_MSA_PIC_EARTH_BEDROOM] = 2;
game.iRoom = IDI_MSA_PIC_NEPTUNE_ENTRYWAY;
return true;
// MERCURY
case IDI_MSA_ACTION_GET_XTAL_MERCURY:
if (game.fHasXtal) {
game.iRmMenu[game.iRoom] = 2;
printDatMessage(32);
} else {
if (game.fItem[IDI_MSA_ITEM_SUNGLASSES]) {
game.iRmMenu[game.iRoom] = 1;
}
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GIVE_SUNGLASSES:
game.iRmObj[game.iRoom] = 17;
game.iRmMenu[game.iRoom] = 2;
game.fItem[IDI_MSA_ITEM_SUNGLASSES] = false;
getXtal(arg);
break;
// TITAN (SATURN)
case IDI_MSA_ACTION_CROSS_LAKE:
if (game.fItem[IDI_MSA_ITEM_MATTRESS]) {
game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_0] = 1;
game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_1] = 1;
game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_2] = 1;
}
printDatMessage(arg);
break;
case IDI_MSA_ACTION_USE_MATTRESS:
game.iRoom = IDI_MSA_PIC_SATURN_ISLAND;
printDatMessage(arg);
return true;
case IDI_MSA_ACTION_GET_XTAL_SATURN:
if (game.fHasXtal) {
printDatMessage(29);
} else {
getXtal(arg);
}
break;
case IDI_MSA_ACTION_LEAVE_ISLAND:
game.iRoom = IDI_MSA_PIC_SATURN_LAKE_1;
printDatMessage(arg);
return true;
// PLUTO
case IDI_MSA_ACTION_GET_XTAL_PLUTO:
if (game.fHasXtal) {
printDatMessage(19);
} else {
if (game.fItem[IDI_MSA_ITEM_BONE]) {
game.iRmMenu[game.iRoom] = 1;
}
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GIVE_BONE:
game.fItem[IDI_MSA_ITEM_BONE] = false;
game.iRmMenu[game.iRoom] = 0;
game.iRmObj[game.iRoom] = 16;
getXtal(arg);
break;
// IO (JUPITER)
case IDI_MSA_ACTION_GET_ROCK_0:
if (game.fItem[IDI_MSA_ITEM_ROCK]) {
printDatMessage(38);
} else {
game.iRmMenu[game.iRoom] = 1;
game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
getItem(IDI_MSA_ITEM_ROCK);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_ROCK_1:
if (game.fItem[IDI_MSA_ITEM_ROCK]) {
printDatMessage(38);
} else {
game.iRmMenu[game.iRoom] = 1;
game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
getItem(IDI_MSA_ITEM_ROCK);
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_XTAL_JUPITER:
if (game.fHasXtal) {
printDatMessage(15);
} else {
switch (game.nRocks) {
case 0:
if (game.fItem[IDI_MSA_ITEM_ROCK]) {
game.iRmMenu[game.iRoom] = 1;
}
printDatMessage(arg);
break;
case 1:
if (game.fItem[IDI_MSA_ITEM_ROCK]) {
game.iRmMenu[game.iRoom] = 1;
}
printDatMessage(34);
break;
case 2:
getXtal(35);
break;
}
}
break;
case IDI_MSA_ACTION_THROW_ROCK:
game.fItem[IDI_MSA_ITEM_ROCK] = false;
game.nItems--;
game.iRmObj[game.iRoom]++;
game.iRmMenu[game.iRoom] = 0;
drawRoom();
if (game.nRocks) {
printDatMessage(37);
} else {
printDatMessage(arg);
}
game.nRocks++;
break;
// MARS
case IDI_MSA_ACTION_GO_TUBE:
if (game.fItem[IDI_MSA_ITEM_FLASHLIGHT]) {
game.iRmMenu[game.iRoom] = 1;
}
printDatMessage(arg);
break;
case IDI_MSA_ACTION_USE_FLASHLIGHT:
game.iRoom = IDI_MSA_PIC_MARS_TUBE_1;
printDatMessage(15);
return true;
case IDI_MSA_ACTION_PLUTO_DIG:
if (game.fHasXtal) {
printDatMessage(21);
} else {
getXtal(arg);
}
break;
case IDI_MSA_ACTION_GET_XTAL_MARS:
if (game.fHasXtal) {
printDatMessage(23);
} else {
printDatMessage(arg);
}
break;
// OBERON (URANUS)
case IDI_MSA_ACTION_ENTER_TEMPLE:
game.iRoom = IDI_MSA_PIC_URANUS_TEMPLE;
return true;
case IDI_MSA_ACTION_USE_CRYSTAL:
if (game.iRmMenu[game.iRoom]) {
printDatMessage(25);
} else {
game.iRmMenu[game.iRoom] = 1;
game.iRmPic[game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE_1;
drawRoom();
game.iRmPic[game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE;
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_OPEN_DOOR:
if (game.fTempleDoorOpen) {
printDatMessage(36);
} else {
game.fTempleDoorOpen = 1;
game.iRmPic[game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE_2;
drawRoom();
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_ENTER_DOOR:
if (game.fTempleDoorOpen) {
game.iRoom = IDI_MSA_PIC_URANUS_STEPS;
return true;
} else {
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GET_XTAL_URANUS:
if (game.fHasXtal) {
printDatMessage(34);
} else {
if (game.fItem[IDI_MSA_ITEM_CROWBAR]) {
game.iRmMenu[game.iRoom] = 1;
}
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_USE_CROWBAR_1:
game.iRmMenu[game.iRoom] = 0;
getXtal(arg);
break;
// SPACESHIP
case IDI_MSA_ACTION_GO_NORTH:
if (game.fShipDoorOpen) {
if (game.fSuit) {
printDatMessage(45);
} else {
game.iRoom = IDI_MSA_PIC_SHIP_CORRIDOR;
return true;
}
} else {
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_GO_PLANET:
if (!game.fShipDoorOpen) {
if ((game.nXtals == IDI_MSA_MAX_PLANET) && (game.iPlanet == IDI_MSA_PLANET_EARTH))
gameOver();
if ((game.iPlanet == game.iPlanetXtal[game.nXtals]) || (game.iPlanet == IDI_MSA_PLANET_EARTH)) {
game.fHasXtal = false;
game.iRoom = IDI_MSA_HOME_PLANET[game.iPlanet];
if (game.iPlanet != IDI_MSA_PLANET_EARTH)
insertDisk(1);
return true;
} else {
game.iRoom = IDI_MSA_SHIP_PLANET[game.iPlanet];
return true;
}
} else {
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_PRESS_BUTTON:
if (game.fShipDoorOpen) { // inner door open
if (game.iPlanet && !game.fSuit) {
printDatMessage(arg);
} else {
game.fShipDoorOpen = false;
game.iRmPic[game.iRoom]--;
drawRoom();
printDatMessage(2);
}
} else {
game.fShipDoorOpen = true;
game.iRmPic[game.iRoom]++;
drawRoom();
printDatMessage(14);
}
break;
case IDI_MSA_ACTION_WEAR_SPACESUIT:
if (game.fSuit) {
if (game.fShipDoorOpen) {
game.fSuit = false;
game.iRmMenu[game.iRoom] = 0;
game.iRmPic[game.iRoom] -= 2;
drawRoom();
printDatMessage(13);
} else {
printDatMessage(3);
}
} else {
if (game.iPlanet) {
game.fSuit = true;
game.iRmMenu[game.iRoom] = 1;
game.iRmPic[game.iRoom] += 2;
drawRoom();
printDatMessage(arg);
} else {
printDatMessage(12);
}
}
break;
case IDI_MSA_ACTION_READ_GAUGE:
printDatString(arg);
/*
drawStr(IDI_MSA_ROW_TEMPERATURE, IDI_MSA_COL_TEMPERATURE_C,
(char *)IDS_MSA_TEMP_C[game.iPlanet]);
drawStr(IDI_MSA_ROW_TEMPERATURE, IDI_MSA_COL_TEMPERATURE_F,
(char *)IDS_MSA_TEMP_F[game.iPlanet]);
*/
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
_vm->waitAnyKey();
break;
case IDI_MSA_ACTION_PRESS_ORANGE:
if (game.fFlying) {
printDatMessage(4);
} else {
//playSound(IDI_MSA_SND_PRESS_ORANGE); // TODO
printDatMessage(arg);
pressOB(IDI_MSA_BUTTON_ORANGE);
}
break;
case IDI_MSA_ACTION_PRESS_BLUE:
if (game.fFlying) {
printDatMessage(4);
} else {
//playSound(IDI_MSA_SND_PRESS_BLUE); // TODO
printDatMessage(arg);
pressOB(IDI_MSA_BUTTON_BLUE);
}
break;
case IDI_MSA_ACTION_FLIP_SWITCH:
flipSwitch();
break;
case IDI_MSA_ACTION_PUSH_THROTTLE:
if (game.fFlying) {
game.fFlying = false;
game.nButtons = 0;
memset(game.szAddr, 0, sizeof(game.szAddr));
drawRoom();
printDatString(22);
// TODO
//drawStr(IDI_MSA_ROW_PLANET, IDI_MSA_COL_PLANET,
// (char *)IDS_MSA_PLANETS[game.iPlanet]);
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
_vm->waitAnyKeyAnim();
showPlanetInfo();
} else {
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_PULL_THROTTLE:
if (game.fFlying) {
printDatMessage(18);
} else {
if (getPlanet() != -1) {
game.fFlying = true;
game.iPlanet = getPlanet();
drawRoom();
printDatMessage(16);
} else {
game.nButtons = 0;
memset(game.szAddr, 0, sizeof(game.szAddr));
printDatMessage(17);
}
}
break;
case IDI_MSA_ACTION_LEAVE_ROOM:
if (game.fFlying) {
printDatMessage(24);
} else {
game.iRoom = arg;
return true;
}
break;
case IDI_MSA_ACTION_OPEN_CABINET_1:
if (game.iRmMenu[game.iRoom]) {
printExeMsg(IDO_MSA_THE_CABINET_IS_ALREADY_OPEN);
} else {
game.iRmMenu[game.iRoom] = 1;
game.iRmPic[game.iRoom] = IDI_MSA_PIC_SHIP_KITCHEN_1;
drawRoom();
printDatMessage(arg);
}
break;
case IDI_MSA_ACTION_READ_MAP:
game.iRmPic[game.iRoom] = IDI_MSA_PIC_STAR_MAP;
drawRoom();
printDatMessage(46);
printDatMessage(47);
printDatMessage(48);
game.iRmPic[game.iRoom] = IDI_MSA_PIC_SHIP_BEDROOM;
drawRoom();
break;
case IDI_MSA_ACTION_GO_WEST:
game.nButtons = 0;
memset(game.szAddr, 0, sizeof(game.szAddr));
game.iRoom = arg;
return true;
}
return false;
}
void Mickey::gameLoop() {
char *buffer = new char[sizeof(MSA_MENU)];
MSA_MENU menu;
int iSel0, iSel1;
bool done;
for (;;) {
drawRoom();
if (game.fIntro) {
game.fIntro = false;
} else {
printRoomDesc();
}
if (game.iRoom == IDI_MSA_PIC_NEPTUNE_GUARD) {
game.iRoom = IDI_MSA_PIC_NEPTUNE_LEADER;
done = true;
} else {
done = false;
}
while (!done) {
checkAirSupply(game.fSuit, &game.nAir);
readMenu(game.iRoom, buffer);
memcpy(&menu, buffer, sizeof(MSA_MENU));
patchMenu(&menu);
memcpy(buffer, &menu, sizeof(MSA_MENU));
getMenuSel(buffer, &iSel0, &iSel1);
done = parse(menu.cmd[iSel0].data[iSel1], menu.arg[iSel0].data[iSel1]);
}
game.nFrame = 0;
}
delete [] buffer;
}
// Debug
void Mickey::debug_DrawObjs() {
char szTitle[14] = {0};
for (int iObj = 0; iObj < IDI_MSA_MAX_OBJ; iObj++) {
drawPic(0);
drawObj((ENUM_MSA_OBJECT)iObj, 0, 0);
///clearTextArea(); // TODO
sprintf(szTitle, "Object %d", iObj);
// TODO
//drawStrAttrMiddle(22, IDA_DEFAULT, szTitle);
//drawStrAttrMiddle(23, IDA_DEFAULT, (char *)IDS_MSA_NAME_OBJ[iObj]);
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
_vm->waitAnyKey();
}
}
void Mickey::debug_DrawPics(){
char szTitle[14] = {0};
for (int iPic = 1; iPic <= IDI_MSA_MAX_PIC; iPic++) {
drawPic(iPic);
//clearTextArea(); // TODO
sprintf(szTitle, "Picture %d", iPic);
//drawStrAttrMiddle(22, IDA_DEFAULT, szTitle); // TODO
_vm->_gfx->doUpdate();
_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
_vm->waitAnyKey();
}
}
// Init
void Mickey::initVars() {
uint8 buffer[512];
// clear game struct
memset(&game, 0, sizeof(game));
memset(&game.iItem, IDI_MSA_OBJECT_NONE, sizeof(game.iItem));
// read room extended desc flags
readExe(IDO_MSA_ROOM_TEXT, buffer, sizeof(buffer));
memcpy(game.fRmTxt, buffer, sizeof(game.fRmTxt));
// read room extended desc offsets
readExe(IDO_MSA_ROOM_TEXT_OFFSETS, buffer, sizeof(buffer));
// memcpy(game.oRmTxt, buffer, sizeof(game.oRmTxt));
for (int i = 0; i < IDI_MSA_MAX_ROOM; i++)
game.oRmTxt[i] = buffer[i*2] + 256 * buffer[i*2+1];
// read room object indices
readExe(IDO_MSA_ROOM_OBJECT, buffer, sizeof(buffer));
memcpy(game.iRmObj, buffer, sizeof(game.iRmObj));
// read room picture indices
//Mickey_readExe(IDO_MSA_ROOM_PICTURE, buffer, sizeof(buffer));
//memcpy(game.iRmPic, buffer, sizeof(game.iRmPic));
// read room menu patch indices
readExe(IDO_MSA_ROOM_MENU_FIX, buffer, sizeof(buffer));
memcpy(game.nRmMenu, buffer, sizeof(game.nRmMenu));
// set room picture indices
for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
game.iRmPic[i] = i;
}
game.iRmPic[IDI_MSA_PIC_SHIP_AIRLOCK] = IDI_MSA_PIC_SHIP_AIRLOCK_0;
#ifdef _DEBUG
game.iPlanet = IDI_MSA_PLANET_EARTH;
game.iRoom = IDI_MSA_PIC_SHIP_CONTROLS;
game.fHasXtal = true;
game.nXtals = 9;
game.fItemUsed[IDI_MSA_ITEM_LETTER] = true;
#endif
}
void Mickey::initEngine() {
// PreAGI sets the screen params here, but we've already done that in the preagi class
}
Mickey::Mickey(PreAgiEngine *vm) : _vm(vm) {
}
Mickey::~Mickey() {
}
void Mickey::init() {
initEngine();
initVars();
}
void Mickey::run() {
intro();
gameLoop();
gameOver();
}
}