diff options
Diffstat (limited to 'engines/agi/preagi_winnie.cpp')
-rw-r--r-- | engines/agi/preagi_winnie.cpp | 1127 |
1 files changed, 1127 insertions, 0 deletions
diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp new file mode 100644 index 0000000000..8d60f0861e --- /dev/null +++ b/engines/agi/preagi_winnie.cpp @@ -0,0 +1,1127 @@ +/* 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 "agi/preagi.h" +#include "agi/preagi_winnie.h" +#include "agi/graphics.h" + +#include "graphics/cursorman.h" + +#include "common/events.h" +#include "common/savefile.h" + +namespace Agi { + +// default attributes +#define IDA_DEFAULT 0x0F +#define IDA_DEFAULT_REV 0xF0 + +void Winnie::initEngine() { + //SetScreenPar(320, 200, (char*)ibm_fontdata); + //SetMenuPars(21, 21, IDS_WTP_SELECTION); +} + +void Winnie::initVars() { + memset(&game, 0, sizeof(game)); + game.fSound = 1; + game.nObjMiss = IDI_WTP_MAX_OBJ_MISSING; + game.nObjRet = 0; + game.fGame[0] = 1; + game.fGame[1] = 1; + room = IDI_WTP_ROOM_HOME; + + mist = -1; + doWind = false; + winnie_event = false; +} + +void Winnie::readRoom(int iRoom, uint8 *buffer, int buflen) { + char szFile[256] = {0}; + sprintf(szFile, IDS_WTP_PATH_ROOM, iRoom); + Common::File file; + if (!file.open(szFile)) + return; + uint32 filelen = file.size(); + memset(buffer, 0, sizeof(buffer)); + file.read(buffer, filelen); + file.close(); +} + +void Winnie::readObj(int iObj, uint8 *buffer, int buflen) { + char szFile[256] = {0}; + sprintf(szFile, IDS_WTP_PATH_OBJ, iObj); + Common::File file; + if (!file.open(szFile)) + return; + uint32 filelen = file.size(); + memset(buffer, 0, sizeof(buffer)); + file.read(buffer, filelen); + file.close(); +} + +void Winnie::randomize() { + int iObj = 0; + int iRoom = 0; + bool done; + + for (int i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++) { + done = false; + while (!done) { + iObj = _vm->rnd(IDI_WTP_MAX_OBJ - 1) + 2; + done = true; + for (int j = 0; j < IDI_WTP_MAX_OBJ_MISSING; j++) { + if (game.iUsedObj[j] == iObj) { + done = false; + break; + } + } + } + + game.iUsedObj[i] = iObj; + + done = false; + while (!done) { + iRoom = _vm->rnd(IDI_WTP_MAX_ROOM_NORMAL) + 1; + done = true; + for (int j = 0; j < IDI_WTP_MAX_ROOM_OBJ; j++) { + if (game.iObjRoom[j] == iRoom) { + done = false; + break; + } + } + } + + game.iObjRoom[iObj] = iRoom; + } +} + +void Winnie::intro() { + drawPic(IDS_WTP_FILE_LOGO); + _vm->printStr(IDS_WTP_INTRO_0); + _vm->_system->delayMillis(0x640); + drawPic(IDS_WTP_FILE_TITLE); + _vm->printStr(IDS_WTP_INTRO_1); + _vm->_system->delayMillis(0x640); + //if (!Winnie_PlaySound(IDI_WTP_SND_POOH_0)) return; + //if (!Winnie_PlaySound(IDI_WTP_SND_POOH_1)) return; + //if (!Winnie_PlaySound(IDI_WTP_SND_POOH_2)) return; +} + +int Winnie::getObjInRoom(int iRoom) { + for (int iObj = 1; iObj < IDI_WTP_MAX_ROOM_OBJ; iObj++) + if (game.iObjRoom[iObj] == iRoom) + return iObj; + return 0; +} + +#define setTakeDrop() {\ + if (getObjInRoom(room))\ + fCanSel[IDI_WTP_SEL_TAKE] = true;\ + else\ + fCanSel[IDI_WTP_SEL_TAKE] = false;\ + if (game.iObjHave)\ + fCanSel[IDI_WTP_SEL_DROP] = true;\ + else\ + fCanSel[IDI_WTP_SEL_DROP] = false;\ +} + +void Winnie::setFlag(int iFlag) { + game.fGame[iFlag] = 1; +} + +void Winnie::clearFlag(int iFlag) { + game.fGame[iFlag] = 0; +} + +int Winnie::parser(int pc, int index, uint8 *buffer) { + WTP_ROOM_HDR hdr; + int startpc = pc; + int8 opcode; + int iNewRoom = 0; + + int iSel, iDir, iBlock; + int fCanSel[IDI_WTP_SEL_LAST + 1]; + char szMenu[121] = {0}; + bool done; + int fBlock; + + // extract header from buffer + memcpy(&hdr, buffer, sizeof(WTP_ROOM_HDR)); + + for (;;) { + pc = startpc; + + // check if block is to be run + + iBlock = *(buffer + pc++); + if (iBlock == 0) + return IDI_WTP_PAR_OK; + + fBlock = *(buffer + pc++); + if (game.fGame[iBlock] != fBlock) + return IDI_WTP_PAR_OK; + + // extract text from block + + opcode = *(buffer + pc); + switch(opcode) { + case 0: + case IDO_WTP_OPTION_0: + case IDO_WTP_OPTION_1: + case IDO_WTP_OPTION_2: + // clear fCanSel block + memset(fCanSel, 0, sizeof(fCanSel)); + + // check if NSEW directions should be displayed + if (hdr.roomNew[0]) + fCanSel[IDI_WTP_SEL_NORTH] = fCanSel[IDI_WTP_SEL_SOUTH] = + fCanSel[IDI_WTP_SEL_EAST] = fCanSel[IDI_WTP_SEL_WEST] = true; + + // check if object in room or player carrying one + setTakeDrop(); + + // check which rows have a menu option + for (iSel = 0; iSel < IDI_WTP_MAX_OPTION; iSel++) { + opcode = *(buffer + pc++); + if (opcode) { + fCanSel[opcode - IDO_WTP_OPTION_0] = true; + fCanSel[iSel + IDI_WTP_SEL_REAL_OPT_1] = opcode - 0x14; + } + } + + // extract menu string + strcpy(szMenu, (char *)(buffer + pc)); + _vm->XOR80(szMenu); + break; + default: + // print description + _vm->printStrXOR((char *)(buffer + pc)); + if (getSelOkBack()) + return IDI_WTP_PAR_OK; + else + return IDI_WTP_PAR_BACK; + } + + // input handler + + done = false; + while (!done) { + // run wind if it's time + if (doWind) + wind(); + + // get menu selection + getMenuSel(szMenu, &iSel, fCanSel); + + if (++game.nMoves == IDI_WTP_MAX_MOVES_UNTIL_WIND) + doWind = true; + + if (winnie_event && (room <= IDI_WTP_MAX_ROOM_TELEPORT)) { + if (!tigger_mist) { + tigger_mist = 1; + //Winnie_Tigger(); + } else { + tigger_mist = 0; + //Winnie_Mist(); + } + winnie_event = false; + return IDI_WTP_PAR_GOTO; + } + + // process selection + switch(iSel) { + case IDI_WTP_SEL_HOME: + switch(room) { + case IDI_WTP_ROOM_HOME: + case IDI_WTP_ROOM_MIST: + case IDI_WTP_ROOM_TIGGER: + break; + default: + room = IDI_WTP_ROOM_HOME; + return IDI_WTP_PAR_GOTO; + } + break; + case IDI_WTP_SEL_BACK: + return IDI_WTP_PAR_BACK; + case IDI_WTP_SEL_OPT_1: + case IDI_WTP_SEL_OPT_2: + case IDI_WTP_SEL_OPT_3: + done = true; + break; + case IDI_WTP_SEL_NORTH: + case IDI_WTP_SEL_SOUTH: + case IDI_WTP_SEL_EAST: + case IDI_WTP_SEL_WEST: + iDir = iSel - IDI_WTP_SEL_NORTH; + if (hdr.roomNew[iDir] == IDI_WTP_ROOM_NONE) { + _vm->printStr(IDS_WTP_CANT_GO); + _vm->waitAnyKeyChoice(); + } else { + room = hdr.roomNew[iDir]; + return IDI_WTP_PAR_GOTO; + } + break; + case IDI_WTP_SEL_TAKE: + takeObj(room); + setTakeDrop(); + break; + case IDI_WTP_SEL_DROP: + dropObj(room); + setTakeDrop(); + break; + } + } + + // jump to the script block of the selected option + pc = hdr.opt[index].ofsOpt[iSel] - IDI_WTP_OFS_ROOM; + opcode = *(buffer + pc); + if (!opcode) pc++; + + // process script + do { + opcode = *(buffer + pc++); + switch(opcode) { + case IDO_WTP_GOTO_ROOM: + opcode = *(buffer + pc++); + iNewRoom = opcode; + break; + case IDO_WTP_PRINT_MSG: + opcode = *(buffer + pc++); + printRoomStr(room, opcode); + _vm->waitAnyKeyChoice(); + break; + case IDO_WTP_PRINT_STR: + opcode = *(buffer + pc++); + printRoomStr(room, opcode); + break; + case IDO_WTP_DROP_OBJ: + opcode = *(buffer + pc++); + opcode = -1; + dropObjRnd(); + break; + case IDO_WTP_FLAG_CLEAR: + opcode = *(buffer + pc++); + clearFlag(opcode); + break; + case IDO_WTP_FLAG_SET: + opcode = *(buffer + pc++); + setFlag(opcode); + break; + case IDO_WTP_GAME_OVER: + gameOver(); + break; + case IDO_WTP_WALK_MIST: + mist--; + if (!mist) { + room = _vm->rnd(IDI_WTP_MAX_ROOM_TELEPORT) + 1; + return IDI_WTP_PAR_GOTO; + } + break; + case IDO_WTP_PLAY_SOUND: + opcode = *(buffer + pc++); + //Winnie_PlaySound((ENUM_WTP_SOUND)opcode); + break; + case IDO_WTP_SAVE_GAME: + saveGame(); + room = IDI_WTP_ROOM_HOME; + return IDI_WTP_PAR_GOTO; + case IDO_WTP_LOAD_GAME: + loadGame(); + room = IDI_WTP_ROOM_HOME; + return IDI_WTP_PAR_GOTO; + case IDO_WTP_OWL_HELP: + opcode = *(buffer + pc++); + showOwlHelp(); + break; + case IDO_WTP_GOTO_RND: + room = _vm->rnd(IDI_WTP_MAX_ROOM_TELEPORT) + 1; + return IDI_WTP_PAR_GOTO; + default: + opcode = 0; + break; + } + } while (opcode); + + if (iNewRoom) { + room = iNewRoom; + return IDI_WTP_PAR_GOTO; + } + + if (iBlock == 1) + return IDI_WTP_PAR_OK; + } +} + +void Winnie::keyHelp() { + //Winnie_PlaySound(IDI_WTP_SND_KEYHELP); + _vm->printStr(IDS_WTP_HELP_0); + _vm->waitAnyKeyChoice(); + _vm->printStr(IDS_WTP_HELP_1); + _vm->waitAnyKeyChoice(); +} + +void Winnie::inventory() { + char szMissing[41] = {0}; + + if (game.iObjHave) + printObjStr(game.iObjHave, IDI_WTP_OBJ_TAKE); + else { + _vm->clearTextArea(); + _vm->drawStr(IDI_WTP_ROW_MENU, IDI_WTP_COL_MENU, IDA_DEFAULT, IDS_WTP_INVENTORY_0); + } + + sprintf(szMissing, IDS_WTP_INVENTORY_1, game.nObjMiss); + _vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_MENU, IDA_DEFAULT, szMissing); + _vm->_gfx->doUpdate(); + _vm->_system->updateScreen(); + _vm->waitAnyKeyChoice(); +} + +void Winnie::printObjStr(int iObj, int iStr) { + WTP_OBJ_HDR hdr; + uint8 *buffer = (uint8 *)malloc(2048); + + readObj(iObj, buffer, 2048); + memcpy(&hdr, buffer, sizeof(hdr)); + _vm->printStrXOR((char *)(buffer + hdr.ofsStr[iStr] - IDI_WTP_OFS_OBJ)); + + free(buffer); +} + +bool Winnie::isRightObj(int iRoom, int iObj, int *iCode) { + WTP_ROOM_HDR roomhdr; + WTP_OBJ_HDR objhdr; + uint8 *roomdata = new uint8[4096]; + uint8 *objdata = new uint8[2048]; + + readRoom(iRoom, roomdata, 4096); + memcpy(&roomhdr, roomdata, sizeof(WTP_ROOM_HDR)); + readObj(iObj, objdata, 2048); + memcpy(&objhdr, objdata, sizeof(WTP_OBJ_HDR)); + + delete [] roomdata; + delete [] objdata; + + *iCode = objhdr.objId; + + if (objhdr.objId == 11) objhdr.objId = 34; + + if (roomhdr.objId == objhdr.objId) + return true; + else + return false; +} + +void Winnie::takeObj(int iRoom) { + if (game.iObjHave) { + // player is already carrying an object, can't take + _vm->printStr(IDS_WTP_CANT_TAKE); + _vm->waitAnyKeyChoice(); + } else { + // take object + int iObj = getObjInRoom(iRoom); + game.iObjHave = iObj; + game.iObjRoom[iObj] = 0; + + _vm->printStr(IDS_WTP_OK); + //Winnie_PlaySound(IDI_WTP_SND_TAKE); + + drawRoomPic(); + + // print object "take" string + printObjStr(game.iObjHave, IDI_WTP_OBJ_TAKE); + _vm->waitAnyKeyChoice(); + + // HACK WARNING + if (iObj == 18) { + game.fGame[0x0d] = 1; + } + } +} + +void Winnie::dropObj(int iRoom) { + int iCode; + + if (getObjInRoom(iRoom)) { + // there already is an object in the room, can't drop + _vm->printStr(IDS_WTP_CANT_DROP); + _vm->waitAnyKeyChoice(); + } else { + // HACK WARNING + if (game.iObjHave == 18) { + game.fGame[0x0d] = 0; + } + + if (isRightObj(iRoom, game.iObjHave, &iCode)) { + // object has been dropped in the right place + _vm->printStr(IDS_WTP_OK); + _vm->waitAnyKeyChoice(); + //Winnie_PlaySound(IDI_WTP_SND_DROP_OK); + printObjStr(game.iObjHave, IDI_WTP_OBJ_DROP); + _vm->waitAnyKeyChoice(); + + // increase amount of objects returned, decrease amount of objects missing + game.nObjMiss--; + game.nObjRet++; + + // xor the dropped object with 0x80 to signify it has been dropped in the right place + for (int i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++) { + if (game.iUsedObj[i] == game.iObjHave) { + game.iUsedObj[i] ^= 0x80; + break; + } + } + + // set flag according to dropped object's id + game.fGame[iCode] = 1; + + // player is carrying nothing + game.iObjHave = 0; + + if (!game.nObjMiss) { + // all objects returned, tell player to find party + //Winnie_PlaySound(IDI_WTP_SND_FANFARE); + _vm->printStr(IDS_WTP_GAME_OVER_0); + _vm->waitAnyKeyChoice(); + _vm->printStr(IDS_WTP_GAME_OVER_1); + _vm->waitAnyKeyChoice(); + } + } else { + // drop object in the given room + game.iObjRoom[game.iObjHave] = iRoom; + + // object has been dropped in the wrong place + _vm->printStr(IDS_WTP_WRONG_PLACE); + _vm->waitAnyKeyChoice(); + //Winnie_PlaySound(IDI_WTP_SND_DROP); + drawRoomPic(); + _vm->printStr(IDS_WTP_WRONG_PLACE); + _vm->waitAnyKeyChoice(); + + // print object description + printObjStr(game.iObjHave, IDI_WTP_OBJ_DESC); + _vm->waitAnyKeyChoice(); + + game.iObjHave = 0; + } + } +} + +void Winnie::dropObjRnd() { + if (!game.iObjHave) + return; + + int iRoom = 0; + bool done = false; + + while (!done) { + iRoom = _vm->rnd(IDI_WTP_MAX_ROOM_NORMAL); + done = true; + if (iRoom == room) + done = false; + for (int j = 0; j < IDI_WTP_MAX_ROOM_OBJ; j++) { + if (game.iObjRoom[j] == iRoom) { + done = false; + } + } + } + + game.iObjRoom[game.iObjHave] = iRoom; + game.iObjHave = 0; +} + +void Winnie::wind() { + int iRoom = 0; + bool done; + + doWind = 0; + game.nMoves = 0; + if (!game.nObjMiss) + return; + + _vm->printStr(IDS_WTP_WIND_0); + //Winnie_PlaySound(IDI_WTP_SND_WIND_0); + _vm->waitAnyKeyChoice(); + _vm->printStr(IDS_WTP_WIND_1); + //Winnie_PlaySound(IDI_WTP_SND_WIND_0); + _vm->waitAnyKeyChoice(); + + dropObjRnd(); + + // randomize positions of objects at large + for (int i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++) { + if (!(game.iUsedObj[i] & IDI_XOR_KEY)) { + done = false; + while (!done) { + iRoom = _vm->rnd(IDI_WTP_MAX_ROOM_NORMAL); + done = true; + for (int j = 0; j < IDI_WTP_MAX_ROOM_OBJ; j++) { + if (game.iObjRoom[j] == iRoom) { + done = false; + } + } + } + game.iObjRoom[game.iUsedObj[i]] = iRoom; + } + } +} + +void Winnie::showOwlHelp() { + if (game.iObjHave) { + _vm->printStr(IDS_WTP_OWL_0); + _vm->waitAnyKeyChoice(); + printObjStr(game.iObjHave, IDI_WTP_OBJ_HELP); + _vm->waitAnyKeyChoice(); + } + if (getObjInRoom(room)) { + _vm->printStr(IDS_WTP_OWL_0); + _vm->waitAnyKeyChoice(); + printObjStr(getObjInRoom(room), IDI_WTP_OBJ_HELP); + _vm->waitAnyKeyChoice(); + } +} + + +void Winnie::drawMenu(char *szMenu, int iSel, int fCanSel[]) { + int iRow = 0, iCol = 0; + + _vm->clearTextArea(); + _vm->drawStr(IDI_WTP_ROW_MENU, IDI_WTP_COL_MENU, IDA_DEFAULT, szMenu); + + if (fCanSel[IDI_WTP_SEL_NORTH]) + _vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_NSEW, IDA_DEFAULT, IDS_WTP_NSEW); + if (fCanSel[IDI_WTP_SEL_TAKE]) + _vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_TAKE, IDA_DEFAULT, IDS_WTP_TAKE); + if (fCanSel[IDI_WTP_SEL_DROP]) + _vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_DROP, IDA_DEFAULT, IDS_WTP_DROP); + + switch(iSel) { + case IDI_WTP_SEL_OPT_1: + iRow = IDI_WTP_ROW_OPTION_1; + iCol = IDI_WTP_COL_OPTION; + break; + case IDI_WTP_SEL_OPT_2: + iRow = IDI_WTP_ROW_OPTION_2; + iCol = IDI_WTP_COL_OPTION; + break; + case IDI_WTP_SEL_OPT_3: + iRow = IDI_WTP_ROW_OPTION_3; + iCol = IDI_WTP_COL_OPTION; + break; + case IDI_WTP_SEL_NORTH: + iRow = IDI_WTP_ROW_OPTION_4; + iCol = IDI_WTP_COL_NORTH; + break; + case IDI_WTP_SEL_SOUTH: + iRow = IDI_WTP_ROW_OPTION_4; + iCol = IDI_WTP_COL_SOUTH; + break; + case IDI_WTP_SEL_EAST: + iRow = IDI_WTP_ROW_OPTION_4; + iCol = IDI_WTP_COL_EAST; + break; + case IDI_WTP_SEL_WEST: + iRow = IDI_WTP_ROW_OPTION_4; + iCol = IDI_WTP_COL_WEST; + break; + case IDI_WTP_SEL_TAKE: + iRow = IDI_WTP_ROW_OPTION_4; + iCol = IDI_WTP_COL_TAKE; + break; + case IDI_WTP_SEL_DROP: + iRow = IDI_WTP_ROW_OPTION_4; + iCol = IDI_WTP_COL_DROP; + break; + } + _vm->drawStr(iRow, iCol - 1, IDA_DEFAULT, IDS_WTP_SELECTION); + _vm->_gfx->doUpdate(); + _vm->_system->updateScreen(); // TODO: this should go in the game's main loop +} + +void Winnie::incMenuSel(int *iSel, int fCanSel[]) { + do { + *iSel += 1; + if (*iSel > IDI_WTP_SEL_DROP) *iSel = IDI_WTP_SEL_OPT_1; + } while(!fCanSel[*iSel]); +} + +void Winnie::decMenuSel(int *iSel, int fCanSel[]) { + do { + *iSel -= 1; + if (*iSel < IDI_WTP_SEL_OPT_1) *iSel = IDI_WTP_SEL_DROP; + } while(!fCanSel[*iSel]); +} + +void Winnie::getMenuMouseSel(int *iSel, int fCanSel[], int x, int y) { + switch(y) { + case IDI_WTP_ROW_OPTION_1: + if (fCanSel[IDI_WTP_SEL_OPT_1]) *iSel = IDI_WTP_SEL_OPT_1; + break; + case IDI_WTP_ROW_OPTION_2: + if (fCanSel[IDI_WTP_SEL_OPT_2]) *iSel = IDI_WTP_SEL_OPT_2; + break; + case IDI_WTP_ROW_OPTION_3: + if (fCanSel[IDI_WTP_SEL_OPT_3]) *iSel = IDI_WTP_SEL_OPT_3; + break; + case IDI_WTP_ROW_OPTION_4: + if (fCanSel[IDI_WTP_SEL_NORTH] && (x > IDI_WTP_COL_NORTH - 1) && (x < 6)) *iSel = IDI_WTP_SEL_NORTH; + if (fCanSel[IDI_WTP_SEL_SOUTH] && (x > IDI_WTP_COL_SOUTH - 1) && (x < 13)) *iSel = IDI_WTP_SEL_SOUTH; + if (fCanSel[IDI_WTP_SEL_EAST] && (x > IDI_WTP_COL_EAST - 1) && (x < 19)) *iSel = IDI_WTP_SEL_EAST; + if (fCanSel[IDI_WTP_SEL_WEST] && (x > IDI_WTP_COL_WEST - 1) && (x < 25)) *iSel = IDI_WTP_SEL_WEST; + if (fCanSel[IDI_WTP_SEL_TAKE] && (x > IDI_WTP_COL_TAKE - 1) && (x < 33)) *iSel = IDI_WTP_SEL_TAKE; + if (fCanSel[IDI_WTP_SEL_DROP] && (x > IDI_WTP_COL_DROP - 1) && (x < 39)) *iSel = IDI_WTP_SEL_DROP; + break; + } +} + +#define makeSel() {\ + if (fCanSel[*iSel]) {\ + return;\ + } else {\ + keyHelp();\ + clrMenuSel(iSel, fCanSel);\ + }\ +} + +void Winnie::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) { + Common::Event event; + int x, y; + + clrMenuSel(iSel, fCanSel); + drawMenu(szMenu, *iSel, fCanSel); + + // Show the mouse cursor for the menu + CursorMan.showMouse(true); + + for (;;) { + // check if tigger/mist is to be triggered +// if (something) +// event = true; + + while (_vm->_system->getEventManager()->pollEvent(event)) { + switch(event.type) { + case Common::EVENT_QUIT: + _vm->_system->quit(); + break; + case Common::EVENT_MOUSEMOVE: + x = event.mouse.x / 8; + y = event.mouse.y / 8; + getMenuMouseSel(iSel, fCanSel, x, y); + + // Change cursor + if (fCanSel[IDI_WTP_SEL_NORTH] && (event.mouse.x >= 20 && event.mouse.x <= (IDI_WTP_PIC_WIDTH + 10) * 2) && + (event.mouse.y >= 0 && event.mouse.y <= 10)) { + _vm->_gfx->setCursorPalette(true); + } else if (fCanSel[IDI_WTP_SEL_SOUTH] && (event.mouse.x >= 20 && event.mouse.x <= (IDI_WTP_PIC_WIDTH + 10) * 2) && + (event.mouse.y >= IDI_WTP_PIC_HEIGHT - 10 && event.mouse.y <= IDI_WTP_PIC_HEIGHT)) { + _vm->_gfx->setCursorPalette(true); + } else if (fCanSel[IDI_WTP_SEL_WEST] && (event.mouse.y >= 0 && event.mouse.y <= IDI_WTP_PIC_HEIGHT) && + (event.mouse.x >= 20 && event.mouse.x <= 30)) { + _vm->_gfx->setCursorPalette(true); + } else if (fCanSel[IDI_WTP_SEL_EAST] && (event.mouse.y >= 0 && event.mouse.y <= IDI_WTP_PIC_HEIGHT) && + (event.mouse.x >= IDI_WTP_PIC_WIDTH * 2 && event.mouse.x <= (IDI_WTP_PIC_WIDTH + 10) * 2)) { + _vm->_gfx->setCursorPalette(true); + } else { + _vm->_gfx->setCursorPalette(false); + } + + break; + case Common::EVENT_LBUTTONUP: + // Click to move + if (fCanSel[IDI_WTP_SEL_NORTH] && (event.mouse.x >= 20 && event.mouse.x <= (IDI_WTP_PIC_WIDTH + 10) * 2) && + (event.mouse.y >= 0 && event.mouse.y <= 10)) { + *iSel = IDI_WTP_SEL_NORTH; + makeSel(); + _vm->_gfx->setCursorPalette(false); + return; + } else if (fCanSel[IDI_WTP_SEL_SOUTH] && (event.mouse.x >= 20 && event.mouse.x <= (IDI_WTP_PIC_WIDTH + 10) * 2) && + (event.mouse.y >= IDI_WTP_PIC_HEIGHT - 10 && event.mouse.y <= IDI_WTP_PIC_HEIGHT)) { + *iSel = IDI_WTP_SEL_SOUTH; + makeSel(); + _vm->_gfx->setCursorPalette(false); + return; + } else if (fCanSel[IDI_WTP_SEL_WEST] && (event.mouse.y >= 0 && event.mouse.y <= IDI_WTP_PIC_HEIGHT) && + (event.mouse.x >= 20 && event.mouse.x <= 30)) { + *iSel = IDI_WTP_SEL_WEST; + makeSel(); + _vm->_gfx->setCursorPalette(false); + return; + } else if (fCanSel[IDI_WTP_SEL_EAST] && (event.mouse.y >= 0 && event.mouse.y <= IDI_WTP_PIC_HEIGHT) && + (event.mouse.x >= IDI_WTP_PIC_WIDTH * 2 && event.mouse.x <= (IDI_WTP_PIC_WIDTH + 10) * 2)) { + *iSel = IDI_WTP_SEL_EAST; + makeSel(); + _vm->_gfx->setCursorPalette(false); + return; + } else { + _vm->_gfx->setCursorPalette(false); + } + + switch(*iSel) { + case IDI_WTP_SEL_OPT_1: + case IDI_WTP_SEL_OPT_2: + case IDI_WTP_SEL_OPT_3: + for (int iSel2 = 0; iSel2 < IDI_WTP_MAX_OPTION; iSel2++) { + if (*iSel == (fCanSel[iSel2 + IDI_WTP_SEL_REAL_OPT_1] - 1)) { + *iSel = iSel2; + // Menu selection made, hide the mouse cursor + CursorMan.showMouse(false); + return; + } + } + break; + default: + if (fCanSel[*iSel]) { + // Menu selection made, hide the mouse cursor + CursorMan.showMouse(false); + return; + } + break; + } + break; + case Common::EVENT_RBUTTONUP: + *iSel = IDI_WTP_SEL_BACK; + // Menu selection made, hide the mouse cursor + CursorMan.showMouse(false); + return; + case Common::EVENT_WHEELUP: + decMenuSel(iSel, fCanSel); + break; + case Common::EVENT_WHEELDOWN: + incMenuSel(iSel, fCanSel); + break; + case Common::EVENT_KEYDOWN: + switch (event.kbd.keycode) { + case Common::KEYCODE_ESCAPE: + *iSel = IDI_WTP_SEL_HOME; + // Menu selection made, hide the mouse cursor + CursorMan.showMouse(false); + return; + case Common::KEYCODE_BACKSPACE: + *iSel = IDI_WTP_SEL_BACK; + // Menu selection made, hide the mouse cursor + CursorMan.showMouse(false); + return; + case Common::KEYCODE_c: + inventory(); + break; + case Common::KEYCODE_SPACE: + case Common::KEYCODE_RIGHT: + case Common::KEYCODE_DOWN: + incMenuSel(iSel, fCanSel); + break; + case Common::KEYCODE_LEFT: + case Common::KEYCODE_UP: + decMenuSel(iSel, fCanSel); + break; + case Common::KEYCODE_1: + case Common::KEYCODE_2: + case Common::KEYCODE_3: + *iSel = event.kbd.keycode - Common::KEYCODE_1; + if (fCanSel[*iSel + IDI_WTP_SEL_REAL_OPT_1]) { + // Menu selection made, hide the mouse cursor + CursorMan.showMouse(false); + return; + } else { + keyHelp(); + clrMenuSel(iSel, fCanSel); + } + break; + case Common::KEYCODE_n: + *iSel = IDI_WTP_SEL_NORTH; + makeSel(); + break; + case Common::KEYCODE_s: + if (event.kbd.flags & Common::KBD_CTRL) { + //FlipSound(); + } else { + *iSel = IDI_WTP_SEL_SOUTH; + makeSel(); + } + break; + case Common::KEYCODE_e: + *iSel = IDI_WTP_SEL_EAST; + makeSel(); + break; + case Common::KEYCODE_w: + *iSel = IDI_WTP_SEL_WEST; + makeSel(); + break; + case Common::KEYCODE_t: + *iSel = IDI_WTP_SEL_TAKE; + makeSel(); + break; + case Common::KEYCODE_d: + *iSel = IDI_WTP_SEL_DROP; + makeSel(); + break; + case Common::KEYCODE_RETURN: + switch(*iSel) { + case IDI_WTP_SEL_OPT_1: + case IDI_WTP_SEL_OPT_2: + case IDI_WTP_SEL_OPT_3: + for (int iSel2 = 0; iSel2 < IDI_WTP_MAX_OPTION; iSel2++) { + if (*iSel == (fCanSel[iSel2 + IDI_WTP_SEL_REAL_OPT_1] - 1)) { + *iSel = iSel2; + // Menu selection made, hide the mouse cursor + CursorMan.showMouse(false); + return; + } + } + break; + default: + if (fCanSel[*iSel]) { + // Menu selection made, hide the mouse cursor + CursorMan.showMouse(false); + return; + } + break; + } + default: + keyHelp(); + clrMenuSel(iSel, fCanSel); + break; + } + break; + default: + break; + } + + drawMenu(szMenu, *iSel, fCanSel); + } + } +} + +void Winnie::gameLoop() { + WTP_ROOM_HDR hdr; + uint8 *roomdata = new uint8[4096]; + int iBlock; + +phase0: + if (!game.nObjMiss && (room == IDI_WTP_ROOM_PICNIC)) + room = IDI_WTP_ROOM_PARTY; + readRoom(room, roomdata, 4096); + memcpy(&hdr, roomdata, sizeof(WTP_ROOM_HDR)); + drawRoomPic(); +phase1: + if (getObjInRoom(room)) { + printObjStr(getObjInRoom(room), IDI_WTP_OBJ_DESC); + _vm->waitAnyKeyChoice(); + } +phase2: + for (iBlock = 0; iBlock < IDI_WTP_MAX_BLOCK; iBlock++) { + if (parser(hdr.ofsDesc[iBlock] - IDI_WTP_OFS_ROOM, iBlock, roomdata) == IDI_WTP_PAR_BACK) { + goto phase1; + } + } + for (;;) { + for (iBlock = 0; iBlock < IDI_WTP_MAX_BLOCK; iBlock++) { + switch(parser(hdr.ofsBlock[iBlock] - IDI_WTP_OFS_ROOM, iBlock, roomdata)) { + case IDI_WTP_PAR_GOTO: + goto phase0; + break; + case IDI_WTP_PAR_BACK: + goto phase2; + break; + } + } + } + + delete [] roomdata; +} + +void Winnie::drawPic(const char *szName) { + char szFile[256] = {0}; + uint8 *buffer = new uint8[4096]; + + // construct filename + sprintf(szFile, IDS_WTP_PATH, szName); + Common::File file; + if (!file.open(szName)) + return; + uint32 size = file.size(); + file.read(buffer, size); + file.close(); + + _vm->_picture->decodePicture(buffer, size, 1, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT); + _vm->_picture->showPic(IDI_WTP_PIC_X0, IDI_WTP_PIC_Y0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT); + _vm->_gfx->doUpdate(); + _vm->_system->updateScreen(); // TODO: this should go in the game's main loop + + delete [] buffer; +} + +void Winnie::drawObjPic(int iObj, int x0, int y0) { + WTP_OBJ_HDR objhdr; + uint8 *buffer = new uint8[2048]; + + if (!iObj) + return; + + readObj(iObj, buffer, 2048); + memcpy(&objhdr, buffer, sizeof(WTP_OBJ_HDR)); + + _vm->_picture->setOffset(x0, y0); + _vm->_picture->decodePicture(buffer + objhdr.ofsPic - IDI_WTP_OFS_OBJ, 4096, 0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT); + _vm->_picture->setOffset(0, 0); + _vm->_picture->showPic(10, 0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT); + _vm->_gfx->doUpdate(); + _vm->_system->updateScreen(); + + delete [] buffer; +} + +void Winnie::drawRoomPic() { + WTP_ROOM_HDR roomhdr; + uint8 *buffer = new uint8[4096]; + int iObj = getObjInRoom(room); + + // clear gfx screen + _vm->_gfx->clearScreen(0); + _vm->_gfx->doUpdate(); + _vm->_system->updateScreen(); // TODO: this should go in the game's main loop + + // read room picture + readRoom(room, buffer, 4096); + memcpy(&roomhdr, buffer, sizeof(WTP_ROOM_HDR)); + + // draw room picture + _vm->_picture->decodePicture(buffer + roomhdr.ofsPic - IDI_WTP_OFS_ROOM, 4096, 1, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT); + _vm->_picture->showPic(IDI_WTP_PIC_X0, IDI_WTP_PIC_Y0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT); + _vm->_gfx->doUpdate(); + _vm->_system->updateScreen(); // TODO: this should go in the game's main loop + + // draw object picture + drawObjPic(iObj, IDI_WTP_PIC_X0 + roomhdr.objX, IDI_WTP_PIC_Y0 + roomhdr.objY); + + delete [] buffer; +} + +bool Winnie::getSelOkBack() { + Common::Event event; + + for (;;) { + while (_vm->_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_QUIT: + _vm->_system->quit(); + break; + case Common::EVENT_LBUTTONUP: + return true; + case Common::EVENT_RBUTTONUP: + return false; + case Common::EVENT_KEYDOWN: + switch (event.kbd.keycode) { + case Common::KEYCODE_BACKSPACE: + return false; + default: + return true; + } + default: + break; + } + } + } +} +void Winnie::clrMenuSel(int *iSel, int fCanSel[]) { + *iSel = IDI_WTP_SEL_OPT_1; + while(!fCanSel[*iSel]) { + *iSel += 1; + } +} + +void Winnie::printRoomStr(int iRoom, int iStr) { + WTP_ROOM_HDR hdr; + uint8 *buffer = (uint8 *)malloc(4096); + + readRoom(iRoom, buffer, 4096); + memcpy(&hdr, buffer, sizeof(hdr)); + _vm->printStrXOR((char *)(buffer + hdr.ofsStr[iStr - 1] - IDI_WTP_OFS_ROOM)); + + free(buffer); +} + +void Winnie::gameOver() { + // sing the Pooh song forever + for (;;) { + _vm->printStr(IDS_WTP_SONG_0); + //Winnie_PlaySound(IDI_WTP_SND_POOH_0); + _vm->printStr(IDS_WTP_SONG_1); + //Winnie_PlaySound(IDI_WTP_SND_POOH_1); + _vm->printStr(IDS_WTP_SONG_2); + //Winnie_PlaySound(IDI_WTP_SND_POOH_2); + _vm->waitAnyKeyChoice(); + } +} + +void Winnie::saveGame() { + uint8 *buffer = new uint8[sizeof(WTP_SAVE_GAME)]; + memcpy(buffer, &game, sizeof(WTP_SAVE_GAME)); + writeSaveGame(buffer); + delete [] buffer; +} + +void Winnie::loadGame() { + uint8 *buffer = new uint8[sizeof(WTP_SAVE_GAME)]; + readSaveGame(buffer); + memcpy(&game, buffer, sizeof(WTP_SAVE_GAME)); + delete [] buffer; +} + +void Winnie::readSaveGame(uint8 *buffer) { + Common::InSaveFile* infile; + char szFile[256] = {0}; + sprintf(szFile, IDS_WTP_FILE_SAVEGAME); + if (!(infile = _vm->getSaveFileMan()->openForLoading(szFile))) + return; + infile->read(buffer, sizeof(WTP_SAVE_GAME)); + delete infile; +} + +void Winnie::writeSaveGame(uint8 *buffer) { + Common::OutSaveFile* outfile; + char szFile[256] = {0}; + sprintf(szFile, IDS_WTP_FILE_SAVEGAME); + if (!(outfile = _vm->getSaveFileMan()->openForSaving(szFile))) + return; + outfile->write(buffer, sizeof(WTP_SAVE_GAME)); + delete outfile; +} + +Winnie::Winnie(PreAgiEngine* vm) : _vm(vm) { + +} + +void Winnie::init() { + initEngine(); + initVars(); +} + +void Winnie::run() { + randomize(); + intro(); + gameLoop(); +} + +} |