diff options
author | Filippos Karapetis | 2007-09-01 18:46:55 +0000 |
---|---|---|
committer | Filippos Karapetis | 2007-09-01 18:46:55 +0000 |
commit | 9db1525e50e76760cf4b5500de50514c08871886 (patch) | |
tree | e0dd0d086b20ad69b7326dd96f13cfbf93c0fa6b /engines/agi/preagi_mickey.cpp | |
parent | 9644a764b82c3ac07c900b481a1aad94baf6e6ef (diff) | |
download | scummvm-rg350-9db1525e50e76760cf4b5500de50514c08871886.tar.gz scummvm-rg350-9db1525e50e76760cf4b5500de50514c08871886.tar.bz2 scummvm-rg350-9db1525e50e76760cf4b5500de50514c08871886.zip |
Added WIP logic code for Mickey's Space Adventure
svn-id: r28800
Diffstat (limited to 'engines/agi/preagi_mickey.cpp')
-rw-r--r-- | engines/agi/preagi_mickey.cpp | 2053 |
1 files changed, 1993 insertions, 60 deletions
diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp index 6cbc316543..f82fb7ef8a 100644 --- a/engines/agi/preagi_mickey.cpp +++ b/engines/agi/preagi_mickey.cpp @@ -23,71 +23,779 @@ * */ +#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 { -Mickey::Mickey(PreAgiEngine *vm) : _vm(vm) { +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; } -Mickey::~Mickey() { +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::init() { +void Mickey::getDatFileName(int iRoom, char *szFile) { + sprintf(szFile, IDS_MSA_PATH_DAT, IDS_MSA_NAME_DAT[getDat(iRoom)]); } -void Mickey::run() { - intro(); - while(true) { - _vm->getSelection(0); - _vm->_system->delayMillis(10); +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; } - //gameLoop(); - //gameOver(); + 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::intro() { - // draw sierra logo - drawLogo(); +void Mickey::readDesc(int iRoom, char *buffer, long buflen) { + MSA_DAT_HEADER hdr; + char szFile[256] = {0}; - // draw title picture - game.iRoom = IDI_MSA_PIC_TITLE; - drawRoom(); + getDatFileName(iRoom, szFile); + readDatHdr(szFile, &hdr); + + Common::File infile; -#if 0 - // show copyright and play theme - PrintExeMsg(IDO_MSA_COPYRIGHT); - PlaySound(IDI_MSA_SND_THEME); - - // 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; + 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; + } + 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(¬e, 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]); } } +} - // play spaceship landing scene - game.iPlanet = IDI_MSA_PLANET_EARTH; - game.iRoom = IDI_MSA_PIC_EARTH_ROAD_4; +void Mickey::drawRoomObjects() { + if (game.iRoom >= IDI_MSA_MAX_PIC_ROOM) + return; - DrawRoom(); - PrintRoomDesc(); + uint8 buffer[256]; + int pBuf = 0; + int nObjs; - #ifndef _DEBUG - PlaySound(IDI_MSA_SND_SHIP_LAND); - #endif + // 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); + } + } - FlashScreen(); - FlashScreen(); - FlashScreen(); + // draw objects - PrintExeMsg(IDO_MSA_INTRO); -#endif + 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() { @@ -101,40 +809,1265 @@ void Mickey::drawLogo() { return; infile.read(buffer, infile.size()); infile.close(); - + // draw logo bitmap - // TODO - //drawPictureBCG(buffer); - //updateScreen(); + //drawPictureBCG(buffer); // TODO + _vm->_gfx->doUpdate(); + _vm->_system->updateScreen(); // TODO: this should go in the game's main loop delete [] buffer; } -void Mickey::drawRoomPicture() { - if (false) { //(getDebug()) { - drawPic(0); - //debug(); // TODO +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 { - if (game.iRoom == IDI_MSA_PIC_TITLE) { - drawPic(IDI_MSA_PIC_TITLE); + *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 { - drawPic(game.iRmPic[game.iRoom]); + 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::drawPic(int iPic) { - _vm->preAgiLoadResource(rPICTURE, iPic); - _vm->_picture->decodePicture(iPic, true); - _vm->_picture->showPic(); +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::drawRoom() { - drawRoomPicture(); - //drawRoomObjects(); - //drawRoomAnimation(); +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(); + +#ifndef _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(); } } |