/* 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 3 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, see .
*
*/
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/debug.h"
#include "common/debug-channels.h"
#include "common/error.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/fs.h"
#include "common/system.h"
#include "graphics/surface.h"
#include "graphics/screen.h"
#include "audio/mixer.h"
#include "cryo/defs.h"
#include "cryo/cryo.h"
#include "cryo/platdefs.h"
#include "cryo/cryolib.h"
#include "cryo/eden.h"
#include "cryo/sound.h"
#include "cryo/eden_graphics.h"
namespace Cryo {
#define Z_RESET -3400
#define Z_STEP 200
#define Z_UP 1
#define Z_DOWN -1
EdenGame::EdenGame(CryoEngine *vm) : _vm(vm), kMaxMusicSize(2200000) {
static const uint8 statTab2CB1E[8][4] = {
{ 0x10, 0x81, 1, 0x90},
{ 0x90, 1, 0x81, 0x10},
{ 1, 0x90, 0x10, 0x81},
{ 1, 0x10, 0x90, 0x81},
{ 1, 0x90, 0x10, 0x81},
{ 0x81, 0x10, 0x90, 1},
{ 0x81, 0x10, 0x90, 1},
{ 0x81, 0x90, 1, 0x10}
};
_graphics = nullptr;
_adamMapMarkPos = Common::Point(-1, -1);
_scrollPos = _oldScrollPos = 0;
_frescoTalk = false;
_torchCursor = false;
_curBankNum = 0;
_paletteUpdateRequired = false;
_cursorSaved = false;
_backgroundSaved = false;
_bankData = nullptr;
_tyranPtr = nullptr;
_lastAnimFrameNumb = _curAnimFrameNumb = 0;
_lastAnimTicks = 0;
_numAnimFrames = _maxPersoDesc = _numImgDesc = 0;
_restartAnimation = _animationActive = false;
_animationDelay = _animationIndex = _lastAnimationIndex = 0;
dword_30724 = dword_30728 = _mouthAnimations = _animationTable = nullptr;
_characterBankData = nullptr;
_numTextLines = 0;
_textOutPtr = textout = nullptr;
_curSpecialObject = nullptr;
_lastDialogChoice = false;
parlemoiNormalFlag = false;
_closeCharacterDialog = false;
dword_30B04 = 0;
_lastPhrasesFile = 0;
_dialogSkipFlags = 0;
_voiceSamplesBuffer = nullptr;
_mainBankBuf = nullptr;
_musicBuf = nullptr;
_gameLipsync = nullptr;
_gamePhrases = nullptr;
_gameDialogs = nullptr;
_gameConditions = nullptr;
_placeRawBuf = nullptr;
_bankDataBuf = nullptr;
_gameIcons = nullptr;
_gameRooms = nullptr;
_glowBuffer = nullptr;
_gameFont = nullptr;
_globals = nullptr;
_mouseCenterY = _mouseCenterX = 0;
_bufferAllocationErrorFl = _quitFlag2 = _quitFlag3 = false;
_gameStarted = false;
_soundAllocated = false;
_musicChannel = _voiceChannel = nullptr;
_cirsorPanX = 0;
_inventoryScrollDelay = 0;
_cursorPosY = _cursorPosX = 0;
_currCursor = 0;
_currSpot = _curSpot2 = nullptr;
_mouseHeld = false;
_normalCursor = false;
_specialTextMode = false;
_voiceSamplesSize = 0;
_animateTalking = false;
_personTalking = false;
_musicFadeFlag = 0;
_musicPlayingFlag = false;
_musicSamplesPtr = _musicPatternsPtr = _musSequencePtr = nullptr;
_musicEnabledFlag = false;
_currentObjectLocation = nullptr;
byte_31D64 = false;
_noPalette = false;
_gameLoaded = false;
memset(_tapes, 0, sizeof(_tapes));
_confirmMode = 0;
_curSliderValuePtr = nullptr;
_lastMenuItemIdLo = 0;
_lastTapeRoomNum = 0;
_curSliderX = _curSliderY = 0;
_destinationRoom = 0;
word_31E7A = 0;
word_378CC = 0; //TODO: set by CLComputer_Init to 0
word_378CE = 0;
_rotationAngleY = _rotationAngleX = _rotationAngleZ = 0;
_translationY = _translationX = 0.0; //TODO: never changed, make consts?
_cursorOldTick = 0;
_invIconsBase = 19;
// invIconsCount = (_vm->getPlatform() == Common::kPlatformMacintosh) ? 9 : 11;
_invIconsCount = 11;
_roomIconsBase = _invIconsBase + _invIconsCount;
_codePtr = nullptr;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 4; j++)
tab_2CB1E[i][j] = statTab2CB1E[i][j];
}
_translationZ = Z_RESET;
_zDirection = Z_UP;
_torchTick = 0;
_glowIndex = 0;
_torchCurIndex = 0;
_cursCenter = 11;
for (int i = 0; i < 42; ++i)
_objects[i].clear();
for (int i = 0; i < 58; ++i)
_persons[i].clear();
for (int i = 0; i < 7; ++i)
_citadelList[i].clear();
for (int i = 0; i < 12; ++i)
_areasTable[i].clear();
}
EdenGame::~EdenGame() {
}
void EdenGame::removeConsole() {
}
void EdenGame::scroll() {
restoreFriezes();
_graphics->getMainView()->_normal._srcLeft = _scrollPos;
_graphics->getMainView()->_zoom._srcLeft = _scrollPos;
}
void EdenGame::resetScroll() {
_oldScrollPos = _scrollPos;
_scrollPos = 0;
restoreFriezes(); //TODO: inlined scroll() ?
_graphics->getMainView()->_normal._srcLeft = 0;
_graphics->getMainView()->_zoom._srcLeft = 0;
}
void EdenGame::scrollFrescoes() {
if (_cursorPosY > 16 && _cursorPosY < 176) {
if (_cursorPosX >= 0 && _cursorPosX < 32 && _scrollPos > 3)
_scrollPos -= 4;
else if (_cursorPosX > 288 && _cursorPosX < 320 && _scrollPos < _globals->_frescoeWidth)
_scrollPos += 4;
}
scroll();
}
bool EdenGame::animationIsActive() {
return _animationActive;
}
// Original name: afffresques
void EdenGame::displayFrescoes() {
useBank(_globals->_frescoeImgBank);
_graphics->drawSprite(0, 0, 16);
useBank(_globals->_frescoeImgBank + 1);
_graphics->drawSprite(0, 320, 16);
_paletteUpdateRequired = true;
}
void EdenGame::gametofresques() {
_frescoTalk = false;
_graphics->rundcurs();
saveFriezes();
displayFrescoes();
_globals->_displayFlags = DisplayFlags::dfFrescoes;
}
// Original name: dofresques
void EdenGame::doFrescoes() {
_cursorSaved = false;
_torchCursor = true;
_graphics->setGlowX(-1);
_graphics->setGlowY(-1);
_globals->_gameFlags |= GameFlags::gfFlag20;
_globals->_varD4 = 0;
_globals->_curObjectId = 0;
_globals->_iconsIndex = 13;
_globals->_autoDialog = false;
gametofresques();
_globals->_frescoNumber = 3;
}
// Original name: finfresques
void EdenGame::actionEndFrescoes() {
_torchCursor = false;
_cursorSaved = true;
_globals->_displayFlags = DisplayFlags::dfFlag1;
resetScroll();
_globals->_var100 = 0xFF;
updateRoom(_globals->_roomNum);
if (_globals->_phaseNum == 114)
_globals->_narratorSequence = 1;
_globals->_eventType = EventType::etEvent8;
showEvents();
}
void EdenGame::scrollMirror() {
if (_cursorPosY > 16 && _cursorPosY < 165) {
if (_cursorPosX >= 0 && _cursorPosX < 16) {
if (_scrollPos > 3) {
_scrollPos--;
scroll();
}
} else if (_cursorPosX > 290 && _cursorPosX < 320) {
if (_scrollPos < 320) {
_scrollPos++;
scroll();
}
}
}
}
// Original name: scrollpano
void EdenGame::scrollPanel() {
if (_cursorPosY > 16 && _cursorPosY < 165) {
if (_cursorPosX >= 0 && _cursorPosX < 16 && _scrollPos > 3)
_scrollPos--;
else if (_cursorPosX > 290 && _cursorPosX < 320 && _scrollPos < 320)
_scrollPos++;
}
scroll();
}
// Original name: affsuiveur
void EdenGame::displayFollower(Follower *follower, int16 x, int16 y) {
useBank(follower->_spriteBank);
_graphics->drawSprite(follower->_spriteNum, x, y + 16);
}
// Original name: persoinmiroir
void EdenGame::characterInMirror() {
Icon *icon1 = &_gameIcons[3];
Icon *icon = &_gameIcons[_roomIconsBase];
Follower *suiveur = _followerList;
int16 num = 1;
for (int i = 0; i < 16; i++) {
if (_globals->_party & (1 << i))
num++;
}
icon += num;
icon->sx = -1;
icon--;
icon->sx = icon1->sx;
icon->sy = icon1->sy;
icon->ex = icon1->ex;
icon->ey = 170;
icon->_cursorId = icon1->_cursorId;
icon->_actionId = icon1->_actionId;
icon->_objectId = icon1->_objectId;
icon--;
displayFollower(suiveur, suiveur->sx, suiveur->sy);
for (; suiveur->_id != -1; suiveur++) {
perso_t *perso;
for (perso = _persons; perso != &_persons[PER_UNKN_156]; perso++) {
if (perso->_id != suiveur->_id)
continue;
if (perso->_flags & PersonFlags::pf80)
continue;
if ((perso->_flags & PersonFlags::pfInParty) == 0)
continue;
if (perso->_roomNum != _globals->_roomNum)
continue;
icon->sx = suiveur->sx;
icon->sy = suiveur->sy;
icon->ex = suiveur->ex;
icon->ey = suiveur->ey;
icon->_cursorId = 8;
icon->_actionId = perso->_actionId;
icon--;
displayFollower(suiveur, suiveur->sx, suiveur->sy);
break;
}
}
}
// Original name: gametomiroir
void EdenGame::gameToMirror(byte arg1) {
if (_globals->_displayFlags != DisplayFlags::dfFlag2) {
_graphics->rundcurs();
restoreFriezes();
drawTopScreen();
showObjects();
saveFriezes();
}
int16 bank = _globals->_roomBackgroundBankNum;
uint16 resNum = bank + 326;
if ((_vm->getPlatform() == Common::kPlatformMacintosh) && (bank == 76 || bank == 128))
resNum = 2487; // PCIMG.HSQ
useBank(resNum);
_graphics->drawSprite(0, 0, 16);
useBank(resNum + 1);
_graphics->drawSprite(0, 320, 16);
characterInMirror();
_paletteUpdateRequired = true;
_globals->_iconsIndex = 16;
_globals->_autoDialog = false;
_globals->_displayFlags = DisplayFlags::dfMirror;
_globals->_mirrorEffect = arg1;
}
void EdenGame::flipMode() {
if (_personTalking) {
endCharacterSpeech();
if (_globals->_displayFlags == DisplayFlags::dfPerson) {
if (_globals->_characterPtr == &_persons[PER_TAU] && _globals->_phaseNum >= 80)
_graphics->displaySubtitles();
else {
getDataSync();
loadCurrCharacter();
addanim();
_restartAnimation = true;
animCharacter();
}
} else
_graphics->displaySubtitles();
persovox();
} else {
if (_globals->_displayFlags != DisplayFlags::dfFrescoes && _globals->_displayFlags != DisplayFlags::dfFlag2) {
closeRoom();
if (_globals->_displayFlags & DisplayFlags::dfFlag1)
gameToMirror(1);
else {
quitMirror();
updateRoom(_globals->_roomNum);
if (byte_31D64) {
dialautoon();
parle_moi();
byte_31D64 = false;
}
}
}
}
}
// Original name: quitmiroir
void EdenGame::quitMirror() {
_graphics->rundcurs();
display();
resetScroll();
saveFriezes();
_globals->_displayFlags = DisplayFlags::dfFlag1;
_globals->_var100 = 0xFF;
_globals->_eventType = EventType::etEventC;
_globals->_mirrorEffect = 1;
}
void EdenGame::clictimbre() {
flipMode();
}
// Original name: clicplanval
void EdenGame::actionClickValleyPlan() {
if ((_globals->_partyOutside & PersonMask::pmDina) && _globals->_phaseNum == 371) {
quitMirror();
updateRoom(_globals->_roomNum);
return;
}
if (_globals->_roomNum == 8 || _globals->_roomNum < 16)
return;
_graphics->rundcurs();
display();
if (_globals->_displayFlags == DisplayFlags::dfMirror)
quitMirror();
deplaval((_globals->_roomNum & 0xFF00) | 1); //TODO: check me
}
// Original name: gotolieu
void EdenGame::gotoPlace(Goto *go) {
_globals->_valleyVidNum = go->_arriveVideoNum;
_globals->_travelTime = go->_travelTime * 256;
_globals->_stepsToFindAppleFast = 0;
_globals->_eventType = EventType::etEvent2;
setChoiceYes();
showEvents();
if (!isAnswerYes())
return;
if (_globals->_var113) {
waitEndSpeak();
if (!_vm->shouldQuit())
closeCharacterScreen();
}
if (go->_enterVideoNum) {
_graphics->hideBars();
_graphics->playHNM(go->_enterVideoNum);
_graphics->setFade(true);
}
initPlace(_globals->_newRoomNum);
specialoutside();
faire_suivre(_globals->_newRoomNum);
closeRoom();
_adamMapMarkPos.x = -1;
_adamMapMarkPos.y = -1;
addTime(_globals->_travelTime);
_globals->_var100 = _globals->_roomPtr->_id;
_globals->_roomNum = _globals->_newRoomNum;
_globals->_areaNum = _globals->_roomNum >> 8;
_globals->_eventType = EventType::etEvent5;
_globals->_newMusicType = MusicType::mt2;
setCharacterHere();
musique();
updateRoom1(_globals->_roomNum);
drawTopScreen();
_adamMapMarkPos.x = -1;
_adamMapMarkPos.y = -1;
}
void EdenGame::deplaval(uint16 roomNum) {
_globals->_newLocation = roomNum & 0xFF;
_globals->_valleyVidNum = 0;
_globals->_phaseActionsCount++;
closeRoom();
endCharacterSpeech();
byte c1 = roomNum & 0xFF;
if (c1 == 0)
return;
if (c1 < 0x80) {
_globals->_displayFlags = DisplayFlags::dfFlag1;
setChoiceYes();
_globals->_eventType = EventType::etEvent1;
showEvents();
if (!isAnswerYes())
return;
if (_globals->_var113) {
waitEndSpeak();
if (!_vm->shouldQuit())
closeCharacterScreen();
}
specialout();
if (_globals->_areaPtr->_type == AreaType::atValley) {
addTime(32);
_globals->_stepsToFindAppleFast++;
_globals->_stepsToFindAppleNormal++;
}
faire_suivre((roomNum & 0xFF00) | _globals->_newLocation);
_globals->_var100 = _globals->_roomPtr->_id;
_globals->_roomNum = roomNum;
_globals->_areaNum = roomNum >> 8;
_globals->_eventType = EventType::etEvent5;
setCharacterHere();
_globals->_newMusicType = MusicType::mtNormal;
musique();
updateRoom1(roomNum);
_globals->_chronoFlag = 0;
_globals->_chrono = 0;
_globals->_var54 = 0;
if (_globals->_roomCharacterType == PersonFlags::pftTyrann)
setChrono(3000);
return;
}
if (c1 == 0xFF) {
_globals->_eventType = EventType::etEventE;
showEvents();
if (!_persons[PER_ELOI]._roomNum && checkEloiReturn())
setChrono(800);
return;
}
_globals->_stepsToFindAppleFast = 0;
byte newAreaNum = c1 & 0x7F;
byte curAreaNum = _globals->_roomNum >> 8;
int16 newRoomNum = newAreaNum << 8;
if (curAreaNum == Areas::arTausCave && newAreaNum == Areas::arMo)
newRoomNum |= 0x16;
else if (curAreaNum == Areas::arMoorkusLair)
newRoomNum |= 4;
else
newRoomNum |= 1;
_globals->_newRoomNum = newRoomNum;
if (newAreaNum == Areas::arTausCave)
gotoPlace(&_gotos[0]);
else {
for (Goto *go = _gotos + 1; go->_curAreaNum != 0xFF; go++) {
if (go->_curAreaNum == curAreaNum) {
gotoPlace(go);
break;
}
}
}
}
// Original name: deplacement
void EdenGame::move(Direction dir) {
Room *room = _globals->_roomPtr;
int16 roomNum = _globals->_roomNum;
debug("move: from room %4X", roomNum);
char newLoc = 0;
_graphics->rundcurs();
display();
_globals->_prevLocation = roomNum & 0xFF;
switch (dir) {
case kCryoNorth:
newLoc = room->_exits[0];
break;
case kCryoEast:
newLoc = room->_exits[1];
break;
case kCryoSouth:
newLoc = room->_exits[2];
break;
case kCryoWest:
newLoc = room->_exits[3];
break;
default:
break;
}
deplaval((roomNum & 0xFF00) | newLoc);
}
// Original name: deplacement2
void EdenGame::move2(Direction dir) {
Room *room = _globals->_roomPtr;
int16 roomNum = _globals->_roomNum;
char newLoc = 0;
_globals->_prevLocation = roomNum & 0xFF;
switch (dir) {
case kCryoNorth:
newLoc = room->_exits[0];
break;
case kCryoEast:
newLoc = room->_exits[1];
break;
case kCryoSouth:
newLoc = room->_exits[2];
break;
case kCryoWest:
newLoc = room->_exits[3];
break;
default:
break;
}
deplaval((roomNum & 0xFF00) | newLoc);
}
// Original name: dinosoufle
void EdenGame::actionDinoBlow() {
if (_globals->_curObjectId == 0) {
_graphics->hideBars();
_graphics->playHNM(148);
maj2();
}
}
// Original name: plaquemonk
void EdenGame::actionPlateMonk() {
if (_globals->_curObjectId != 0) {
if (_globals->_curObjectId == Objects::obPrism) {
loseObject(Objects::obPrism);
_graphics->hideBars();
_specialTextMode = true;
_graphics->playHNM(89);
// CHECKME: Unused code
// word_2F514 |= 0x8000;
maj2();
_globals->_eventType = EventType::etEventB;
showEvents();
}
} else {
_graphics->hideBars();
_graphics->playHNM(7);
maj2();
_globals->_eventType = EventType::etEvent4;
showEvents();
}
}
// Original name: fresquesgraa
void EdenGame::actionGraaFrescoe() {
if (_globals->_curObjectId == 0) {
_globals->_frescoeWidth = 320;
_globals->_frescoeImgBank = 113;
doFrescoes();
handleDinaDialog();
}
}
// Original name: fresqueslasc
void EdenGame::actionLascFrescoe() {
if (_globals->_curObjectId == 0) {
_globals->_frescoeWidth = 112;
_globals->_frescoeImgBank = 315;
doFrescoes();
}
}
// Original name: pushpierre
void EdenGame::actionPushStone() {
if (_globals->_curObjectId == 0) {
_gameRooms[22]._exits[0] = 17;
_gameRooms[26]._exits[2] = 9;
move(kCryoNorth);
}
}
// Original name: tetemomie
void EdenGame::actionMummyHead() {
if (_globals->_curObjectId == Objects::obTooth) {
_globals->_gameFlags |= GameFlags::gfMummyOpened;
move(kCryoNorth);
} else if (_globals->_curObjectId == 0) {
if (_globals->_gameFlags & GameFlags::gfMummyOpened)
move(kCryoNorth);
else {
_globals->_eventType = EventType::etEvent6;
handleCharacterDialog(PersonId::pidMonk);
_globals->_eventType = 0;
}
}
}
// Original name: tetesquel
void EdenGame::actionSkelettonHead() {
if (_globals->_curObjectId == Objects::obTooth) {
_gameRooms[22]._exits[0] = 16;
_gameRooms[26]._exits[2] = 13;
_gameIcons[16]._cursorId |= 0x8000;
loseObject(Objects::obTooth);
move(kCryoNorth);
}
}
// Original name: squelmoorkong
void EdenGame::actionSkelettonMoorkong() {
_globals->_eventType = EventType::etEvent9;
showEvents();
}
// Original name: choisir
void EdenGame::actionChoose() {
byte objid = _curSpot2->_objectId;
byte obj;
switch (objid) {
case 0:
obj = _globals->_giveObj1;
break;
case 1:
obj = _globals->_giveObj2;
break;
case 2:
obj = _globals->_giveObj3;
break;
default:
warning("Unexpected objid in actionChoose()");
return;
}
objectmain(obj);
winObject(obj);
_globals->_iconsIndex = 16;
_globals->_autoDialog = false;
_globals->_var60 = 0;
parle_moi();
}
// Original name: dinaparle
void EdenGame::handleDinaDialog() {
perso_t *perso = &_persons[PER_DINA];
if (perso->_partyMask & (_globals->_party | _globals->_partyOutside)) {
if (_globals->_frescoNumber < 3)
_globals->_frescoNumber = 3;
_globals->_frescoNumber++;
if (_globals->_frescoNumber < 15) {
endCharacterSpeech();
if (_globals->_frescoNumber == 7 && _globals->_phaseNum == 113)
incPhase();
_globals->_characterPtr = perso;
_globals->_dialogType = DialogType::dtInspect;
int16 num = (perso->_id << 3) | DialogType::dtInspect; //TODO: combine
bool res = dialoscansvmas((Dialog *)getElem(_gameDialogs, num));
_frescoTalk = false;
if (res) {
_graphics->restoreUnderSubtitles();
_frescoTalk = true;
persovox();
}
_globals->_varCA = 0;
_globals->_dialogType = DialogType::dtTalk;
} else
actionEndFrescoes();
}
}
int16 EdenGame::getCurPosX() {
return _cursorPosX;
}
int16 EdenGame::getCurPosY() {
return _cursorPosY;
}
void EdenGame::setCurPosX(int16 xpos) {
_cursorPosX = xpos;
}
void EdenGame::setCurPosY(int16 ypos) {
_cursorPosY = ypos;
}
// Original name: roiparle
void EdenGame::handleKingDialog() {
if (_globals->_phaseNum <= 400)
handleCharacterDialog(0);
}
// Original name: roiparle1
void EdenGame::actionKingDialog1() {
if (_globals->_curObjectId == Objects::obSword) {
_globals->_gameFlags |= GameFlags::gfFlag80;
_graphics->hideBars();
_graphics->playHNM(76);
move2(kCryoNorth);
} else {
_globals->_frescoNumber = 1;
handleKingDialog();
}
}
// Original name: roiparle2
void EdenGame::actionKingDialog2() {
_globals->_frescoNumber = 2;
handleKingDialog();
}
// Original name: roiparle3
void EdenGame::actionKingDialog3() {
_globals->_frescoNumber = 3;
handleKingDialog();
}
// Original name: getcouteau
void EdenGame::actionGetKnife() {
if (_globals->_phaseNum >= 80) {
_gameRooms[113]._video = 0;
getObject(Objects::obKnife);
}
_globals->_eventType = EventType::etEvent7;
showEvents();
}
// Original name: getprisme
void EdenGame::actionGetPrism() {
getObject(Objects::obPrism);
_globals->_eventType = EventType::etEvent7;
showEvents();
}
// Original name: getchampb
void EdenGame::actionGetMushroom() {
getObject(Objects::obShroom);
}
// Original name: getchampm
void EdenGame::actionGetBadMushroom() {
getObject(Objects::obBadShroom);
}
// Original name: getor
void EdenGame::actionGetGold() {
getObject(Objects::obGold);
}
// Original name: getnido
void EdenGame::actionGetFullNest() {
if (_globals->_curObjectId != 0)
return;
_globals->_roomPtr->_bank = 282; //TODO: fix me
_globals->_roomPtr--;
_globals->_roomPtr->_bank = 281; //TODO: fix me
_globals->_roomPtr->_id = 3;
getObject(Objects::obFullNest);
}
// Original name: getnidv
void EdenGame::actionGetEmptyNest() {
if (_globals->_curObjectId != 0)
return;
_globals->_roomPtr->_bank = 282; //TODO: fix me
_globals->_roomPtr--;
_globals->_roomPtr->_bank = 281; //TODO: fix me
_globals->_roomPtr->_id = 3;
getObject(Objects::obNest);
}
// Original name: getcorne
void EdenGame::actionGetHorn() {
if (_globals->_curObjectId != 0)
return;
getObject(Objects::obHorn);
_globals->_eventType = EventType::etEvent7;
showEvents();
bigphase1();
setCharacterHere();
_globals->_roomPtr = getRoom(_globals->_roomNum);
}
// Original name: getsoleil
void EdenGame::actionGetSunStone() {
if (_globals->_curObjectId != 0)
return;
_gameRooms[238]._video = 0;
_gameRooms[238]._flags = RoomFlags::rf80;
getObject(Objects::obSunStone);
}
// Original name: getoueuf
void EdenGame::actionGetEgg() {
if (_globals->_curObjectId != 0)
return;
_globals->_roomPtr->_flags = 0;
_globals->_roomPtr->_video = 0;
getObject(Objects::obEgg);
}
// Original name: getplaque
void EdenGame::actionGetTablet() {
if (_globals->_curObjectId != 0 && _globals->_curObjectId < Objects::obTablet1)
return;
_globals->_curObjectId = 0;
getObject(Objects::obTablet2);
putObject();
for (int i = 0; i < 6; i++)
_objects[Objects::obTablet1 - 1 + i]._count = 0;
_globals->_curObjectFlags = 0;
_globals->_inventoryScrollPos = 0;
_globals->_curObjectCursor = 9;
_gameIcons[16]._cursorId |= 0x8000;
showObjects();
_gameRooms[131]._video = 0;
_graphics->hideBars();
_graphics->playHNM(149);
_globals->_varF1 = RoomFlags::rf04;
_globals->_drawFlags = DrawFlags::drDrawFlag20;
_normalCursor = true;
maj2();
}
// Original name: voirlac
void EdenGame::actionLookLake() {
perso_t *perso = &_persons[PER_MORKUS];
Room *room = _globals->_roomPtr;
Area *area = _globals->_areaPtr;
int16 vid = _globals->_curObjectId == Objects::obApple ? 81 : 54;
for (++perso; perso->_roomNum != 0xFFFF; perso++) {
if (perso->_roomNum != _globals->_roomNum)
continue;
vid++;
if (_globals->_curObjectId != Objects::obApple)
continue; //TODO: pc breaks here
if ((perso->_flags & PersonFlags::pfTypeMask) != PersonFlags::pftMosasaurus)
continue;
if (!(perso->_flags & PersonFlags::pf80))
return;
perso->_flags &= ~PersonFlags::pf80; //TODO: useless? see above
area->_flags |= AreaFlags::afFlag8;
_globals->_curAreaFlags |= AreaFlags::afFlag8;
room->_id = 3;
}
debug("sea monster: room = %X, d0 = %X\n", _globals->_roomNum, _globals->_roomImgBank);
_graphics->hideBars();
_graphics->playHNM(vid);
updateRoom(_globals->_roomNum); //TODO: getting memory trashed here?
if (_globals->_curObjectId == Objects::obApple)
loseObject(Objects::obApple);
_globals->_eventType = EventType::etEventF;
showEvents();
}
// Original name: gotohall
void EdenGame::actionGotoHall() {
_globals->_prevLocation = _globals->_roomNum & 0xFF;
deplaval((_globals->_roomNum & 0xFF00) | 6);
}
// Original name: demitourlabi
void EdenGame::actionLabyrinthTurnAround() {
_globals->_prevLocation = _globals->_roomNum & 0xFF;
_globals->_var100 = 0xFF;
uint16 target = (_globals->_roomNum & 0xFF00) | _globals->_roomPtr->_exits[2];
faire_suivre(target);
_globals->_roomNum = target;
_globals->_eventType = EventType::etEvent5;
updateRoom(_globals->_roomNum);
}
// Original name: gotonido
void EdenGame::actionGotoFullNest() {
_globals->_roomPtr++;
_globals->_eventType = 0;
_globals->_roomImgBank = _globals->_roomPtr->_bank;
_globals->_roomVidNum = _globals->_roomPtr->_video;
_globals->_curRoomFlags = _globals->_roomPtr->_flags;
_globals->_varF1 = _globals->_roomPtr->_flags;
animpiece();
_globals->_var100 = 0;
maj2();
}
// Original name: gotoval
void EdenGame::actionGotoVal() {
uint16 target = _globals->_roomNum;
_graphics->rundcurs();
display();
_scrollPos = 0;
char obj = _curSpot2->_objectId - 14; //TODO
_globals->_prevLocation = target & 0xFF;
deplaval((target & 0xFF00) | obj);
}
// Original name: visiter
void EdenGame::actionVisit() {
_graphics->hideBars();
_graphics->playHNM(144);
_globals->_varF1 = RoomFlags::rf04;
maj2();
}
// Original name: final
void EdenGame::actionFinal() {
if (_globals->_curObjectId != 0)
return;
_graphics->hideBars();
*(int16 *)(_gameRooms + 0x6DC) = 319; //TODO
_globals->_roomImgBank = 319;
_graphics->playHNM(97);
maj2();
_globals->_eventType = EventType::etEvent12;
showEvents();
_globals->_narratorSequence = 54;
}
// Original name: goto_nord
void EdenGame::actionMoveNorth() {
if (_globals->_curObjectId == 0)
move(kCryoNorth);
}
// Original name: goto_est
void EdenGame::actionMoveEast() {
if (_globals->_curObjectId == 0)
move(kCryoEast);
}
// Original name: goto_sud
void EdenGame::actionMoveSouth() {
if (_globals->_curObjectId == 0)
move(kCryoSouth);
}
// Original name: goto_ouest
void EdenGame::actionMoveWest() {
if (_globals->_curObjectId == 0)
move(kCryoWest);
}
// Original name: afficher
void EdenGame::display() {
if (!_globals->_mirrorEffect && !_globals->_var103) {
if (_paletteUpdateRequired) {
_paletteUpdateRequired = false;
_graphics->SendPalette2Screen(256);
}
CLBlitter_CopyView2Screen(_graphics->getMainView());
} else {
if (_globals->_mirrorEffect)
_graphics->displayEffect3();
else
_graphics->displayEffect2();
_globals->_var103 = 0;
_globals->_mirrorEffect = 0;
}
}
void EdenGame::afficher128() {
if (_globals->_updatePaletteFlag == 16) {
_graphics->SendPalette2Screen(129);
CLBlitter_CopyView2Screen(_graphics->getMainView());
_globals->_updatePaletteFlag = 0;
} else {
_graphics->clearScreen();
_graphics->fadeToBlackLowPalette(1);
if (_graphics->getShowBlackBars())
_graphics->drawBlackBars();
CLBlitter_CopyView2Screen(_graphics->getMainView());
_graphics->fadeFromBlackLowPalette(1);
}
}
// Original name: sauvefrises
void EdenGame::saveFriezes() {
_graphics->saveTopFrieze(0);
_graphics->saveBottomFrieze();
}
// Original name: restaurefrises
void EdenGame::restoreFriezes() {
_graphics->restoreTopFrieze();
_graphics->restoreBottomFrieze();
}
byte * EdenGame::getBankData() {
return _bankData;
}
void EdenGame::useMainBank() {
_bankData = _mainBankBuf;
}
void EdenGame::useCharacterBank() {
_bankData = _characterBankData;
}
// Original name: use_bank
void EdenGame::useBank(int16 bank) {
if (bank > 2500)
error("attempt to load bad bank %d", bank);
_bankData = _bankDataBuf;
if (_curBankNum != bank) {
loadRawFile(bank, _bankDataBuf);
verifh(_bankDataBuf);
_curBankNum = bank;
}
}
void EdenGame::drawTopScreen() { // Draw top bar (location / party / map)
_globals->_drawFlags &= ~DrawFlags::drDrawTopScreen;
useBank(314);
_graphics->drawSprite(36, 83, 0);
_graphics->drawSprite(_globals->_areaPtr->_num - 1, 0, 0);
_graphics->drawSprite(23, 145, 0);
for (perso_t *perso = &_persons[PER_DINA]; perso != &_persons[PER_UNKN_156]; perso++) {
if ((perso->_flags & PersonFlags::pfInParty) && !(perso->_flags & PersonFlags::pf80))
_graphics->drawSprite(perso->_targetLoc + 18, perso->_lastLoc + 120, 0);
}
_adamMapMarkPos.x = -1;
_adamMapMarkPos.y = -1;
displayValleyMap();
_paletteUpdateRequired = true;
}
// Original name: affplanval
void EdenGame::displayValleyMap() { // Draw mini-map
if (_globals->_areaPtr->_type == AreaType::atValley) {
_graphics->drawSprite(_globals->_areaPtr->_num + 9, 266, 1);
for (perso_t *perso = &_persons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) {
if (((perso->_roomNum >> 8) == _globals->_areaNum)
&& !(perso->_flags & PersonFlags::pf80) && (perso->_flags & PersonFlags::pf20))
displayMapMark(33, perso->_roomNum & 0xFF);
}
if (_globals->_areaPtr->_citadelLevel)
displayMapMark(34, _globals->_areaPtr->_citadelRoomPtr->_location);
_graphics->saveTopFrieze(0);
int16 loc = _globals->_roomNum & 0xFF;
if (loc >= 16)
displayAdamMapMark(loc);
_graphics->restoreTopFrieze();
} else {
_graphics->saveTopFrieze(0);
_graphics->restoreTopFrieze();
}
}
// Original name: affrepere
void EdenGame::displayMapMark(int16 index, int16 location) {
_graphics->drawSprite(index, 269 + location % 16 * 4, 2 + (location - 16) / 16 * 3);
}
// Original name: affrepereadam
void EdenGame::displayAdamMapMark(int16 location) {
int16 x = 269;
int16 y = 2;
restoreAdamMapMark();
if (location > 15 && location < 76) {
x += (location & 15) * 4;
y += ((location - 16) >> 4) * 3;
saveAdamMapMark(x, y);
byte *pix = _graphics->getUnderBarsView()->_bufferPtr;
int16 w = _graphics->getUnderBarsView()->_width;
pix += x + w * y;
pix[1] = 0xC3;
pix[2] = 0xC3;
pix += w;
pix[0] = 0xC3;
pix[1] = 0xC3;
pix[2] = 0xC3;
pix[3] = 0xC3;
pix += w;
pix[1] = 0xC3;
pix[2] = 0xC3;
}
}
// Original name: rest_repadam
void EdenGame::restoreAdamMapMark() {
if (_adamMapMarkPos.x == -1 && _adamMapMarkPos.y == -1)
return;
int16 x = _adamMapMarkPos.x;
int16 y = _adamMapMarkPos.y;
byte *pix = _graphics->getUnderBarsView()->_bufferPtr;
int16 w = _graphics->getUnderBarsView()->_width;
pix += x + w * y;
pix[1] = _oldPix[0];
pix[2] = _oldPix[1];
pix += w;
pix[0] = _oldPix[2];
pix[1] = _oldPix[3];
pix[2] = _oldPix[4];
pix[3] = _oldPix[5];
pix += w;
pix[1] = _oldPix[6];
pix[2] = _oldPix[7];
}
// Original name: save_repadam
void EdenGame::saveAdamMapMark(int16 x, int16 y) {
_adamMapMarkPos.x = x;
_adamMapMarkPos.y = y;
byte *pix = _graphics->getUnderBarsView()->_bufferPtr;
int16 w = _graphics->getUnderBarsView()->_width;
pix += x + w * y;
_oldPix[0] = pix[1];
_oldPix[1] = pix[2];
pix += w;
_oldPix[2] = pix[0];
_oldPix[3] = pix[1];
_oldPix[4] = pix[2];
_oldPix[5] = pix[3];
pix += w;
_oldPix[6] = pix[1];
_oldPix[7] = pix[2];
}
bool EdenGame::istrice(int16 roomNum) {
char loc = roomNum & 0xFF;
int16 area = roomNum & 0xFF00;
for (perso_t *perso = &_persons[PER_UNKN_18C]; perso != &_persons[PER_UNKN_372]; perso++) {
if ((perso->_flags & PersonFlags::pf80) || (perso->_flags & PersonFlags::pfTypeMask) != PersonFlags::pftTriceraptor)
continue;
if (perso->_roomNum == (area | (loc - 16)))
return true;
if (perso->_roomNum == (area | (loc + 16)))
return true;
if (perso->_roomNum == (area | (loc - 1)))
return true;
if (perso->_roomNum == (area | (loc + 1)))
return true;
}
return false;
}
bool EdenGame::istyran(int16 roomNum) {
char loc = roomNum & 0xFF;
int16 area = roomNum & 0xFF00;
// TODO: orig bug: this ptr is not initialized when first called from getsalle
// PC version scans _persons[] directly and is not affected
if (!_tyranPtr)
return false;
for (; _tyranPtr->_roomNum != 0xFFFF; _tyranPtr++) {
if (_tyranPtr->_flags & PersonFlags::pf80)
continue;
if (_tyranPtr->_roomNum == (area | (loc - 16)))
return true;
if (_tyranPtr->_roomNum == (area | (loc + 16)))
return true;
if (_tyranPtr->_roomNum == (area | (loc - 1)))
return true;
if (_tyranPtr->_roomNum == (area | (loc + 1)))
return true;
}
return false;
}
void EdenGame::istyranval(Area *area) {
byte areaNum = area->_num;
area->_flags &= ~AreaFlags::HasTyrann;
for (perso_t *perso = &_persons[PER_UNKN_372]; perso->_roomNum != 0xFFFF; perso++) {
if (perso->_flags & PersonFlags::pf80)
continue;
if ((perso->_roomNum >> 8) == areaNum) {
area->_flags |= AreaFlags::HasTyrann;
break;
}
}
}
char EdenGame::getDirection(perso_t *perso) {
char dir = -1;
byte trgLoc = perso->_targetLoc;
byte curLoc = perso->_roomNum & 0xFF; //TODO name
if (curLoc != trgLoc) {
curLoc &= 0xF;
trgLoc &= 0xF;
if (curLoc != trgLoc) {
dir = 2;
if (curLoc > trgLoc)
dir = 5;
}
trgLoc = perso->_targetLoc;
curLoc = perso->_roomNum & 0xFF;
curLoc &= 0xF0;
trgLoc &= 0xF0;
if (curLoc != trgLoc) {
if (curLoc > trgLoc)
dir++;
dir++;
}
}
return dir;
}
// Original name: caselibre
bool EdenGame::canMoveThere(char loc, perso_t *perso) {
Room *room = _globals->_citaAreaFirstRoom;
if (loc <= 0x10 || loc > 76 || (loc & 0xF) >= 12 || loc == perso->_lastLoc)
return false;
int16 roomNum = (perso->_roomNum & ~0xFF) | loc; //TODO: danger! signed
if (roomNum == _globals->_roomNum)
return false;
for (; room->_id != 0xFF; room++) {
if (room->_location != loc)
continue;
if (!(room->_flags & RoomFlags::rf01))
return false;
for (perso = &_persons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) {
if (perso->_flags & PersonFlags::pf80)
continue;
if (perso->_roomNum == roomNum)
break;
}
if (perso->_roomNum != 0xFFFF)
return false;
return true;
}
return false;
}
// Original name: melange1
void EdenGame::scramble1(uint8 elem[4]) {
if (_vm->_rnd->getRandomNumber(1) & 1)
SWAP(elem[1], elem[2]);
}
// Original name melange2
void EdenGame::scramble2(uint8 elem[4]) {
if (_vm->_rnd->getRandomNumber(1) & 1)
SWAP(elem[0], elem[1]);
if (_vm->_rnd->getRandomNumber(1) & 1)
SWAP(elem[2], elem[3]);
}
// Original name: melangedir
void EdenGame::scrambleDirections() {
scramble1(tab_2CB1E[0]);
scramble1(tab_2CB1E[1]);
scramble1(tab_2CB1E[2]);
scramble2(tab_2CB1E[3]);
scramble2(tab_2CB1E[4]);
scramble1(tab_2CB1E[5]);
scramble2(tab_2CB1E[6]);
scramble2(tab_2CB1E[7]);
}
bool EdenGame::naitredino(char persoType) {
for (perso_t *perso = &_persons[PER_MORKUS]; (++perso)->_roomNum != 0xFFFF;) {
char areaNum = perso->_roomNum >> 8;
if (areaNum != _globals->_citadelAreaNum)
continue;
if ((perso->_flags & PersonFlags::pf80) && (perso->_flags & PersonFlags::pfTypeMask) == persoType) {
perso->_flags &= ~PersonFlags::pf80;
return true;
}
}
return false;
}
// Original name: newcita
void EdenGame::newCitadel(char area, int16 level, Room *room) {
Citadel *cita = _citadelList;
while (cita->_id < level)
cita++;
uint16 index = ((room->_flags & 0xC0) >> 6); //TODO: this is very wrong
if (area == 4 || area == 6)
index++;
room->_bank = cita->_bank[index];
room->_video = cita->_video[index];
room->_flags |= RoomFlags::rf02;
}
// Original name: citaevol
void EdenGame::evolveCitadel(int16 level) {
Room *room = _globals->_curAreaPtr->_citadelRoomPtr;
perso_t *perso = &_persons[PER_UNKN_372];
byte loc = room->_location;
if (level >= 80 && !istrice((_globals->_citadelAreaNum << 8) | loc)) {
room->_level = 79;
return;
}
if (level > 160)
level = 160;
if (room->_level < 64 && level >= 64 && naitredino(PersonFlags::pftTriceraptor)) {
_globals->_curAreaPtr->_flags |= AreaFlags::HasTriceraptors;
addInfo(_globals->_citadelAreaNum + ValleyNews::vnTriceraptorsIn);
}
if (room->_level < 40 && level >= 40 && naitredino(PersonFlags::pftVelociraptor)) {
_globals->_curAreaPtr->_flags |= AreaFlags::HasVelociraptors;
addInfo(_globals->_citadelAreaNum + ValleyNews::vnVelociraptorsIn);
}
room->_level = level;
newCitadel(_globals->_citadelAreaNum, level, room);
byte speed = _dinoSpeedForCitadelLevel[room->_level >> 4];
for (; perso->_roomNum != 0xFFFF; perso++) {
if (perso->_flags & PersonFlags::pf80)
continue;
if ((perso->_roomNum >> 8) == _globals->_citadelAreaNum && perso->_targetLoc == loc)
perso->_speed = speed;
}
}
int16 EdenGame::getCurBankNum() {
return _curBankNum;
}
// Original name: citacapoute
void EdenGame::destroyCitadelRoom(int16 roomNum) {
perso_t *perso = &_persons[PER_UNKN_18C];
Room *room = _globals->_curAreaPtr->_citadelRoomPtr;
room->_flags |= RoomFlags::rf01;
room->_flags &= ~RoomFlags::rfHasCitadel;
room->_bank = 193;
room->_video = 0;
room->_level = 0;
_globals->_curAreaPtr->_citadelLevel = 0;
_globals->_curAreaPtr->_citadelRoomPtr = nullptr;
roomNum = (roomNum & ~0xFF) | room->_location;
for (; perso->_roomNum != 0xFFFF; perso++) {
if (perso->_roomNum == roomNum) {
perso->_flags &= ~PersonFlags::pf80;
removeInfo((roomNum >> 8) + ValleyNews::vnTyrannIn);
break;
}
}
}
// Original name: buildcita
void EdenGame::narratorBuildCitadel() {
Area *area = _globals->_areaPtr;
_globals->_curAreaPtr = _globals->_areaPtr;
if (area->_citadelRoomPtr)
destroyCitadelRoom(_globals->_roomNum);
_globals->_var6A = _globals->_var69;
_globals->_narratorSequence = _globals->_var69 | 0x80;
area->_citadelRoomPtr = _globals->_roomPtr;
_globals->_roomPtr->_flags &= ~RoomFlags::rf01;
_globals->_roomPtr->_flags |= RoomFlags::rfHasCitadel;
_globals->_roomPtr->_level = 32;
newCitadel(_globals->_areaNum, 32, _globals->_roomPtr);
area->_flags &= ~AreaFlags::TyrannSighted;
if (!(area->_flags & AreaFlags::afFlag8000)) {
if (_globals->_phaseNum == 304 || _globals->_phaseNum != 384) //TODO: wha
handleEloiReturn();
area->_flags |= AreaFlags::afFlag8000;
}
_globals->_roomCharacterPtr->_flags |= PersonFlags::pf80;
_globals->_citadelAreaNum = _globals->_areaNum;
naitredino(1);
removeInfo(_globals->_areaNum + ValleyNews::vnCitadelLost);
removeInfo(_globals->_areaNum + ValleyNews::vnTyrannLost);
if (_globals->_phaseNum == 193 && _globals->_areaNum == Areas::arUluru)
bigphase1();
}
// Original name: citatombe
void EdenGame::citadelFalls(char level) {
if (level)
newCitadel(_globals->_citadelAreaNum, level, _globals->_curAreaPtr->_citadelRoomPtr);
else {
destroyCitadelRoom(_globals->_citadelAreaNum << 8);
addInfo(_globals->_citadelAreaNum + ValleyNews::vnCitadelLost);
}
}
// Original name: constcita
void EdenGame::buildCitadel() {
if (!_globals->_curAreaPtr->_citadelLevel || !_globals->_curAreaPtr->_citadelRoomPtr)
return;
Room *room = _globals->_curAreaPtr->_citadelRoomPtr;
byte loc = room->_location;
_tyranPtr = &_persons[PER_UNKN_372];
if (istyran((_globals->_citadelAreaNum << 8) | loc)) {
if (!(_globals->_curAreaPtr->_flags & AreaFlags::TyrannSighted)) {
addInfo(_globals->_citadelAreaNum + ValleyNews::vnTyrannIn);
_globals->_curAreaPtr->_flags |= AreaFlags::TyrannSighted;
}
byte level = room->_level - 1;
if (level < 32)
level = 32;
room->_level = level;
citadelFalls(level);
} else {
_globals->_curAreaPtr->_flags &= ~AreaFlags::TyrannSighted;
evolveCitadel(room->_level + 1);
}
}
// Original name: depladino
void EdenGame::moveDino(perso_t *perso) {
int dir = getDirection(perso);
if (dir != -1) {
scrambleDirections();
uint8 *dirs = tab_2CB1E[dir];
byte loc = perso->_roomNum & 0xFF;
uint8 dir2 = dirs[0];
if (dir2 & 0x80)
dir2 = -(dir2 & ~0x80);
dir2 += loc;
if (!canMoveThere(dir2, perso)) {
dir2 = dirs[1];
if (dir2 & 0x80)
dir2 = -(dir2 & ~0x80);
dir2 += loc;
if (!canMoveThere(dir2, perso)) {
dir2 = dirs[2];
if (dir2 & 0x80)
dir2 = -(dir2 & ~0x80);
dir2 += loc;
if (!canMoveThere(dir2, perso)) {
dir2 = dirs[3];
if (dir2 & 0x80)
dir2 = -(dir2 & ~0x80);
dir2 += loc;
if (!canMoveThere(dir2, perso)) {
dir2 = perso->_lastLoc;
perso->_lastLoc = 0;
if (!canMoveThere(dir2, perso))
return;
}
}
}
}
perso->_lastLoc = perso->_roomNum & 0xFF;
perso->_roomNum &= ~0xFF;
perso->_roomNum |= dir2 & 0xFF;
if ((perso->_targetLoc - 16 == (perso->_roomNum & 0xFF))
|| (perso->_targetLoc + 16 == (perso->_roomNum & 0xFF))
|| (perso->_targetLoc - 1 == (perso->_roomNum & 0xFF))
|| (perso->_targetLoc + 1 == (perso->_roomNum & 0xFF)))
perso->_targetLoc = 0;
} else
perso->_targetLoc = 0;
}
// Original name: deplaalldino
void EdenGame::moveAllDino() {
for (perso_t *perso = &_persons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) {
if (((perso->_roomNum >> 8) & 0xFF) != _globals->_citadelAreaNum)
continue;
if ((perso->_flags & PersonFlags::pf80) || !perso->_targetLoc)
continue;
if (--perso->_steps)
continue;
perso->_steps = 1;
if (perso->_roomNum == _globals->_roomNum)
continue;
perso->_steps = perso->_speed;
moveDino(perso);
}
}
// Original name: newvallee
void EdenGame::newValley() {
static const int16 roomNumList[] = { 2075, 2080, 2119, -1};
perso_t *perso = &_persons[PER_UNKN_372];
const int16 *ptr = roomNumList;
int16 roomNum = *ptr++;
while (roomNum != -1) {
perso->_roomNum = roomNum;
perso->_flags &= ~PersonFlags::pf80;
perso->_flags &= ~PersonFlags::pf20;
perso++;
roomNum = *ptr++;
}
perso->_roomNum = 0xFFFF;
_areasTable[7]._flags |= AreaFlags::HasTyrann;
_globals->_worldHasTyran = 32;
}
char EdenGame::whereIsCita() {
char res = (char)-1;
for (Room *room = _globals->_citaAreaFirstRoom; room->_id != 0xFF; room++) {
if (!(room->_flags & RoomFlags::rfHasCitadel))
continue;
res = room->_location;
break;
}
return res;
}
bool EdenGame::isCita(int16 loc) {
loc &= 0xFF;
for (Room *room = _globals->_citaAreaFirstRoom; room->_id != 0xFF; room++) {
if (!(room->_flags & RoomFlags::rfHasCitadel))
continue;
if ((room->_location == loc + 16)
|| (room->_location == loc - 16)
|| (room->_location == loc - 1)
|| (room->_location == loc + 1))
return true;
}
return false;
}
// Original name: lieuvava
void EdenGame::placeVava(Area *area) {
if (area->_type == AreaType::atValley) {
istyranval(area);
area->_citadelLevel = 0;
if (area->_citadelRoomPtr)
area->_citadelLevel = _globals->_citaAreaFirstRoom->_level; //TODO: no search?
byte mask = ~(1 << (area->_num - Areas::arChamaar));
_globals->_worldTyranSighted &= mask;
_globals->_var4E &= mask;
_globals->_worldGaveGold &= mask;
_globals->_worldHasVelociraptors &= mask;
_globals->_worldHasTriceraptors &= mask;
_globals->_worldHasTyran &= mask;
_globals->_var53 &= mask;
mask = ~mask;
if (area->_flags & AreaFlags::TyrannSighted)
_globals->_worldTyranSighted |= mask;
if (area->_flags & AreaFlags::afFlag4)
_globals->_var4E |= mask;
if (area->_flags & AreaFlags::HasTriceraptors)
_globals->_worldHasTriceraptors |= mask;
if (area->_flags & AreaFlags::afGaveGold)
_globals->_worldGaveGold |= mask;
if (area->_flags & AreaFlags::HasVelociraptors)
_globals->_worldHasVelociraptors |= mask;
if (area->_flags & AreaFlags::HasTyrann)
_globals->_worldHasTyran |= mask;
if (area->_flags & AreaFlags::afFlag20)
_globals->_var53 |= mask;
if (area == _globals->_areaPtr) {
_globals->_curAreaFlags = area->_flags;
_globals->_curCitadelLevel = area->_citadelLevel;
}
}
_globals->_var4D &= _globals->_worldTyranSighted;
}
void EdenGame::vivredino() {
for (perso_t *perso = &_persons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) {
if (((perso->_roomNum >> 8) & 0xFF) != _globals->_citadelAreaNum)
continue;
if (perso->_flags & PersonFlags::pf80)
continue;
switch (perso->_flags & PersonFlags::pfTypeMask) {
case PersonFlags::pftTyrann:
if (isCita(perso->_roomNum))
perso->_targetLoc = 0;
else if (!perso->_targetLoc) {
char cita = whereIsCita();
if (cita != (char)-1) {
perso->_targetLoc = cita;
perso->_speed = 2;
perso->_steps = 1;
}
}
break;
case PersonFlags::pftTriceraptor:
if (perso->_flags & PersonFlags::pfInParty) {
if (isCita(perso->_roomNum))
perso->_targetLoc = 0;
else if (!perso->_targetLoc) {
char cita = whereIsCita();
if (cita != (char)-1) {
perso->_targetLoc = cita;
perso->_speed = 3;
perso->_steps = 1;
}
}
}
break;
case PersonFlags::pftVelociraptor:
if (perso->_flags & PersonFlags::pf10) {
if (perso->_roomNum == _globals->_roomNum) {
perso_t *perso2 = &_persons[PER_UNKN_372];
bool found = false;
for (; perso2->_roomNum != 0xFFFF; perso2++) {
if ((perso->_roomNum & ~0xFF) == (perso2->_roomNum & ~0xFF)) {
if (perso2->_flags & PersonFlags::pf80)
continue;
perso->_targetLoc = perso2->_roomNum & 0xFF;
perso->_steps = 1;
found = true;
break;
}
}
if (found)
continue;
} else {
_tyranPtr = &_persons[PER_UNKN_372];
if (istyran(perso->_roomNum)) {
if (_globals->_phaseNum < 481 && (perso->_powers & (1 << (_globals->_citadelAreaNum - 3)))) {
_tyranPtr->_flags |= PersonFlags::pf80;
_tyranPtr->_roomNum = 0;
perso->_flags &= ~PersonFlags::pf10;
perso->_flags |= PersonFlags::pfInParty;
addInfo(_globals->_citadelAreaNum + ValleyNews::vnTyrannLost);
removeInfo(_globals->_citadelAreaNum + ValleyNews::vnTyrannIn);
if (naitredino(PersonFlags::pftTriceraptor))
addInfo(_globals->_citadelAreaNum + ValleyNews::vnTriceraptorsIn);
buildCitadel();
_globals->_curAreaPtr->_flags &= ~AreaFlags::TyrannSighted;
} else {
perso->_flags &= ~PersonFlags::pf10;
perso->_flags &= ~PersonFlags::pfInParty;
addInfo(_globals->_citadelAreaNum + ValleyNews::vnVelociraptorsLost);
}
continue;
}
}
}
if (!perso->_targetLoc) {
int16 loc;
perso->_lastLoc = 0;
do {
loc = (_vm->_rnd->getRandomNumber(63) & 63) + 16;
if ((loc & 0xF) >= 12)
loc &= ~4; //TODO: ??? same as -= 4
} while (!canMoveThere(loc, perso));
perso->_targetLoc = loc;
perso->_steps = 1;
}
break;
default:
break;
}
}
}
void EdenGame::vivreval(int16 areaNum) {
_globals->_citadelAreaNum = areaNum;
_globals->_curAreaPtr = &_areasTable[areaNum - 1];
_globals->_citaAreaFirstRoom = &_gameRooms[_globals->_curAreaPtr->_firstRoomIdx];
moveAllDino();
buildCitadel();
vivredino();
newMushroom();
newNestWithEggs();
newEmptyNest();
if (_globals->_phaseNum >= 226)
newGold();
placeVava(_globals->_curAreaPtr);
}
// Original name: chaquejour
void EdenGame::handleDay() {
vivreval(3);
vivreval(4);
vivreval(5);
vivreval(6);
vivreval(7);
vivreval(8);
_globals->_drawFlags |= DrawFlags::drDrawTopScreen;
}
// Original name: temps_passe
void EdenGame::addTime(int16 t) {
int16 days = _globals->_gameDays;
int16 lo = _globals->_gameHours + t;
if (lo > 255) {
days++;
lo &= 0xFF;
}
_globals->_gameHours = lo;
t = ((t >> 8) & 0xFF) + days;
t -= _globals->_gameDays;
if (t) {
_globals->_gameDays += t;
while (t--)
handleDay();
}
}
byte *EdenGame::getImageDesc() {
return _imageDesc;
}
// Original name: anim_perso
void EdenGame::animCharacter() {
if (_curBankNum != _globals->_characterImageBank)
loadCharacter(_globals->_characterPtr);
_graphics->restoreUnderSubtitles();
if (_restartAnimation) {
_lastAnimTicks = _vm->_timerTicks;
_restartAnimation = false;
}
_curAnimFrameNumb = (_vm->_timerTicks - _lastAnimTicks) >> 2; // TODO: check me!!!
if (_curAnimFrameNumb > _numAnimFrames) // TODO: bug?
_animateTalking = false;
if (_globals->_curCharacterAnimPtr && !_globals->_animationFlags && _curAnimFrameNumb != _lastAnimFrameNumb) {
_lastAnimFrameNumb = _curAnimFrameNumb;
if (*_globals->_curCharacterAnimPtr == 0xFF)
getanimrnd();
useCharacterBank();
_numImgDesc = 0;
setCharacterSprite(_globals->_curCharacterAnimPtr);
_globals->_curCharacterAnimPtr += _numImgDesc + 1;
_mouthAnimations = _imageDesc + 200;
removeMouthSprite();
if (*_mouthAnimations)
_graphics->displayImage();
_animationDelay--;
if (!_animationDelay) {
_globals->_animationFlags = 1;
_animationDelay = 8;
}
}
_animationDelay--;
if (!_animationDelay) {
getanimrnd();
//TODO: no reload?
}
if (_animateTalking) {
if (!_animationTable) {
_animationTable = _gameLipsync + 7262; //TODO: fix me
if (!_backgroundSaved) {
_graphics->saveMouthBackground();
_backgroundSaved = true;
}
}
if (!_personTalking)
_curAnimFrameNumb = _numAnimFrames - 1;
_animationIndex = _animationTable[_curAnimFrameNumb];
if (_animationIndex == 0xFF)
_animateTalking = false;
else if (_animationIndex != _lastAnimationIndex) {
useCharacterBank();
_graphics->restoreMouthBackground();
// debug("perso spr %d", animationIndex);
setCharacterSprite(_globals->_persoSpritePtr2 + _animationIndex * 2); //TODO: int16s?
_mouthAnimations = _imageDesc + 200;
if (*_mouthAnimations)
_graphics->displayImage();
_lastAnimationIndex = _animationIndex;
}
}
_graphics->displaySubtitles();
}
void EdenGame::getanimrnd() {
_animationDelay = 8;
int16 rnd = _vm->_rnd->getRandomNumber(65535) & (byte)~0x18; //TODO
dword_30724 = _globals->_persoSpritePtr + 16; //TODO
_globals->_curCharacterAnimPtr = _globals->_persoSpritePtr + ((dword_30724[1] << 8) + dword_30724[0]);
_globals->_animationFlags = 1;
if (rnd >= 8)
return;
_globals->_animationFlags = 0;
if (rnd <= 0)
return;
for (rnd *= 8; rnd > 0; rnd--) {
while (*_globals->_curCharacterAnimPtr)
_globals->_curCharacterAnimPtr++;
_globals->_curCharacterAnimPtr++;
}
}
void EdenGame::addanim() {
_lastAnimationIndex = 0xFF;
_lastAnimTicks = 0;
_globals->_animationFlags = 0xC0;
_globals->_curCharacterAnimPtr = _globals->_persoSpritePtr;
getanimrnd();
_animationActive = true;
if (_globals->_characterPtr == &_persons[PER_KING])
return;
setCharacterSprite(_globals->_persoSpritePtr + READ_LE_UINT16(_globals->_persoSpritePtr)); //TODO: GetElem(0)
_mouthAnimations = _imageDesc + 200;
if (_globals->_characterPtr->_id != PersonId::pidCabukaOfCantura && _globals->_characterPtr->_targetLoc != 7) //TODO: targetLoc is minisprite idx
removeMouthSprite();
if (*_mouthAnimations)
_graphics->displayImage();
}
// Original name: virespritebouche
void EdenGame::removeMouthSprite() {
byte *src = _mouthAnimations + 2;
byte *dst = src;
char cnt = _mouthAnimations[0];
while (cnt--) {
byte a = *src++;
byte b = *src++;
byte c = *src++;
dst[0] = a;
dst[1] = b;
dst[2] = c;
if (dword_30728[0] != 0xFF) {
if ((a < dword_30728[0] || a > dword_30728[1])
&& (a < dword_30728[2] || a > dword_30728[3]))
dst += 3;
else
_mouthAnimations[0]--;
} else
dst += 3;
}
}
// Original name: anim_perfin
void EdenGame::AnimEndCharacter() {
_globals->_animationFlags &= ~0x80;
_animationDelay = 0;
_animationActive = false;
}
// Original name: perso_spr
void EdenGame::setCharacterSprite(byte *spr) {
byte *img = _imageDesc + 200 + 2;
int16 count = 0;
byte c;
while ((c = *spr++)) {
byte *src;
int16 index = 0;
byte cc = 0;
if (c == 1) {
cc = index;
c = *spr++;
}
_numImgDesc++;
index = (cc << 8) | c;
index -= 2;
if (index > _maxPersoDesc)
index = _maxPersoDesc;
index *= 2; //TODO: src = GetElem(ff_C2, index)
src = _globals->_varC2;
src += READ_LE_UINT16(src + index);
while ((c = *src++)) {
*img++ = c;
*img++ = *src++;
*img++ = *src++;
count++;
}
}
_imageDesc[200] = count & 0xFF;
_imageDesc[201] = count >> 8;
}
// Original name: af_perso1
void EdenGame::displayCharacter1() {
setCharacterSprite(_globals->_persoSpritePtr + READ_LE_UINT16(_globals->_persoSpritePtr));
_graphics->displayImage();
}
// Original name: af_perso
void EdenGame::displayCharacter() {
loadCurrCharacter();
displayCharacter1();
}
void EdenGame::ef_perso() {
_globals->_animationFlags &= 0x3F;
}
// Original name: load_perso
void EdenGame::loadCharacter(perso_t *perso) {
_characterBankData = nullptr;
if (!perso->_spriteBank)
return;
if (perso->_spriteBank != _globals->_characterImageBank) {
_graphics->setCurCharRect(&_characterRects[perso->_id]); //TODO: array of int16?
dword_30728 = _characterArray[perso->_id];
ef_perso();
_globals->_characterImageBank = perso->_spriteBank;
useBank(_globals->_characterImageBank);
_characterBankData = _bankData;
byte *ptr = _bankData;
ptr += READ_LE_UINT16(ptr);
byte *baseptr = ptr;
ptr += READ_LE_UINT16(ptr) - 2;
ptr = baseptr + READ_LE_UINT16(ptr) + 4;
_gameIcons[0].sx = READ_LE_UINT16(ptr);
_gameIcons[0].sy = READ_LE_UINT16(ptr + 2);
_gameIcons[0].ex = READ_LE_UINT16(ptr + 4);
_gameIcons[0].ey = READ_LE_UINT16(ptr + 6);
ptr += 8;
_globals->_varC2 = ptr + 2;
_maxPersoDesc = READ_LE_UINT16(ptr) / 2;
ptr += READ_LE_UINT16(ptr);
baseptr = ptr;
ptr += READ_LE_UINT16(ptr) - 2;
_globals->_persoSpritePtr = baseptr;
_globals->_persoSpritePtr2 = baseptr + READ_LE_UINT16(ptr);
debug("load perso: b6 len is %d", (int)(_globals->_persoSpritePtr2 - _globals->_persoSpritePtr));
} else {
useBank(_globals->_characterImageBank);
_characterBankData = _bankData;
}
}
// Original name: load_perso_cour
void EdenGame::loadCurrCharacter() {
loadCharacter(_globals->_characterPtr);
}
void EdenGame::fin_perso() {
_globals->_animationFlags &= 0x3F;
_globals->_curCharacterAnimPtr = nullptr;
_globals->_varCA = 0;
_globals->_characterImageBank = -1;
AnimEndCharacter();
}
void EdenGame::no_perso() {
if (_globals->_displayFlags == DisplayFlags::dfPerson) {
_globals->_displayFlags = _globals->_oldDisplayFlags;
fin_perso();
}
endCharacterSpeech();
}
// Original name: close_perso
void EdenGame::closeCharacterScreen() {
endCharacterSpeech();
if (_globals->_displayFlags == DisplayFlags::dfPerson && _globals->_characterPtr->_id != PersonId::pidNarrator && _globals->_eventType != EventType::etEventE) {
_graphics->rundcurs();
_graphics->setSavedUnderSubtitles(true);
_graphics->restoreUnderSubtitles();
display();
_globals->_var103 = 16;
}
if (_globals->_characterPtr->_id == PersonId::pidNarrator)
_globals->_var103 = 69;
_globals->_eloiHaveNews &= 1;
_globals->_varCA = 0;
_globals->_varF6 = 0;
if (_globals->_displayFlags == DisplayFlags::dfPerson) {
_globals->_displayFlags = _globals->_oldDisplayFlags;
_globals->_animationFlags &= 0x3F;
_globals->_curCharacterAnimPtr = nullptr;
AnimEndCharacter();
if (_globals->_displayFlags & DisplayFlags::dfMirror) {
gameToMirror(1);
_scrollPos = _oldScrollPos;
scroll();
return;
}
if (_globals->_numGiveObjs) {
if (!(_globals->_displayFlags & DisplayFlags::dfFlag2))
showObjects();
_globals->_numGiveObjs = 0;
}
if (_globals->_varF2 & 1) {
_globals->_mirrorEffect = 6; // CHECKME: Verify the value
_globals->_varF2 &= ~1;
}
char oldLoc = _globals->_newLocation;
_globals->_newLocation = 0;
if (!(_globals->_narratorSequence & 0x80))
_globals->_var100 = 0xFF;
updateRoom(_globals->_roomNum);
_globals->_newLocation = oldLoc;
}
if (_globals->_chrono)
_globals->_chronoFlag = 1;
}
// Original name: af_fondsuiveur
void EdenGame::displayBackgroundFollower() {
char id = _globals->_characterPtr->_id;
for (Follower *follower = _followerList; follower->_id != -1; follower++) {
if (follower->_id == id) {
int bank = 326;
if (follower->sx >= 320)
bank = 327;
useBank(bank + _globals->_roomBackgroundBankNum);
_graphics->drawSprite(0, 0, 16, true);
break;
}
}
}
void EdenGame::displayNoFollower(int16 bank) {
if (bank) {
useBank(bank);
if (_globals->_characterPtr == &_persons[PER_UNKN_156])
_graphics->drawSprite(0, 0, 16, true);
else
_graphics->drawSprite(0, 0, 16);
}
}
int16 EdenGame::getGameIconX(int16 index) {
return _gameIcons[index].sx;
}
int16 EdenGame::getGameIconY(int16 index) {
return _gameIcons[index].sy;
}
// Original name: af_fondperso1
void EdenGame::displayCharacterBackground1() {
byte bank;
char *ptab;
if (_globals->_characterPtr == &_persons[PER_ELOI]) {
_gameIcons[0].sx = 0;
_characterRects[PER_ELOI].left = 2;
bank = _globals->_characterBackgroundBankIdx;
if (_globals->_eventType == EventType::etEventE) {
_globals->_var103 = 1;
displayNoFollower(bank);
return;
}
_gameIcons[0].sx = 60;
_characterRects[PER_ELOI].left = 62;
}
if (_globals->_characterPtr == &_persons[PER_TAU]) {
bank = 37;
if (_globals->_curObjectId == Objects::obShell) {
displayNoFollower(bank);
return;
}
}
ptab = _personRoomBankTable + _globals->_characterPtr->_roomBankId;
bank = *ptab++;
if (!(_globals->_characterPtr->_partyMask & _globals->_party)) {
while ((bank = *ptab++) != 0xFF) {
if (bank == (_globals->_roomNum & 0xFF)) { //TODO: signed vs unsigned - chg bank to uns?
bank = *ptab;
break;
}
ptab++;
}
if (bank == 0xFF) {
ptab = _personRoomBankTable + _globals->_characterPtr->_roomBankId;
bank = *ptab++;
}
}
displayBackgroundFollower();
displayNoFollower(bank);
}
// Original name: af_fondperso
void EdenGame::displayCharacterBackground() {
if (_globals->_characterPtr->_spriteBank) {
_backgroundSaved = false;
displayCharacterBackground1();
}
}
// Original name: setpersoicon
void EdenGame::setCharacterIcon() {
if (_globals->_iconsIndex == 4)
return;
if (_globals->_characterPtr == &_persons[PER_ELOI] && _globals->_eventType == EventType::etEventE) {
_globals->_iconsIndex = 123;
return;
}
Icon *icon = _gameIcons;
Icon *icon2 = &_gameIcons[_roomIconsBase];
*icon2++ = *icon++; //TODO: is this ok?
*icon2++ = *icon++;
icon2->sx = -1;
}
// Original name: show_perso
void EdenGame::showCharacter() {
perso_t *perso = _globals->_characterPtr;
if (perso->_spriteBank) {
closeRoom();
if (_globals->_displayFlags != DisplayFlags::dfPerson) {
if (_globals->_displayFlags & DisplayFlags::dfMirror)
resetScroll();
_globals->_oldDisplayFlags = _globals->_displayFlags;
_globals->_displayFlags = DisplayFlags::dfPerson;
loadCharacter(perso);
setCharacterIcon();
displayCharacterBackground();
if (perso == &_persons[PER_TAU] && _globals->_curObjectId == Objects::obShell) {
_graphics->displaySubtitles();
updateCursor();
_paletteUpdateRequired = true;
display();
_graphics->rundcurs();
return;
}
}
loadCurrCharacter();
addanim();
if (!_globals->_curCharacterAnimPtr) {
displayCharacter();
_graphics->displaySubtitles();
}
_restartAnimation = true;
animCharacter();
if (perso != &_persons[PER_UNKN_156])
updateCursor();
_paletteUpdateRequired = true;
if (perso != &_persons[PER_UNKN_156])
_graphics->rundcurs();
display();
} else {
displayPlace();
_graphics->displaySubtitles();
}
}
// Original name: showpersopanel
void EdenGame::displayCharacterPanel() {
perso_t *perso = _globals->_characterPtr;
loadCurrCharacter();
addanim();
if (!_globals->_curCharacterAnimPtr) {
displayCharacter();
_graphics->displaySubtitles();
}
_restartAnimation = true;
_paletteUpdateRequired = true;
if (_globals->_drawFlags & DrawFlags::drDrawFlag8)
return;
animCharacter();
if (perso != &_persons[PER_UNKN_156])
updateCursor();
display();
if (perso != &_persons[PER_UNKN_156])
_graphics->rundcurs();
_globals->_drawFlags |= DrawFlags::drDrawFlag8;
_globals->_iconsIndex = 112;
}
void EdenGame::getDataSync() {
int16 num = _globals->_textNum;
if (_globals->_textBankIndex != 1)
num += 565;
if (_globals->_textBankIndex == 3)
num += 707;
if (num == 144)
num = 142;
_animateTalking = ReadDataSync(num - 1);
if (_animateTalking)
_numAnimFrames = readFrameNumber();
else
_numAnimFrames = 0;
if (_globals->_textNum == 144)
_numAnimFrames = 48;
_animationTable = nullptr;
}
// Original name: ReadNombreFrames
int16 EdenGame::readFrameNumber() {
int16 num = 0;
_animationTable = _gameLipsync + 7260 + 2; //TODO: fix me
while (*_animationTable++ != 0xFF)
num++;
return num;
}
void EdenGame::waitEndSpeak() {
for (;;) {
if (_animationActive)
animCharacter();
musicspy();
display();
_vm->pollEvents();
if (_vm->shouldQuit()) {
closeCharacterScreen();
edenShudown();
break;
}
if (!_mouseHeld)
if (_vm->isMouseButtonDown())
break;
if (_mouseHeld)
if (!_vm->isMouseButtonDown())
_mouseHeld = false;
}
_mouseHeld = true;
}
int16 EdenGame::getNumTextLines() {
return _numTextLines;
}
void EdenGame::my_bulle() {
if (!_globals->_textNum)
return;
byte *icons = phraseIconsBuffer;
byte *linesp = _sentenceCoordsBuffer;
byte *sentencePtr = _sentenceBuffer;
_globals->_numGiveObjs = 0;
_globals->_giveObj1 = 0;
_globals->_giveObj2 = 0;
_globals->_giveObj3 = 0;
_globals->_textWidthLimit = _subtitlesXWidth;
byte *textPtr = getPhrase(_globals->_textNum);
_numTextLines = 0;
int16 wordsOnLine = 0;
int16 wordWidth = 0;
int16 lineWidth = 0;
byte c;
while ((c = *textPtr++) != 0xFF) {
if (c == 0x11 || c == 0x13) {
if (_globals->_phaseNum <= 272 || _globals->_phaseNum == 386) {
_globals->_eloiHaveNews = c & 0xF;
_globals->_var4D = _globals->_worldTyranSighted;
}
} else if (c >= 0x80 && c < 0x90)
SysBeep(1);
else if (c >= 0x90 && c < 0xA0) {
while (*textPtr++ != 0xFF) {}
textPtr--;
} else if (c >= 0xA0 && c < 0xC0)
_globals->_textToken1 = c & 0xF;
else if (c >= 0xC0 && c < 0xD0)
_globals->_textToken2 = c & 0xF;
else if (c >= 0xD0 && c < 0xE0) {
byte c1 = *textPtr++;
if (c == 0xD2)
#ifdef FAKE_DOS_VERSION
_globals->_textWidthLimit = c1 + 160;
#else
_globals->_textWidthLimit = c1 + _subtitlesXCenter; // TODO: signed? 160 in pc ver
#endif
else {
byte c2 = *textPtr++;
switch (_globals->_numGiveObjs) {
case 0:
_globals->_giveObj1 = c2;
break;
case 1:
_globals->_giveObj2 = c2;
break;
case 2:
_globals->_giveObj3 = c2;
break;
default:
break;
}
_globals->_numGiveObjs++;
*icons++ = *textPtr++;
*icons++ = *textPtr++;
*icons++ = c2;
}
} else if (c >= 0xE0 && c < 0xFF)
SysBeep(1);
else if (c != '\r') {
*sentencePtr++ = c;
byte width = _gameFont[c];
#ifdef FAKE_DOS_VERSION
if (c == ' ')
width = _spaceWidth;
#endif
wordWidth += width;
lineWidth += width;
int16 overrun = lineWidth - _globals->_textWidthLimit;
if (overrun > 0) {
_numTextLines++;
if (c != ' ') {
*linesp++ = wordsOnLine;
*linesp++ = wordWidth + _spaceWidth - overrun;
lineWidth = wordWidth;
} else {
*linesp++ = wordsOnLine + 1;
*linesp++ = _spaceWidth - overrun; //TODO: checkme
lineWidth = 0;
}
wordWidth = 0;
wordsOnLine = 0;
} else {
if (c == ' ') {
wordsOnLine++;
wordWidth = 0;
}
}
}
}
_numTextLines++;
*linesp++ = wordsOnLine + 1;
*linesp++ = wordWidth;
*sentencePtr = c;
if (_globals->_textBankIndex == 2 && _globals->_textNum == 101 && _globals->_prefLanguage == 1)
patchSentence();
my_pr_bulle();
if (!_globals->_numGiveObjs)
return;
useMainBank();
if (_numTextLines < 3)
_numTextLines = 3;
icons = phraseIconsBuffer;
for (byte i = 0; i < _globals->_numGiveObjs; i++) {
byte x = *icons++;
byte y = *icons++;
byte s = *icons++;
_graphics->drawSprite(52, x + _subtitlesXCenter, y - 1, false, true);
_graphics->drawSprite(s + 9, x + _subtitlesXCenter + 1, y, false, true);
}
}
int16 EdenGame::getScrollPos() {
return _scrollPos;
}
bool EdenGame::getSpecialTextMode() {
return _specialTextMode;
}
void EdenGame::setSpecialTextMode(bool value) {
_specialTextMode = value;
}
void EdenGame::my_pr_bulle() {
CLBlitter_FillView(_graphics->getSubtitlesView(), 0);
if (_globals->_prefLanguage == 0)
return;
byte *coo = _sentenceCoordsBuffer;
bool done = false;
textout = _graphics->getSubtitlesViewBuf();
byte *textPtr = _sentenceBuffer;
int16 lines = 1;
while (!done) {
int16 numWords = *coo++; // num words on line
int16 padSize = *coo++; // amount of extra spacing
byte *currOut = textout;
int16 extraSpacing = numWords > 1 ? padSize / (numWords - 1) + 1 : 0;
if (lines == _numTextLines)
extraSpacing = 0;
byte c = *textPtr++;
while (!done && (numWords > 0)) {
if (c < 0x80 && c != '\r') {
if (c == ' ') {
numWords--;
if (padSize >= extraSpacing) {
textout += extraSpacing + _spaceWidth;
padSize -= extraSpacing;
} else {
textout += padSize + _spaceWidth;
padSize = 0;
}
} else {
int16 charWidth = _gameFont[c];
if (!(_globals->_drawFlags & DrawFlags::drDrawMenu)) {
textout += _subtitlesXWidth;
if (!_specialTextMode)
drawSubtitleChar(c, 195, charWidth);
textout++;
if (!_specialTextMode)
drawSubtitleChar(c, 195, charWidth);
textout -= _subtitlesXWidth + 1;
}
if (_specialTextMode)
drawSubtitleChar(c, 250, charWidth);
else
drawSubtitleChar(c, 230, charWidth);
textout += charWidth;
}
} else
error("my_pr_bulle: Unexpected format");
c = *textPtr++;
if (c == 0xFF)
done = true;
}
textout = currOut + _subtitlesXWidth * FONT_HEIGHT;
lines++;
textPtr--;
}
}
// Original name: charsurbulle
void EdenGame::drawSubtitleChar(byte c, byte color, int16 width) {
byte *glyph = _gameFont + 256 + c * FONT_HEIGHT;
_textOutPtr = textout;
for (int16 h = 0; h < FONT_HEIGHT; h++) {
byte bits = *glyph++;
int16 mask = 0x80;
for (int16 w = 0; w < width; w++) {
if (bits & mask)
*_textOutPtr = color;
_textOutPtr++;
mask >>= 1;
}
_textOutPtr += _subtitlesXWidth - width;
}
}
// Original name: patchPhrase
void EdenGame::patchSentence() {
_sentenceBuffer[36] = 'c';
}
void EdenGame::vavapers() {
perso_t *perso = _globals->_characterPtr;
_globals->_curPersoFlags = perso->_flags;
_globals->_curPersoItems = perso->_items;
_globals->_curCharacterPowers = perso->_powers;
}
void EdenGame::citadelle() {
_globals->_var69++;
_globals->_varF6++;
parlemoiNormalFlag = true;
_closeCharacterDialog = true;
}
// Original name: choixzone
void EdenGame::selectZone() {
if (_globals->_giveObj3)
_globals->_iconsIndex = 6;
else
_globals->_iconsIndex = 10;
_globals->_autoDialog = false;
putObject();
}
void EdenGame::showEvents1() {
_globals->_var113 = 0;
perso_ici(3);
}
void EdenGame::showEvents() {
if (_globals->_eventType && _globals->_displayFlags != DisplayFlags::dfPerson)
showEvents1();
}
void EdenGame::parle_mfin() {
perso_t *perso = _globals->_characterPtr;
if (_globals->_curObjectId) {
char curobj = _globals->_curObjectId;
if (_globals->_dialogType == DialogType::dtHint)
return;
object_t *obj = getObjectPtr(_globals->_curObjectId);
if (_globals->_dialogType == DialogType::dtDinoItem)
perso = _globals->_roomCharacterPtr;
if (isAnswerYes()) {
loseObject(_globals->_curObjectId);
perso->_powers |= obj->_powerMask;
}
perso->_items |= obj->_itemMask;
specialObjects(perso, curobj);
return;
}
if (!isAnswerYes())
return;
nextInfo();
if (!_globals->_lastInfo)
_closeCharacterDialog = true;
else {
_globals->_nextDialogPtr = nullptr;
_closeCharacterDialog = false;
}
}
void EdenGame::parlemoi_normal() {
Dialog *dial;
if (!_globals->_nextDialogPtr) {
perso_t *perso = _globals->_characterPtr;
if (perso) {
int16 num = (perso->_id << 3) | _globals->_dialogType;
dial = (Dialog *)getElem(_gameDialogs, num);
} else {
closeCharacterScreen();
return;
}
} else {
if (_closeCharacterDialog) {
closeCharacterScreen();
return;
}
dial = _globals->_nextDialogPtr;
}
char ok = dial_scan(dial);
_globals->_nextDialogPtr = _globals->_dialogPtr;
_closeCharacterDialog = false;
if (!ok)
closeCharacterScreen();
else
parle_mfin();
}
void EdenGame::parle_moi() {
endCharacterSpeech();
byte r28 = _globals->_varF6;
_globals->_varF6 = 0;
if (!r28) {
setChoiceNo();
if (_globals->_drawFlags & DrawFlags::drDrawInventory)
showObjects();
if (_globals->_drawFlags & DrawFlags::drDrawTopScreen)
drawTopScreen();
if (_globals->_curObjectId) {
if (_globals->_dialogType == DialogType::dtTalk) {
_globals->_dialogType = DialogType::dtItem;
_globals->_nextDialogPtr = nullptr;
_closeCharacterDialog = false;
}
parlemoi_normal();
return;
}
if (_globals->_dialogType == DialogType::dtItem) {
_globals->_dialogType = DialogType::dtTalk;
if (!_closeCharacterDialog)
_globals->_nextDialogPtr = nullptr;
}
if (parlemoiNormalFlag) {
parlemoi_normal();
return;
}
Dialog *dial;
if (!_globals->_lastDialogPtr) {
int16 num = 160;
if (_globals->_phaseNum >= 400)
num++;
dial = (Dialog *)getElem(_gameDialogs, num);
} else
dial = _globals->_lastDialogPtr;
char ok = dial_scan(dial);
_globals->_lastDialogPtr = _globals->_dialogPtr;
parlemoiNormalFlag = false;
if (!ok) {
parlemoiNormalFlag = true;
if (_globals->_var60) {
if (_globals->_characterPtr == &_persons[PER_ELOI]) {
_globals->_dialogType = DialogType::dtTalk;
if (_globals->_eloiHaveNews)
parlemoi_normal();
else
closeCharacterScreen();
} else
closeCharacterScreen();
} else
parlemoi_normal();
} else
parle_mfin();
} else
closeCharacterScreen();
}
// Original name: init_perso_ptr
void EdenGame::initCharacterPointers(perso_t *perso) {
_globals->_metPersonsMask1 |= perso->_partyMask;
_globals->_metPersonsMask2 |= perso->_partyMask;
_globals->_nextDialogPtr = nullptr;
_closeCharacterDialog = false;
_dialogSkipFlags = DialogFlags::dfSpoken;
_globals->_var60 = 0;
_globals->_textToken1 = 0;
}
void EdenGame::perso1(perso_t *perso) {
_globals->_phaseActionsCount++;
if (perso == &_persons[PER_TAU])
_globals->_phaseActionsCount--;
_globals->_characterPtr = perso;
initCharacterPointers(perso);
parle_moi();
}
void EdenGame::perso_normal(perso_t *perso) {
_globals->_lastDialogPtr = nullptr;
_globals->_dialogType = DialogType::dtTalk;
parlemoiNormalFlag = false;
perso1(perso);
}
// Original name: persoparle
void EdenGame::handleCharacterDialog(int16 pers) {
perso_t *perso = &_persons[pers];
_globals->_characterPtr = perso;
_globals->_dialogType = DialogType::dtInspect;
uint16 idx = perso->_id * 8 | _globals->_dialogType;
dialoscansvmas((Dialog *)getElem(_gameDialogs, idx));
displayPlace();
_graphics->displaySubtitles();
persovox();
_globals->_varCA = 0;
_globals->_dialogType = DialogType::dtTalk;
}
// Original name: roi
void EdenGame::actionKing() {
perso_normal(&_persons[PER_KING]);
}
// Original name: dina
void EdenGame::actionDina() {
perso_normal(&_persons[PER_DINA]);
}
// Original name: thoo
void EdenGame::actionThoo() {
perso_normal(&_persons[PER_TAU]);
}
// Original name: monk
void EdenGame::actionMonk() {
perso_normal(&_persons[PER_MONK]);
}
// Original name: bourreau
void EdenGame::actionTormentor() {
perso_normal(&_persons[PER_JABBER]);
}
// Original name: messager
void EdenGame::actionMessenger() {
perso_normal(&_persons[PER_ELOI]);
}
// Original name: mango
void EdenGame::actionMango() {
perso_normal(&_persons[PER_MUNGO]);
}
// Original name: eve
void EdenGame::actionEve() {
perso_normal(&_persons[PER_EVE]);
}
// Original name: azia
void EdenGame::actionAzia() {
perso_normal(&_persons[PER_SHAZIA]);
}
// Original name: mammi
void EdenGame::actionMammi() {
perso_t *perso;
for (perso = &_persons[PER_MAMMI]; perso->_partyMask == PersonMask::pmLeader; perso++) {
if (perso->_roomNum == _globals->_roomNum) {
perso_normal(perso);
break;
}
}
}
// Original name: gardes
void EdenGame::actionGuards() {
perso_normal(&_persons[PER_GUARDS]);
}
// Original name: bambou
void EdenGame::actionBamboo() {
perso_normal(&_persons[PER_BAMBOO]);
}
// Original name: kabuka
void EdenGame::actionKabuka() {
if (_globals->_roomNum == 0x711) perso_normal(&_persons[PER_KABUKA]);
else actionBamboo();
}
// Original name: fisher
void EdenGame::actionFisher() {
if (_globals->_roomNum == 0x902) perso_normal(&_persons[PER_FISHER]);
else actionKabuka();
}
// Original name: dino
void EdenGame::actionDino() {
perso_t *perso = _globals->_roomCharacterPtr;
if (!perso)
return;
parlemoiNormalFlag = true;
_globals->_dialogType = DialogType::dtTalk;
_globals->_roomCharacterFlags = perso->_flags;
_globals->_roomPersoItems = perso->_items;
_globals->_roomCharacterPowers = perso->_powers;
_globals->_characterPtr = perso;
initCharacterPointers(perso);
debug("beg dino talk");
parle_moi();
debug("end dino talk");
if (_globals->_areaNum == Areas::arWhiteArch)
return;
if (_globals->_var60)
waitEndSpeak();
if (_vm->shouldQuit())
return;
perso = &_persons[PER_MUNGO];
if (!(_globals->_party & PersonMask::pmMungo)) {
perso = &_persons[PER_DINA];
if (!(_globals->_party & PersonMask::pmDina)) {
perso = &_persons[PER_EVE];
if (!(_globals->_party & PersonMask::pmEve)) {
perso = &_persons[PER_GUARDS];
}
}
}
_globals->_dialogType = DialogType::dtDinoAction;
if (_globals->_curObjectId)
_globals->_dialogType = DialogType::dtDinoItem;
perso1(perso);
if (_globals->_roomCharacterType == PersonFlags::pftMosasaurus && !_globals->_curObjectId) {
_globals->_areaPtr->_flags |= AreaFlags::afFlag20;
placeVava(_globals->_areaPtr);
}
}
// Original name: tyran
void EdenGame::actionTyran() {
perso_t *perso = _globals->_roomCharacterPtr;
if (!perso)
return;
parlemoiNormalFlag = true;
_globals->_dialogType = DialogType::dtTalk;
_globals->_roomCharacterFlags = perso->_flags;
_globals->_characterPtr = perso;
initCharacterPointers(perso);
perso = &_persons[PER_MUNGO];
if (!(_globals->_party & PersonMask::pmMungo)) {
perso = &_persons[PER_DINA];
if (!(_globals->_party & PersonMask::pmDina)) {
perso = &_persons[PER_EVE];
if (!(_globals->_party & PersonMask::pmEve)) {
perso = &_persons[PER_GUARDS];
}
}
}
_globals->_dialogType = DialogType::dtDinoAction;
if (_globals->_curObjectId)
_globals->_dialogType = DialogType::dtDinoItem;
perso1(perso);
}
// Original name: morkus
void EdenGame::actionMorkus() {
perso_normal(&_persons[PER_MORKUS]);
}
void EdenGame::comment() {
perso_t *perso = &_persons[PER_DINA];
if (!(_globals->_party & PersonMask::pmDina)) {
perso = &_persons[PER_EVE];
if (!(_globals->_party & PersonMask::pmEve)) {
perso = &_persons[PER_GUARDS];
if (!(_globals->_party & PersonMask::pmThugg))
return;
}
}
_globals->_dialogType = DialogType::dtHint;
perso1(perso);
}
// Original name: adam
void EdenGame::actionAdam() {
resetScroll();
switch (_globals->_curObjectId) {
case Objects::obNone:
gotoPanel();
break;
case Objects::obRoot:
if (_globals->_roomNum == 2817
&& _globals->_phaseNum > 496 && _globals->_phaseNum < 512) {
bigphase1();
loseObject(Objects::obRoot);
_globals->_var100 = 0xFF;
quitMirror();
updateRoom(_globals->_roomNum);
removeFromParty(PER_ELOI);
_globals->_eventType = EventType::etEvent3;
showEvents();
waitEndSpeak();
if (_vm->shouldQuit())
return;
closeCharacterScreen();
removeFromParty(PER_ELOI);
_globals->_roomNum = 2818;
_globals->_areaNum = Areas::arWhiteArch;
_globals->_eventType = EventType::etEvent5;
_globals->_valleyVidNum = 0;
_globals->_mirrorEffect = 6; // CHECKME: Verify the value
_globals->_newMusicType = MusicType::mtNormal;
updateRoom(_globals->_roomNum);
} else {
_globals->_dialogType = DialogType::dtHint;
perso1(&_persons[PER_EVE]);
}
break;
case Objects::obShell:
_globals->_dialogType = DialogType::dtHint;
perso1(&_persons[PER_TAU]);
break;
case Objects::obFlute:
case Objects::obTrumpet:
if (_globals->_roomCharacterType) {
quitMirror();
updateRoom(_globals->_roomNum);
actionDino();
} else
comment();
break;
case Objects::obTablet1:
case Objects::obTablet2:
case Objects::obTablet3:
case Objects::obTablet4:
case Objects::obTablet5:
case Objects::obTablet6: {
if ((_globals->_partyOutside & PersonMask::pmDina)
&& _globals->_curObjectId == Objects::obTablet1 && _globals->_phaseNum == 370)
incPhase();
char *objvid = &_tabletView[(_globals->_curObjectId - Objects::obTablet1) * 2];
object_t *object = getObjectPtr(*objvid++);
int16 vid = 84;
if (!object->_count)
vid = *objvid;
_graphics->hideBars();
_specialTextMode = true;
_graphics->playHNM(vid);
_paletteUpdateRequired = true;
_globals->_mirrorEffect = 16; // CHECKME: Verify the value
_graphics->showBars();
gameToMirror(0);
}
break;
case Objects::obApple:
case Objects::obShroom:
case Objects::obBadShroom:
case Objects::obNest:
case Objects::obFullNest:
case Objects::obDrum:
if (_globals->_party & PersonMask::pmThugg) {
_globals->_dialogType = DialogType::dtHint;
perso1(&_persons[PER_GUARDS]);
}
break;
default:
comment();
}
}
// Original name: oui and init_oui
void EdenGame::setChoiceYes() {
_lastDialogChoice = true;
}
// Original name: non and init_non
void EdenGame::setChoiceNo() {
_lastDialogChoice = false;
}
// Original name: verif_oui
bool EdenGame::isAnswerYes() {
return _lastDialogChoice;
}
// Original name: SpcChampi
void EdenGame::specialMushroom(perso_t *perso) {
perso->_flags |= PersonFlags::pf10;
_globals->_areaPtr->_flags |= AreaFlags::afFlag2;
_globals->_curAreaFlags |= AreaFlags::afFlag2;
}
// Original name: SpcNidv
void EdenGame::specialEmptyNest(perso_t *perso) {
if (!isAnswerYes())
return;
perso->_flags |= PersonFlags::pf10;
_globals->_roomCharacterFlags |= PersonFlags::pf10;
_globals->_gameFlags |= GameFlags::gfFlag400;
if (_globals->_characterPtr == &_persons[PER_EVE]) {
_globals->_areaPtr->_flags |= AreaFlags::afFlag4;
_globals->_curAreaFlags |= AreaFlags::afFlag4;
perso->_flags |= PersonFlags::pfInParty;
_globals->_roomCharacterFlags |= PersonFlags::pfInParty;
placeVava(_globals->_areaPtr);
} else {
perso->_flags &= ~PersonFlags::pf10;
_globals->_roomCharacterFlags &= ~PersonFlags::pf10;
}
}
// Original name: SpcNido
void EdenGame::specialNestWithEggs(perso_t *perso) {
if (perso == &_persons[PER_GUARDS])
giveObject();
}
// Original name: SpcPomme
void EdenGame::specialApple(perso_t *perso) {
perso->_flags |= PersonFlags::pf10;
_globals->_areaPtr->_flags |= AreaFlags::afFlag8;
_globals->_curAreaFlags |= AreaFlags::afFlag8;
_globals->_gameFlags |= GameFlags::gfFlag200;
}
// Original name: SpcOr
void EdenGame::specialGold(perso_t *perso) {
if (!isAnswerYes())
return;
perso->_items = _curSpecialObject->_itemMask;
_globals->_roomPersoItems = _curSpecialObject->_itemMask;
perso->_flags |= PersonFlags::pf10;
perso->_flags &= ~PersonFlags::pfInParty;
perso->_targetLoc = 0;
_globals->_areaPtr->_flags |= AreaFlags::afGaveGold;
_globals->_curAreaFlags |= AreaFlags::afGaveGold;
if (_globals->_phaseNum == 226)
incPhase();
}
// Original name: SpcPrisme
void EdenGame::specialPrism(perso_t *perso) {
if (perso == &_persons[PER_DINA]) {
if (_globals->_partyOutside & PersonMask::pmMonk)
_globals->_gameFlags |= GameFlags::gfPrismAndMonk;
}
}
// Original name: SpcTalisman
void EdenGame::specialTalisman(perso_t *perso) {
if (perso == &_persons[PER_DINA])
addToParty(PER_DINA);
}
// Original name: SpcMasque
void EdenGame::specialMask(perso_t *perso) {
if (perso == &_persons[PER_BAMBOO]) {
dialautoon();
parlemoiNormalFlag = true;
}
}
// Original name: SpcSac
void EdenGame::specialBag(perso_t *perso) {
if (_globals->_textToken1 != 3)
return;
if (perso == &_persons[PER_KABUKA] || perso == &_persons[PER_MAMMI_3])
loseObject(_curSpecialObject->_id);
}
// Original name: SpcTrompet
void EdenGame::specialTrumpet(perso_t *perso) {
if (!isAnswerYes())
return;
_globals->_var54 = 4;
winObject(Objects::obTrumpet);
_globals->_drawFlags |= DrawFlags::drDrawInventory;
_closeCharacterDialog = true;
tyranDies(_globals->_roomCharacterPtr);
}
// Original name: SpcArmes
void EdenGame::specialWeapons(perso_t *perso) {
if (!isAnswerYes())
return;
perso->_powers = _curSpecialObject->_powerMask;
_globals->_roomCharacterPowers = _curSpecialObject->_powerMask;
giveObject();
}
// Original name: SpcInstru
void EdenGame::specialInstrument(perso_t *perso) {
if (!isAnswerYes())
return;
if (perso == &_persons[PER_MONK]) {
_globals->_partyInstruments &= ~1; //TODO: check me
if (_curSpecialObject->_id == Objects::obRing) {
_globals->_partyInstruments |= 1;
_globals->_monkGotRing++; //TODO: |= 1 ?
}
}
if (perso == &_persons[PER_GUARDS]) {
_globals->_partyInstruments &= ~2;
if (_curSpecialObject->_id == Objects::obDrum)
_globals->_partyInstruments |= 2;
}
perso->_powers = _curSpecialObject->_powerMask;
_globals->_curCharacterPowers = _curSpecialObject->_powerMask;
giveObject();
}
// Original name: SpcOeuf
void EdenGame::specialEgg(perso_t *perso) {
if (!isAnswerYes())
return;
_gameIcons[131]._cursorId &= ~0x8000;
_globals->_characterBackgroundBankIdx = 62;
dialautoon();
}
// Original name: TyranMeurt
void EdenGame::tyranDies(perso_t *perso) {
perso->_flags |= PersonFlags::pf80;
perso->_roomNum = 0;
removeInfo(_globals->_areaNum + ValleyNews::vnTyrannIn);
_globals->_roomCharacterType = 0;
_globals->_roomCharacterFlags = 0;
_globals->_chronoFlag = 0;
}
void EdenGame::specialObjects(perso_t *perso, char objid) {
struct SpecialObject {
int8 _characterType;
int8 _objectId;
void (EdenGame::*dispFct)(perso_t *perso);
};
static const SpecialObject kSpecialObjectActions[] = {
// persoType, objectId, dispFct
{ PersonFlags::pfType8, Objects::obShroom, &EdenGame::specialMushroom },
{ PersonFlags::pftTriceraptor, Objects::obNest, &EdenGame::specialEmptyNest },
{ PersonFlags::pfType0, Objects::obFullNest, &EdenGame::specialNestWithEggs },
{ PersonFlags::pftMosasaurus, Objects::obApple, &EdenGame::specialApple },
{ PersonFlags::pftVelociraptor, Objects::obGold, &EdenGame::specialGold },
{ PersonFlags::pfType0, Objects::obPrism, &EdenGame::specialPrism },
{ PersonFlags::pfType0, Objects::obTalisman, &EdenGame::specialTalisman },
{ PersonFlags::pfType2, Objects::obMaskOfDeath, &EdenGame::specialMask },
{ PersonFlags::pfType2, Objects::obMaskOfBonding, &EdenGame::specialMask },
{ PersonFlags::pfType2, Objects::obMaskOfBirth, &EdenGame::specialMask },
{ PersonFlags::pfType0, Objects::obBag, &EdenGame::specialBag },
{ PersonFlags::pfType2, Objects::obBag, &EdenGame::specialBag },
{ PersonFlags::pftTyrann, Objects::obTrumpet, &EdenGame::specialTrumpet },
{ PersonFlags::pftVelociraptor, Objects::obEyeInTheStorm, &EdenGame::specialWeapons },
{ PersonFlags::pftVelociraptor, Objects::obSkyHammer, &EdenGame::specialWeapons },
{ PersonFlags::pftVelociraptor, Objects::obFireInTheClouds, &EdenGame::specialWeapons },
{ PersonFlags::pftVelociraptor, Objects::obWithinAndWithout, &EdenGame::specialWeapons },
{ PersonFlags::pftVelociraptor, Objects::obEyeInTheCyclone, &EdenGame::specialWeapons },
{ PersonFlags::pftVelociraptor, Objects::obRiverThatWinds, &EdenGame::specialWeapons },
{ PersonFlags::pfType0, Objects::obTrumpet, &EdenGame::specialInstrument },
{ PersonFlags::pfType0, Objects::obDrum, &EdenGame::specialInstrument },
{ PersonFlags::pfType0, Objects::obRing, &EdenGame::specialInstrument },
{ PersonFlags::pfType0, Objects::obEgg, &EdenGame::specialEgg },
{ -1, -1, nullptr }
};
char characterType = perso->_flags & PersonFlags::pfTypeMask;
_curSpecialObject = &_objects[objid - 1];
for (const SpecialObject *spcObj = kSpecialObjectActions; spcObj->_characterType != -1; spcObj++) {
if (spcObj->_objectId == objid && spcObj->_characterType == characterType) {
(this->*spcObj->dispFct)(perso);
break;
}
}
}
void EdenGame::dialautoon() {
_globals->_iconsIndex = 4;
_globals->_autoDialog = true;
putObject();
}
void EdenGame::dialautooff() {
_globals->_iconsIndex = 0x10;
_globals->_autoDialog = false;
}
void EdenGame::follow() {
if (_globals->_roomCharacterType == PersonFlags::pfType12) {
debug("follow: hiding person %d", (int)(_globals->_roomCharacterPtr - _persons));
_globals->_roomCharacterPtr->_flags |= PersonFlags::pf80;
_globals->_roomCharacterPtr->_roomNum = 0;
_globals->_gameFlags |= GameFlags::gfFlag8;
_gameIcons[123]._objectId = 18;
_gameIcons[124]._objectId = 35;
_gameIcons[125]._cursorId &= ~0x8000;
_globals->_characterBackgroundBankIdx = 56;
} else
AddCharacterToParty();
}
void EdenGame::dialonfollow() {
_globals->_iconsIndex = 4;
_globals->_autoDialog = true;
follow();
}
// Original name: abortdial
void EdenGame::abortDialogue() {
_globals->_varF6++;
if (_globals->_roomCharacterType != PersonFlags::pftTriceraptor || _globals->_characterPtr != &_persons[PER_EVE])
return;
_globals->_areaPtr->_flags |= AreaFlags::afFlag4;
_globals->_curAreaFlags |= AreaFlags::afFlag4;
_globals->_roomCharacterPtr->_flags |= PersonFlags::pfInParty;
_globals->_roomCharacterFlags |= PersonFlags::pfInParty;
placeVava(_globals->_areaPtr);
}
void EdenGame::subHandleNarrator() {
_globals->_varF2 &= ~1; //TODO: check me
if (_globals->_narratorSequence > 50 && _globals->_narratorSequence <= 80)
_globals->_endGameFlag = 50;
if (_globals->_narratorSequence == 3)
setChrono(1200);
_globals->_narratorSequence = 0;
}
// Original name: narrateur
void EdenGame::handleNarrator() {
if (!(_globals->_displayFlags & DisplayFlags::dfFlag1))
return;
if (!_globals->_narratorSequence) {
if (_globals->_var6A == _globals->_var69) {
subHandleNarrator();
return;
}
narratorBuildCitadel();
}
_globals->_varF5 |= 0x80;
_globals->_varF2 &= ~1; //TODO: check me
_globals->_characterPtr = &_persons[PER_UNKN_156];
_globals->_var60 = 0;
_globals->_eventType = 0;
_globals->_var103 = 69;
if (dialogEvent(&_persons[PER_UNKN_156])) {
_globals->_narratorDialogPtr = _globals->_dialogPtr;
dialautoon();
_globals->_varF2 |= 1;
waitEndSpeak();
if (_vm->shouldQuit())
return;
endCharacterSpeech();
while (dialoscansvmas(_globals->_narratorDialogPtr)) {
_globals->_narratorDialogPtr = _globals->_dialogPtr;
waitEndSpeak();
if (_vm->shouldQuit())
return;
endCharacterSpeech();
}
_globals->_narratorDialogPtr = _globals->_dialogPtr;
_globals->_mirrorEffect = 0;
_globals->_var103 = 0;
closeCharacterScreen();
placeVava(_globals->_areaPtr);
if (_globals->_narratorSequence == 8)
deplaval(134);
}
_globals->_var103 = 0;
if (_globals->_narratorSequence == 10) {
addToParty(PER_ELOI);
addToParty(PER_EVE);
addToParty(PER_MONK);
addToParty(PER_GUARDS);
removeFromParty(PER_MUNGO);
_globals->_eloiHaveNews = 0;
deplaval(139);
}
_globals->_eventType = EventType::etEventD;
showEvents();
_globals->_varF5 &= ~0x80;
subHandleNarrator();
}
// Original name: vrf_phrases_file
void EdenGame::checkPhraseFile() {
int16 num = 3;
if (_globals->_dialogPtr < (Dialog *)getElem(_gameDialogs, 48))
num = 1;
else if (_globals->_dialogPtr < (Dialog *)getElem(_gameDialogs, 128))
num = 2;
_globals->_textBankIndex = num;
if (_globals->_prefLanguage)
num += (_globals->_prefLanguage - 1) * 3;
if (num == _lastPhrasesFile)
return;
_lastPhrasesFile = num;
num += 404;
loadRawFile(num, _gamePhrases);
verifh(_gamePhrases);
}
// Original name: gettxtad
byte *EdenGame::getPhrase(int16 id) {
checkPhraseFile();
return (byte *)getElem(_gamePhrases, id - 1);
}
// Original name: gotocarte
void EdenGame::actionGotoMap() {
Goto *go = &_gotos[_curSpot2->_objectId];
endCharacterSpeech();
byte newArea = go->_areaNum;
_globals->_newRoomNum = (go->_areaNum << 8) | 1;
_globals->_newLocation = 1;
_globals->_prevLocation = _globals->_roomNum & 0xFF;
char curArea = _globals->_roomNum >> 8;
if (curArea == go->_areaNum)
newArea = 0;
else {
for (; go->_curAreaNum != 0xFF; go++) {
if (go->_curAreaNum == curArea)
break;
}
if (go->_areaNum == 0xFF)
return;
}
_globals->_eventType = EventType::etGotoArea | newArea;
setChoiceYes();
showEvents1();
waitEndSpeak();
if (_vm->shouldQuit())
return;
closeCharacterScreen();
if (isAnswerYes())
gotoPlace(go);
}
void EdenGame::record() {
if (_globals->_curObjectId)
return;
if (_globals->_characterPtr >= &_persons[PER_UNKN_18C])
return;
if (_globals->_eventType == EventType::etEventE || _globals->_eventType >= EventType::etGotoArea)
return;
for (tape_t *tape = _tapes; tape != _tapes + MAX_TAPES; tape++) {
if (tape->_textNum == _globals->_textNum)
return;
}
tape_t *tape = _tapes;
for (int16 i = 0; i < MAX_TAPES - 1; i++) {
tape->_textNum = tape[+1]._textNum;
tape->_perso = tape[+1]._perso;
tape->_party = tape[+1]._party;
tape->_roomNum = tape[+1]._roomNum;
tape->_backgroundBankNum = tape[+1]._backgroundBankNum;
tape->_dialog = tape[+1]._dialog;
tape++;
}
perso_t *perso = _globals->_characterPtr;
if (perso == &_persons[PER_EVE])
perso = _globals->_phaseNum >= 352 ? &_persons[PER_UNKN_372]
: &_persons[PER_UNKN_402];
tape->_textNum = _globals->_textNum;
tape->_perso = perso;
tape->_party = _globals->_party;
tape->_roomNum = _globals->_roomNum;
tape->_backgroundBankNum = _globals->_roomBackgroundBankNum;
tape->_dialog = _globals->_dialogPtr;
}
bool EdenGame::dial_scan(Dialog *dial) {
if (_globals->_numGiveObjs) {
if (!(_globals->_displayFlags & DisplayFlags::dfFlag2))
showObjects();
_globals->_numGiveObjs = 0;
}
_globals->_dialogPtr = dial;
vavapers();
_globals->_sentenceBufferPtr = _sentenceBuffer;
byte hidx, lidx;
uint16 mask = 0;
bool skipFl = false;
for (;; _globals->_dialogPtr++) {
for (;; _globals->_dialogPtr++) {
if (_globals->_dialogPtr->_flags == -1 && _globals->_dialogPtr->_condNumLow == -1)
return false;
byte flags = _globals->_dialogPtr->_flags;
_globals->_dialogFlags = flags;
if (!(flags & DialogFlags::dfSpoken) || (flags & DialogFlags::dfRepeatable)) {
hidx = (_globals->_dialogPtr->_textCondHiMask >> 6) & 3;
lidx = _globals->_dialogPtr->_condNumLow;
if (flags & 0x10)
hidx |= 4;
if (testCondition(((hidx << 8) | lidx) & 0x7FF))
break;
} else {
if (flags & _dialogSkipFlags)
continue;
hidx = (_globals->_dialogPtr->_textCondHiMask >> 6) & 3;
lidx = _globals->_dialogPtr->_condNumLow;
if (flags & 0x10)
hidx |= 4;
if (testCondition(((hidx << 8) | lidx) & 0x7FF))
break;
}
}
char bidx = (_globals->_dialogPtr->_textCondHiMask >> 2) & 0xF;
if (!bidx) {
skipFl = true;
break;
}
mask = (_globals->_party | _globals->_partyOutside) & (1 << (bidx - 1));
if (mask)
break;
}
if (!skipFl) {
perso_t *perso;
for (perso = _persons; !(perso->_partyMask == mask && perso->_roomNum == _globals->_roomNum); perso++)
; //Find matching
_globals->_characterPtr = perso;
initCharacterPointers(perso);
no_perso();
}
hidx = _globals->_dialogPtr->_textCondHiMask;
lidx = _globals->_dialogPtr->_textNumLow;
_globals->_textNum = ((hidx << 8) | lidx) & 0x3FF;
if (_globals->_sentenceBufferPtr != _sentenceBuffer) {
for (int16 i = 0; i < 32; i++)
SysBeep(1);
} else
my_bulle();
if (!dword_30B04) {
typedef void (EdenGame::*TalkSubject)();
static const TalkSubject talk_subject[] = {
&EdenGame::setChoiceYes,
&EdenGame::setChoiceNo,
&EdenGame::handleEloiDeparture,
&EdenGame::dialautoon,
&EdenGame::dialautooff,
&EdenGame::characterStayHere,
&EdenGame::follow,
&EdenGame::citadelle,
&EdenGame::dialonfollow,
&EdenGame::abortDialogue,
&EdenGame::incPhase,
&EdenGame::bigphase,
&EdenGame::giveObject,
&EdenGame::selectZone,
&EdenGame::lostObject
};
char pnum = _globals->_dialogPtr->_flags & 0xF;
if (pnum)
(this->*talk_subject[pnum - 1])();
_globals->_var60 = 1;
_globals->_dialogPtr->_flags |= DialogFlags::dfSpoken;
_globals->_dialogPtr++;
}
if (_globals->_dialogType != DialogType::dtInspect) {
record();
getDataSync();
showCharacter();
persovox();
}
return true;
}
bool EdenGame::dialoscansvmas(Dialog *dial) {
byte oldFlag = _dialogSkipFlags;
_dialogSkipFlags = DialogFlags::df20;
bool res = dial_scan(dial);
_dialogSkipFlags = oldFlag;
return res;
}
byte *EdenGame::getGameDialogs() {
return _gameDialogs;
}
// Original name: dialo_even
bool EdenGame::dialogEvent(perso_t *perso) {
_globals->_characterPtr = perso;
int num = (perso->_id << 3) | DialogType::dtEvent;
Dialog *dial = (Dialog *)getElem(_gameDialogs, num);
bool retVal = dialoscansvmas(dial);
_globals->_lastDialogPtr = nullptr;
parlemoiNormalFlag = false;
return retVal;
}
// Original name: stay_here
void EdenGame::characterStayHere() {
if (_globals->_characterPtr == &_persons[PER_DINA] && _globals->_roomNum == 260)
_globals->_gameFlags |= GameFlags::gfFlag1000;
removeCharacterFromParty();
}
// Original name: mort
void EdenGame::endDeath(int16 vid) {
_graphics->hideBars();
_graphics->playHNM(vid);
_graphics->fadeToBlack(2);
CLBlitter_FillScreenView(0);
CLBlitter_FillView(_graphics->getMainView(), 0);
_graphics->showBars();
_globals->_narratorSequence = 51;
_globals->_newMusicType = MusicType::mtNormal;
musique();
musicspy();
}
// Original name: evenchrono
void EdenGame::chronoEvent() {
if (!(_globals->_displayFlags & DisplayFlags::dfFlag1))
return;
uint16 oldGameTime = _globals->_gameTime;
_currentTime = _vm->_timerTicks / 100;
_globals->_gameTime = _currentTime;
if (_globals->_gameTime <= oldGameTime)
return;
addTime(5);
if (!(_globals->_chronoFlag & 1))
return;
_globals->_chrono -= 200;
if (_globals->_chrono == 0)
_globals->_chronoFlag |= 2;
if (!(_globals->_chronoFlag & 2))
return;
_globals->_chronoFlag = 0;
_globals->_chrono = 0;
if (_globals->_roomCharacterType == PersonFlags::pftTyrann) {
int16 vid = 272;
if (_globals->_curRoomFlags & 0xC0) {
vid += 2;
if ((_globals->_curRoomFlags & 0xC0) != 0x80) {
vid += 2;
endDeath(vid);
return;
}
}
if (_globals->_areaNum == Areas::arUluru || _globals->_areaNum == Areas::arTamara)
endDeath(vid);
else
endDeath(vid + 1);
return;
}
if (_globals->_roomNum == 2817) {
addToParty(PER_ELOI);
_globals->_gameFlags |= GameFlags::gfFlag40;
dialautoon();
} else
handleEloiReturn();
_globals->_eventType = EventType::etEvent10;
showEvents();
}
// Original name: chronoon
void EdenGame::setChrono(int16 t) {
_globals->_chrono = t;
_globals->_chronoFlag = 1;
}
void EdenGame::wait(int howlong) {
int t = g_system->getMillis();
for (int t2 = t; t2 - t < howlong; t2 = g_system->getMillis())
g_system->delayMillis(10); // waste time
}
//////
// Original name: ajouinfo
void EdenGame::addInfo(byte info) {
byte idx = _globals->_nextInfoIdx;
if (_persons[PER_ELOI]._roomNum)
info |= 0x80;
_infoList[idx] = info;
if (idx == _globals->_lastInfoIdx)
_globals->_lastInfo = info;
idx++;
if (idx == 16)
idx = 0;
_globals->_nextInfoIdx = idx;
}
void EdenGame::unlockInfo() {
for (byte idx = 0; idx < 16; idx++) {
if (_infoList[idx] != 0xFF)
_infoList[idx] &= ~0x80;
}
_globals->_lastInfo &= ~0x80;
}
void EdenGame::nextInfo() {
do {
byte idx = _globals->_lastInfoIdx;
_infoList[idx] = 0;
idx++;
if (idx == 16)
idx = 0;
_globals->_lastInfoIdx = idx;
_globals->_lastInfo = _infoList[idx];
} while (_globals->_lastInfo == 0xFF);
}
// Original name: delinfo
void EdenGame::removeInfo(byte info) {
for (byte idx = 0; idx < 16; idx++) {
if ((_infoList[idx] & ~0x80) == info) {
_infoList[idx] = 0xFF;
if (idx == _globals->_lastInfoIdx)
nextInfo();
break;
}
}
}
void EdenGame::updateInfoList() {
for (int idx = 0; idx < 16; idx++)
_infoList[idx] = 0;
}
void EdenGame::initGlobals() {
_gameIcons[16]._cursorId |= 0x8000;
_globals->_areaNum = Areas::arMo;
_globals->_areaVisitCount = 1;
_globals->_menuItemIdLo = 0;
_globals->_menuItemIdHi = 0;
_globals->_randomNumber = 0;
_globals->_gameTime = 0;
_globals->_gameDays = 0;
_globals->_chrono = 0;
_globals->_eloiDepartureDay = 0;
_globals->_roomNum = 259;
_globals->_newRoomNum = 0;
_globals->_phaseNum = 0;
_globals->_metPersonsMask1 = 0;
_globals->_party = 0;
_globals->_partyOutside = 0;
_globals->_metPersonsMask2 = 0;
_globals->_phaseActionsCount = 0;
_globals->_curAreaFlags = 0;
_globals->_curItemsMask = 0;
_globals->_curPowersMask = 0;
_globals->_curPersoItems = 0;
_globals->_curCharacterPowers = 0;
_globals->_wonItemsMask = 0;
_globals->_wonPowersMask = 0;
_globals->_stepsToFindAppleFast = 0;
_globals->_stepsToFindAppleNormal = 0;
_globals->_roomPersoItems = 0;
_globals->_roomCharacterPowers = 0;
_globals->_gameFlags = GameFlags::gfNone;
_globals->_curVideoNum = 0;
_globals->_morkusSpyVideoNum1 = 89;
_globals->_morkusSpyVideoNum2 = 88;
_globals->_morkusSpyVideoNum3 = 83;
_globals->_morkusSpyVideoNum4 = 94;
_globals->_newMusicType = MusicType::mtDontChange;
_globals->_var43 = 0;
_globals->_videoSubtitleIndex = 0;
_globals->_partyInstruments = 0;
_globals->_monkGotRing = 0;
_globals->_chronoFlag = 0;
_globals->_curRoomFlags = 0;
_globals->_endGameFlag = 0;
_globals->_lastInfo = 0;
_globals->_autoDialog = false;
_globals->_worldTyranSighted = 0;
_globals->_var4D = 0;
_globals->_var4E = 0;
_globals->_worldGaveGold = 0;
_globals->_worldHasTriceraptors = 0;
_globals->_worldHasVelociraptors = 0;
_globals->_worldHasTyran = 0;
_globals->_var53 = 0;
_globals->_var54 = 0;
_globals->_var55 = 0;
_globals->_gameHours = 0;
_globals->_textToken1 = 0;
_globals->_textToken2 = 0;
_globals->_eloiHaveNews = 0;
_globals->_dialogFlags = 0;
_globals->_curAreaType = 0;
_globals->_curCitadelLevel = 0;
_globals->_newLocation = 0;
_globals->_prevLocation = 0;
_globals->_curPersoFlags = 0;
_globals->_var60 = 0;
_globals->_eventType = EventType::etEvent5;
_globals->_var62 = 0;
_globals->_curObjectId = 0;
_globals->_curObjectFlags = 0;
_globals->_var65 = 1;
_globals->_roomCharacterType = 0;
_globals->_roomCharacterFlags = 0;
_globals->_narratorSequence = 0;
_globals->_var69 = 0;
_globals->_var6A = 0;
_globals->_frescoNumber = 0;
_globals->_var6C = 0;
_globals->_var6D = 0;
_globals->_labyrinthDirections = 0;
_globals->_labyrinthRoom = 0;
_globals->_curCharacterAnimPtr = nullptr;
_globals->_characterImageBank = 0;
_globals->_roomImgBank = 0;
_globals->_characterBackgroundBankIdx = 55;
_globals->_varD4 = 0;
_globals->_frescoeWidth = 0;
_globals->_frescoeImgBank = 0;
_globals->_varDA = 0;
_globals->_varDC = 0;
_globals->_roomBaseX = 0;
_globals->_varE0 = 0;
_globals->_dialogType = DialogType::dtTalk;
_globals->_varE4 = 0;
_globals->_currMusicNum = 0;
_globals->_textNum = 0;
_globals->_travelTime = 0;
_globals->_varEC = 0;
_globals->_displayFlags = DisplayFlags::dfFlag1;
_globals->_oldDisplayFlags = 1;
_globals->_drawFlags = 0;
_globals->_varF1 = 0;
_globals->_varF2 = 0;
_globals->_menuFlags = 0;
_globals->_varF5 = 0;
_globals->_varF6 = 0;
_globals->_varF7 = 0;
_globals->_varF8 = 0;
_globals->_varF9 = 0;
_globals->_varFA = 0;
_globals->_animationFlags = 0;
_globals->_giveObj1 = 0;
_globals->_giveObj2 = 0;
_globals->_giveObj3 = 0;
_globals->_var100 = 0;
_globals->_roomVidNum = 0;
_globals->_mirrorEffect = 0;
_globals->_var103 = 0;
_globals->_roomBackgroundBankNum = 0;
_globals->_valleyVidNum = 0;
_globals->_updatePaletteFlag = 0;
_globals->_inventoryScrollPos = 0;
_globals->_objCount = 0;
_globals->_textBankIndex = 69;
_globals->_citadelAreaNum = 0;
_globals->_var113 = 0;
_globals->_lastPlaceNum = 0;
_globals->_dialogPtr = nullptr;
_globals->_tapePtr = _tapes;
_globals->_nextDialogPtr = nullptr;
_globals->_narratorDialogPtr = nullptr;
_globals->_lastDialogPtr = nullptr;
_globals->_nextRoomIcon = nullptr;
_globals->_sentenceBufferPtr = nullptr;
_globals->_roomPtr = nullptr;
_globals->_areaPtr = nullptr;
_globals->_lastAreaPtr = nullptr;
_globals->_curAreaPtr = nullptr;
_globals->_citaAreaFirstRoom = nullptr;
_globals->_characterPtr = nullptr;
_globals->_roomCharacterPtr = nullptr;
_globals->_lastInfoIdx = 0;
_globals->_nextInfoIdx = 0;
_globals->_iconsIndex = 16;
_globals->_persoSpritePtr = nullptr;
_globals->_numGiveObjs = 0;
_graphics->initRects();
_graphics->initGlobals();
_graphics->setSavedUnderSubtitles(false);
}
// Original name: closesalle
void EdenGame::closeRoom() {
if (_globals->_displayFlags & DisplayFlags::dfPanable) {
_globals->_displayFlags &= ~DisplayFlags::dfPanable;
resetScroll();
}
}
// Original name: aflieu
void EdenGame::displayPlace() {
no_perso();
if (!_vm->shouldQuit()) {
_globals->_iconsIndex = 16;
_globals->_autoDialog = false;
}
_globals->_nextRoomIcon = &_gameIcons[_roomIconsBase];
_graphics->displayRoom();
_paletteUpdateRequired = true;
}
// Original name: loadsal
void EdenGame::loadPlace(int16 num) {
if (num == _globals->_lastPlaceNum)
return;
_globals->_lastPlaceNum = num;
loadRawFile(num + 419, _placeRawBuf);
}
byte EdenGame::getActionCursor(byte value) {
return _actionCursors[value];
}
byte *EdenGame::getPlaceRawBuf() {
return _placeRawBuf;
}
void EdenGame::specialoutside() {
if (_globals->_lastAreaPtr->_type == AreaType::atValley && (_globals->_party & PersonMask::pmLeader))
perso_ici(5);
}
void EdenGame::specialout() {
if (_globals->_gameDays - _globals->_eloiDepartureDay > 2) {
if (checkEloiReturn())
handleEloiReturn();
}
if (_globals->_phaseNum >= 32 && _globals->_phaseNum < 48) {
if (_globals->_newLocation == 9 || _globals->_newLocation == 4 || _globals->_newLocation == 24) {
_persons[PER_ELOI]._roomNum = 263;
return;
}
}
if ((_globals->_phaseNum == 434) && (_globals->_newLocation == 5)) {
removeFromParty(PER_JABBER);
_persons[PER_JABBER]._roomNum = 264;
return;
}
if (_globals->_phaseNum < 400) {
if ((_globals->_gameFlags & GameFlags::gfFlag4000) && _globals->_prevLocation == 1
&& (_globals->_party & PersonMask::pmEloi) && _globals->_curAreaType == AreaType::atValley)
handleEloiDeparture();
}
if (_globals->_phaseNum == 386) {
if (_globals->_prevLocation == 1
&& (_globals->_party & PersonMask::pmEloi) && _globals->_areaNum == Areas::arCantura)
handleEloiDeparture();
}
}
void EdenGame::specialin() {
if (!(_globals->_party & PersonMask::pmEloi) && (_globals->_partyOutside & PersonMask::pmEloi) && (_globals->_roomNum & 0xFF) == 1) {
addToParty(PER_ELOI);
_globals->_eloiHaveNews = 1;
}
if (_globals->_roomNum == 288)
_globals->_gameFlags |= GameFlags::gfFlag100 | GameFlags::gfFlag2000;
if (_globals->_roomNum == 3075 && _globals->_phaseNum == 546) {
incPhase();
if (_globals->_curItemsMask & 0x2000) { // Morkus' tablet
_graphics->hideBars();
_graphics->playHNM(92);
_gameRooms[129]._exits[0] = 0;
_gameRooms[129]._exits[2] = 1;
_globals->_roomNum = 3074;
_persons[PER_MUNGO]._roomNum = 3074;
_globals->_eventType = EventType::etEvent5;
updateRoom(_globals->_roomNum);
return;
}
_globals->_narratorSequence = 53;
}
if (_globals->_roomNum == 1793 && _globals->_phaseNum == 336)
handleEloiDeparture();
if (_globals->_roomNum == 259 && _globals->_phaseNum == 129)
_globals->_narratorSequence = 12;
if (_globals->_roomNum >= 289 && _globals->_roomNum < 359)
_globals->_labyrinthDirections = _labyrinthPath[(_globals->_roomNum & 0xFF) - 33];
if (_globals->_roomNum == 305 && _globals->_prevLocation == 103)
_globals->_gameFlags &= ~GameFlags::gfFlag2000;
if (_globals->_roomNum == 304 && _globals->_prevLocation == 105)
_globals->_gameFlags &= ~GameFlags::gfFlag2000;
if (_globals->_phaseNum < 226) {
if (_globals->_roomNum == 842)
_globals->_gameFlags |= GameFlags::gfFlag2;
if (_globals->_roomNum == 1072)
_globals->_gameFlags |= GameFlags::gfFlag4;
if (_globals->_roomNum == 1329)
_globals->_gameFlags |= GameFlags::gfFlag8000;
}
}
void EdenGame::animpiece() {
Room *room = _globals->_roomPtr;
if (_globals->_roomVidNum && _globals->_var100 != 0xFF) {
if (_globals->_valleyVidNum || !room->_level || (room->_flags & RoomFlags::rfHasCitadel)
|| room->_level == _globals->_var100) {
_graphics->hideBars();
_globals->_updatePaletteFlag = 16;
if (!(_globals->_narratorSequence & 0x80)) //TODO: bug? !() @ 100DC
_globals->_mirrorEffect = 0;
if (!_graphics->getFade())
_graphics->setFade(room->_flags & RoomFlags::rf02);
_graphics->playHNM(_globals->_roomVidNum);
return;
}
}
_globals->_varF1 &= ~RoomFlags::rf04;
}
void EdenGame::getdino(Room *room) {
assert(tab_2CEF0[4] == 0x25);
room->_flags &= ~0xC;
for (perso_t *perso = &_persons[PER_UNKN_18C]; perso->_roomNum != 0xFFFF; perso++) {
if (perso->_flags & PersonFlags::pf80)
continue;
if (perso->_roomNum != _globals->_roomNum)
continue;
byte persoType = perso->_flags & PersonFlags::pfTypeMask;
if (persoType == PersonFlags::pftVelociraptor)
removeInfo(_globals->_citadelAreaNum + ValleyNews::vnVelociraptorsIn);
if (persoType == PersonFlags::pftTriceraptor)
removeInfo(_globals->_citadelAreaNum + ValleyNews::vnTriceraptorsIn);
perso->_flags |= PersonFlags::pf20;
int16 *tab = tab_2CF70;
if (_globals->_areaNum != Areas::arUluru && _globals->_areaNum != Areas::arTamara)
tab = tab_2CEF0;
byte r27 = (room->_flags & 0xC0) >> 2; //TODO: check me (like pc)
persoType = perso->_flags & PersonFlags::pfTypeMask;
if (persoType == PersonFlags::pftTyrann)
persoType = 13;
r27 |= (persoType & 7) << 1; //TODO: check me 13 & 7 = ???
tab += r27;
_globals->_roomVidNum = *tab++;
int16 bank = *tab;
if (bank & 0x8000) {
bank &= ~0x8000;
room->_flags |= RoomFlags::rf08;
}
room->_flags |= RoomFlags::rf04 | RoomFlags::rf02;
_globals->_roomImgBank = bank;
break;
}
}
// Original name: getsalle
Room *EdenGame::getRoom(int16 loc) { //TODO: byte?
debug("get room for %X, starting from %d, looking for %X", loc, _globals->_areaPtr->_firstRoomIdx, _globals->_partyOutside);
Room *room = &_gameRooms[_globals->_areaPtr->_firstRoomIdx];
loc &= 0xFF;
for (;; room++) {
for (; room->_location != loc; room++) {
if (room->_id == 0xFF)
return nullptr;
}
if (_globals->_partyOutside == room->_party || room->_party == 0xFFFF)
break;
}
debug("found room: party = %X, bank = %X", room->_party, room->_bank);
_globals->_roomImgBank = room->_bank;
_globals->_labyrinthRoom = 0;
if (_globals->_roomImgBank > 104 && _globals->_roomImgBank <= 112)
_globals->_labyrinthRoom = _globals->_roomImgBank - 103;
if (_globals->_valleyVidNum)
_globals->_roomVidNum = _globals->_valleyVidNum;
else
_globals->_roomVidNum = room->_video;
if ((room->_flags & 0xC0) == RoomFlags::rf40 || (room->_flags & RoomFlags::rf01))
getdino(room);
if (room->_flags & RoomFlags::rfHasCitadel) {
removeInfo(_globals->_areaNum + ValleyNews::vnCitadelLost);
removeInfo(_globals->_areaNum + ValleyNews::vnTyrannIn);
removeInfo(_globals->_areaNum + ValleyNews::vnTyrannLost);
removeInfo(_globals->_areaNum + ValleyNews::vnVelociraptorsLost);
}
if (istyran(_globals->_roomNum))
_globals->_gameFlags |= GameFlags::gfFlag10;
else
_globals->_gameFlags &= ~GameFlags::gfFlag10;
return room;
}
// Original name: initlieu
void EdenGame::initPlace(int16 roomNum) {
_globals->_gameFlags |= GameFlags::gfFlag4000;
_gameIcons[18]._cursorId |= 0x8000;
_globals->_lastAreaPtr = _globals->_areaPtr;
_globals->_areaPtr = &_areasTable[((roomNum >> 8) & 0xFF) - 1];
Area *area = _globals->_areaPtr;
area->_visitCount++;
_globals->_areaVisitCount = area->_visitCount;
_globals->_curAreaFlags = area->_flags;
_globals->_curAreaType = area->_type;
_globals->_curCitadelLevel = area->_citadelLevel;
if (_globals->_curAreaType == AreaType::atValley)
_gameIcons[18]._cursorId &= ~0x8000;
loadPlace(area->_placeNum);
}
void EdenGame::maj2() {
displayPlace();
assert(_vm->_screenView->_pitch == 320);
if (_globals->_roomNum == 273 && _globals->_prevLocation == 18)
_globals->_mirrorEffect = 1;
if (_globals->_eventType == EventType::etEventC) {
drawTopScreen();
showObjects();
}
FRDevents();
assert(_vm->_screenView->_pitch == 320);
bool r30 = false;
if (_globals->_curAreaType == AreaType::atValley && !(_globals->_displayFlags & DisplayFlags::dfPanable))
r30 = true;
//TODO: ^^ inlined func?
if (_globals->_mirrorEffect || _globals->_var103)
display();
else if (_globals->_varF1 == (RoomFlags::rf40 | RoomFlags::rf04 | RoomFlags::rf01)) {
_graphics->drawBlackBars();
_graphics->displayEffect1();
} else if (_globals->_varF1 && !(_globals->_varF1 & RoomFlags::rf04) && !r30) {
if (!(_globals->_displayFlags & DisplayFlags::dfPanable))
_graphics->drawBlackBars();
else if (_globals->_valleyVidNum)
_graphics->drawBlackBars();
_graphics->displayEffect1();
} else if (r30 && !(_globals->_varF1 & RoomFlags::rf04))
_graphics->effetpix();
else
afficher128();
musique();
if (_globals->_eventType != EventType::etEventC) {
drawTopScreen();
showObjects();
}
_graphics->showBars();
showEvents();
_globals->_labyrinthDirections = 0;
specialin();
}
// Original name: majsalle1
void EdenGame::updateRoom1(int16 roomNum) {
Room *room = getRoom(roomNum & 0xFF);
_globals->_roomPtr = room;
debug("DrawRoom: room 0x%X, arg = 0x%X", _globals->_roomNum, roomNum);
_globals->_curRoomFlags = room->_flags;
_globals->_varF1 = room->_flags;
animpiece();
_globals->_var100 = 0;
maj2();
}
// Original name: maj_salle
void EdenGame::updateRoom(uint16 roomNum) {
setCharacterHere();
updateRoom1(roomNum);
}
// Original name: initbuf
void EdenGame::allocateBuffers() {
#define ALLOC(ptr, size, typ) if (!((ptr) = (typ*)malloc(size))) _bufferAllocationErrorFl = true;
ALLOC(_gameRooms, 0x4000, Room);
ALLOC(_gameIcons, 0x4000, Icon);
ALLOC(_bankDataBuf, 0x10000, byte);
ALLOC(_globals, sizeof(*_globals), global_t);
ALLOC(_placeRawBuf, 2048, byte);
ALLOC(_gameConditions, 0x4800, byte);
ALLOC(_gameDialogs, 0x2800, byte);
ALLOC(_gamePhrases, 0x10000, byte);
ALLOC(_mainBankBuf, 0x9400, byte);
ALLOC(_glowBuffer, 0x2800, byte);
ALLOC(_gameFont, 0x900, byte);
ALLOC(_gameLipsync, 0x205C, byte);
ALLOC(_musicBuf, kMaxMusicSize, byte);
#undef ALLOC
}
void EdenGame::freebuf() {
delete(_bigfileHeader);
_bigfileHeader = nullptr;
free(_gameRooms);
free(_gameIcons);
free(_bankDataBuf);
free(_globals);
free(_placeRawBuf);
free(_gameConditions);
free(_gameDialogs);
free(_gamePhrases);
free(_mainBankBuf);
free(_glowBuffer);
free(_gameFont);
free(_gameLipsync);
free(_musicBuf);
if (_soundAllocated) {
free(_voiceSamplesBuffer);
_voiceSamplesBuffer = nullptr;
_soundAllocated = false;
}
}
void EdenGame::EmergencyExit() {
SysBeep(1);
}
void EdenGame::stopMusic() {
_musicChannel->stop();
}
void EdenGame::run() {
_invIconsCount = (_vm->getPlatform() == Common::kPlatformMacintosh) ? 9 : 11;
_roomIconsBase = _invIconsBase + _invIconsCount;
word_378CE = 0;
CRYOLib_ManagersInit();
_musicChannel = new CSoundChannel(_vm->_mixer, 11025, false);
_voiceChannel = new CSoundChannel(_vm->_mixer, 11025, false);
_graphics = new EdenGraphics(this);
_graphics->setSavedUnderSubtitles(false);
allocateBuffers();
openbigfile();
_graphics->openWindow();
loadpermfiles();
if (!_bufferAllocationErrorFl) {
LostEdenMac_InitPrefs();
if (_vm->getPlatform() == Common::kPlatformMacintosh)
initCubeMac();
else
initCubePC();
while (!_quitFlag2) {
initGlobals();
_quitFlag3 = false;
_normalCursor = true;
_torchCursor = false;
_graphics->setCursKeepPos(-1,-1);
if (!_gameLoaded)
intro();
edmain();
startmusique(1);
_graphics->drawBlackBars();
display();
_graphics->fadeToBlack(3);
_graphics->clearScreen();
_graphics->playHNM(95);
if (_globals->_endGameFlag == 50) {
loadrestart();
_gameLoaded = false;
}
fademusica0(2);
_musicChannel->stop();
_musicPlayingFlag = false;
_musicEnabledFlag = false;
}
if (_vm->getPlatform() == Common::kPlatformMacintosh)
DELETEcharge_objet_mob(&_cube);
// LostEdenMac_SavePrefs();
}
_graphics->fadeToBlack(4);
delete _voiceChannel;
delete _musicChannel;
delete _graphics;
closebigfile();
freebuf();
CRYOLib_ManagersDone();
}
void EdenGame::edmain() {
//TODO
enterGame();
while (!_bufferAllocationErrorFl && !_quitFlag3 && _globals->_endGameFlag != 50) {
if (!_gameStarted) {
// if in demo mode, reset game after a while
_demoCurrentTicks = _vm->_timerTicks;
if (_demoCurrentTicks - _demoStartTicks > 3000) {
_graphics->rundcurs();
display();
fademusica0(2);
_graphics->fadeToBlack(3);
CLBlitter_FillScreenView(0);
CLBlitter_FillView(_graphics->getMainView(), 0);
_musicChannel->stop();
_musicPlayingFlag = false;
_musicEnabledFlag = false;
intro();
enterGame();
}
}
_graphics->rundcurs();
musicspy();
FRDevents();
handleNarrator();
chronoEvent();
if (_globals->_drawFlags & DrawFlags::drDrawInventory)
showObjects();
if (_globals->_drawFlags & DrawFlags::drDrawTopScreen)
drawTopScreen();
if ((_globals->_displayFlags & DisplayFlags::dfPanable) && (_globals->_displayFlags != DisplayFlags::dfPerson))
scrollPanel();
if ((_globals->_displayFlags & DisplayFlags::dfMirror) && (_globals->_displayFlags != DisplayFlags::dfPerson))
scrollMirror();
if ((_globals->_displayFlags & DisplayFlags::dfFrescoes) && (_globals->_displayFlags != DisplayFlags::dfPerson))
scrollFrescoes();
if (_globals->_displayFlags & DisplayFlags::dfFlag2)
noclicpanel();
if (_animationActive)
animCharacter();
updateCursor();
display();
}
}
void EdenGame::intro() {
if (_vm->getPlatform() == Common::kPlatformMacintosh) {
// Play intro videos in HQ
_graphics->playHNM(2012);
_graphics->playHNM(171);
CLBlitter_FillScreenView(0);
_specialTextMode = false;
_graphics->playHNM(2001);
} else {
if (_vm->isDemo()) {
_graphics->playHNM(171); // Virgin logo
_graphics->playHNM(98); // Cryo logo
}
else {
_graphics->playHNM(98); // Cryo logo
_graphics->playHNM(171); // Virgin logo
}
CLBlitter_FillScreenView(0);
_specialTextMode = false;
startmusique(2); // INTRO.MUS is played during intro video
_graphics->playHNM(170); // Intro video
}
}
void EdenGame::enterGame() {
char flag = 0;
_currentTime = _vm->_timerTicks / 100;
_globals->_gameTime = _currentTime;
_demoStartTicks = _vm->_timerTicks;
_gameStarted = false;
if (!_gameLoaded) {
_globals->_roomNum = 279;
_globals->_areaNum = Areas::arMo;
_globals->_var100 = 0xFF;
initPlace(_globals->_roomNum);
_globals->_currMusicNum = 0;
startmusique(1);
} else {
flag = _globals->_autoDialog; //TODO
initafterload();
byte lastMusicNum = _globals->_currMusicNum; //TODO: ???
_globals->_currMusicNum = 0;
startmusique(lastMusicNum);
_globals->_inventoryScrollPos = 0;
_gameStarted = true;
}
showObjects();
drawTopScreen();
saveFriezes();
_graphics->setShowBlackBars(true);
_globals->_mirrorEffect = 1;
updateRoom(_globals->_roomNum);
if (flag) {
_globals->_iconsIndex = 4;
_globals->_autoDialog = true;
parle_moi();
}
}
void EdenGame::signon(const char *s) {
}
void EdenGame::FRDevents() {
_vm->pollEvents();
int16 mouseY;
int16 mouseX;
_vm->getMousePosition(&mouseX, &mouseY);
mouseX -= _mouseCenterX;
mouseY -= _mouseCenterY;
_vm->setMousePosition(_mouseCenterX , _mouseCenterY);
_cursorPosX += mouseX;
_cursorPosX = CLIP(_cursorPosX, 4, 292);
_cursorPosY += mouseY;
int16 maxY = _globals->_displayFlags == DisplayFlags::dfFlag2 ? 190 : 170;
_cursorPosY = CLIP(_cursorPosY, 4, maxY);
_cirsorPanX = _cursorPosX;
if (_cursorPosY >= 10 && _cursorPosY <= 164 && !(_globals->_displayFlags & DisplayFlags::dfFrescoes))
_cirsorPanX += _scrollPos;
if (_normalCursor) {
_currCursor = 0;
_currSpot = scan_icon_list(_cirsorPanX + _cursCenter, _cursorPosY + _cursCenter, _globals->_iconsIndex);
if (_currSpot)
_currCursor = _currSpot->_cursorId;
}
if (_cursCenter == 0 && _currCursor != 53) {
_cursCenter = 11;
_cursorPosX -= 11;
}
if (_cursCenter == 11 && _currCursor == 53) {
_cursCenter = 0;
_cursorPosX += 11;
}
if (_globals->_displayFlags & DisplayFlags::dfPanable) {
//TODO: _currSpot may be zero (due to scan_icon_list failure) if cursor slips between hot areas.
//fix me here or above?
if (_currSpot) { // ok, plug it here
_curSpot2 = _currSpot;
displayAdamMapMark(_curSpot2->_actionId - 14);
}
}
if (_globals->_displayFlags == DisplayFlags::dfFlag2 && _currSpot)
_curSpot2 = _currSpot;
if (_globals->_displayFlags & DisplayFlags::dfFrescoes) {
if (_frescoTalk)
_graphics->restoreUnderSubtitles();
if (_currCursor == 9 && !_torchCursor) {
_graphics->rundcurs();
_torchCursor = true;
_graphics->setGlowX(-1);
}
if (_currCursor != 9 && _torchCursor) {
_graphics->unglow();
_torchCursor = false;
_cursorSaved = false;
}
}
if (_vm->isMouseButtonDown()) {
if (!_mouseHeld) {
_mouseHeld = true;
_gameStarted = true;
mouse();
}
} else
_mouseHeld = false;
if (_globals->_displayFlags != DisplayFlags::dfFlag2) {
if (--_inventoryScrollDelay <= 0) {
if (_globals->_objCount > _invIconsCount && _cursorPosY > 164) {
if (_cursorPosX > 284 && _globals->_inventoryScrollPos + _invIconsCount < _globals->_objCount) {
_globals->_inventoryScrollPos++;
_inventoryScrollDelay = 20;
showObjects();
}
if (_cursorPosX < 30 && _globals->_inventoryScrollPos != 0) {
_globals->_inventoryScrollPos--;
_inventoryScrollDelay = 20;
showObjects();
}
}
}
}
if (_inventoryScrollDelay < 0)
_inventoryScrollDelay = 0;
if (_vm->shouldQuit())
edenShudown();
}
Icon *EdenGame::scan_icon_list(int16 x, int16 y, int16 index) {
for (Icon *icon = &_gameIcons[index]; icon->sx >= 0; icon++) {
if (icon->_cursorId & 0x8000)
continue;
#if 0
// MAC version use this check. Same check is present in PC version, but never used
// Because of x >= clause two adjacent rooms has 1-pixel wide dead zone between them
// On valley view screens if cursor slips in this zone a crash in FRDevents occurs
// due to lack of proper checks
if (x < icon->ff_0 || x >= icon->ff_4
|| y < icon->ff_2 || y >= icon->ff_6)
#else
// PC version has this check inlined in FRDevents
// Should we keep it or fix edge coordinates in afroom() instead?
if (x < icon->sx || x > icon->ex
|| y < icon->sy || y > icon->ey)
#endif
continue;
return icon;
}
return nullptr;
}
void EdenGame::updateCursor() {
if (++_torchTick > 3)
_torchTick = 0;
if (!_torchTick) {
_torchCurIndex++;
_glowIndex++;
}
if (_torchCurIndex > 8)
_torchCurIndex = 0;
if (_glowIndex > 4)
_glowIndex = 0;
if (!_torchCursor) {
useMainBank();
_graphics->sundcurs(_cursorPosX + _scrollPos, _cursorPosY);
if (_currCursor != 53 && _currCursor < 10) { //TODO: cond
if (_vm->getPlatform() == Common::kPlatformMacintosh)
engineMac();
else
enginePC();
} else
_graphics->drawSprite(_currCursor, _cursorPosX + _scrollPos, _cursorPosY);
_graphics->setGlowX(1);
} else {
useBank(117);
if (_cursorPosX > 294)
_cursorPosX = 294;
_graphics->unglow();
_graphics->glow(_glowIndex);
_graphics->drawSprite(_torchCurIndex, _cursorPosX + _scrollPos, _cursorPosY);
if (_frescoTalk)
_graphics->displaySubtitles();
}
}
void EdenGame::mouse() {
typedef void (EdenGame::*MouseAction)();
static const MouseAction mouse_actions[] = {
&EdenGame::actionMoveNorth,
&EdenGame::actionMoveEast,
&EdenGame::actionMoveSouth,
&EdenGame::actionMoveWest,
&EdenGame::actionPlateMonk,
&EdenGame::actionGraaFrescoe,
&EdenGame::actionPushStone,
&EdenGame::actionSkelettonHead,
&EdenGame::actionMummyHead,
&EdenGame::actionMoveNorth,
&EdenGame::actionKingDialog1,
&EdenGame::actionKingDialog2,
&EdenGame::actionKingDialog3,
&EdenGame::actionGotoHall,
&EdenGame::actionLabyrinthTurnAround,
&EdenGame::actionSkelettonMoorkong,
&EdenGame::actionGotoFullNest,
&EdenGame::actionLookLake,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionFinal,
&EdenGame::actionMoveNorth,
&EdenGame::actionMoveSouth,
&EdenGame::actionVisit,
&EdenGame::actionDinoBlow,
&EdenGame::actionLascFrescoe,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
nullptr,
nullptr,
nullptr,
nullptr,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
nullptr,
nullptr,
nullptr,
nullptr,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
nullptr,
nullptr,
nullptr,
nullptr,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
&EdenGame::actionGotoVal,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionGetPrism,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionGetEgg,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionGetMushroom,
&EdenGame::actionGetBadMushroom,
&EdenGame::actionGetKnife,
&EdenGame::actionGetEmptyNest,
&EdenGame::actionGetFullNest,
&EdenGame::actionGetGold,
nullptr,
&EdenGame::actionNop,
&EdenGame::actionGetSunStone,
&EdenGame::actionGetHorn,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionNop,
&EdenGame::actionNop,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
&EdenGame::actionGetTablet,
&EdenGame::actionClickValleyPlan,
&EdenGame::actionEndFrescoes,
&EdenGame::actionChoose,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
&EdenGame::actionKing,
&EdenGame::actionDina,
&EdenGame::actionThoo,
&EdenGame::actionMonk,
&EdenGame::actionTormentor,
&EdenGame::actionMessenger,
&EdenGame::actionMango,
&EdenGame::actionEve,
&EdenGame::actionAzia,
&EdenGame::actionMammi,
&EdenGame::actionGuards,
&EdenGame::actionFisher,
&EdenGame::actionDino,
&EdenGame::actionTyran,
&EdenGame::actionMorkus,
&EdenGame::actionNop,
&EdenGame::parle_moi,
&EdenGame::actionAdam,
&EdenGame::actionTakeObject,
&EdenGame::putObject,
&EdenGame::clictimbre,
&EdenGame::handleDinaDialog,
&EdenGame::closeCharacterScreen,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
&EdenGame::generique,
&EdenGame::choseSubtitleOption,
&EdenGame::edenQuit,
&EdenGame::restart,
&EdenGame::cancel2,
&EdenGame::testvoice,
&EdenGame::changeVolume,
&EdenGame::load,
&EdenGame::save,
&EdenGame::clickTapeCursor,
&EdenGame::playtape,
&EdenGame::stopTape,
&EdenGame::rewindtape,
&EdenGame::forwardTape,
&EdenGame::confirmYes,
&EdenGame::confirmNo,
&EdenGame::actionGotoMap
};
if (!(_currSpot = scan_icon_list(_cirsorPanX + _cursCenter,
_cursorPosY + _cursCenter, _globals->_iconsIndex)))
return;
_curSpot2 = _currSpot;
debug("invoking mouse action %d", _currSpot->_actionId);
if (mouse_actions[_currSpot->_actionId])
(this->*mouse_actions[_currSpot->_actionId])();
}
////// sound.c
void EdenGame::musique() {
if (_globals->_newMusicType == MusicType::mtDontChange)
return;
Dialog *dial = (Dialog *)getElem(_gameDialogs, 128);
for (;;dial++) {
if (dial->_flags == -1 && dial->_condNumLow == -1)
return;
byte flag = dial->_flags;
byte hidx = (dial->_textCondHiMask & 0xC0) >> 6;
byte lidx = dial->_condNumLow; //TODO: fixme - unsigned = signed
if (flag & 0x10)
hidx |= 4;
if (testCondition(((hidx << 8) | lidx) & 0x7FF))
break;
}
byte mus = dial->_textNumLow;
_globals->_newMusicType = MusicType::mtDontChange;
if (mus != 0 && mus != 2 && mus < 50)
startmusique(mus);
}
void EdenGame::startmusique(byte num) {
if (num == _globals->_currMusicNum)
return;
if (_musicPlayingFlag) {
fademusica0(1);
_musicChannel->stop();
}
loadmusicfile(num);
_globals->_currMusicNum = num;
_musSequencePtr = _musicBuf + 32; //TODO: rewrite it properly
int16 seq_size = READ_LE_UINT16(_musicBuf + 30);
_musicPatternsPtr = _musicBuf + 30 + seq_size;
int16 pat_size = READ_LE_UINT16(_musicBuf + 27);
_musicSamplesPtr = _musicBuf + 32 + 4 + pat_size;
int16 freq = READ_LE_UINT16(_musicSamplesPtr - 2);
delete _musicChannel;
_musicChannel = new CSoundChannel(_vm->_mixer, freq == 166 ? 11025 : 22050, false);
_musicEnabledFlag = true;
_musicSequencePos = 0;
_musicLeftVol = _globals->_prefMusicVol[0];
_musicRightVol = _globals->_prefMusicVol[1];
_musicChannel->setVolume(_musicLeftVol, _musicRightVol);
}
void EdenGame::musicspy() {
if (!_musicEnabledFlag)
return;
_musicLeftVol = _globals->_prefMusicVol[0];
_musicRightVol = _globals->_prefMusicVol[1];
if (_musicFadeFlag & 3)
fademusicup();
if (_personTalking && !_voiceChannel->numQueued())
_musicFadeFlag = 3;
if (_musicChannel->numQueued() < 3) {
byte patnum = _musSequencePtr[(int)_musicSequencePos];
if (patnum == 0xFF) {
// rewind
_musicSequencePos = 0;
patnum = _musSequencePtr[(int)_musicSequencePos];
}
_musicSequencePos++;
byte *patptr = _musicPatternsPtr + patnum * 6;
int ofs = patptr[0] + (patptr[1] << 8) + (patptr[2] << 16);
int len = patptr[3] + (patptr[4] << 8) + (patptr[5] << 16);
_musicChannel->queueBuffer(_musicSamplesPtr + ofs, len);
_musicPlayingFlag = true;
}
}
void EdenGame::persovox() {
int16 num = _globals->_textNum;
if (_globals->_textBankIndex != 1)
num += 565;
if (_globals->_textBankIndex == 3)
num += 707;
_voiceSamplesSize = loadSound(num);
int16 volumeLeft = _globals->_prefSoundVolume[0];
int16 volumeRight = _globals->_prefSoundVolume[1];
int16 stepLeft = _musicChannel->_volumeLeft < volumeLeft ? 1 : -1;
int16 stepRight = _musicChannel->_volumeRight < volumeRight ? 1 : -1;
do {
if (volumeLeft != _musicChannel->_volumeLeft)
_musicChannel->setVolumeLeft(_musicChannel->_volumeLeft + stepLeft);
if (volumeRight != _musicChannel->_volumeRight)
_musicChannel->setVolumeRight(_musicChannel->_volumeRight + stepRight);
} while (_musicChannel->_volumeLeft != volumeLeft || _musicChannel->_volumeRight != volumeRight);
volumeLeft = _globals->_prefVoiceVol[0];
volumeRight = _globals->_prefVoiceVol[1];
_voiceChannel->setVolume(volumeLeft, volumeRight);
_voiceChannel->queueBuffer(_voiceSamplesBuffer, _voiceSamplesSize, true);
_personTalking = true;
_musicFadeFlag = 0;
_lastAnimTicks = _vm->_timerTicks;
}
bool EdenGame::personIsTalking() {
return _personTalking;
}
perso_t *EdenGame::personSubtitles() {
perso_t *perso = nullptr;
switch (_globals->_curVideoNum) {
case 170:
perso = &_persons[PER_UNKN_156];
break;
case 83:
perso = &_persons[PER_MORKUS];
break;
case 88:
perso = &_persons[PER_MORKUS];
break;
case 89:
perso = &_persons[PER_MORKUS];
break;
case 94:
perso = &_persons[PER_MORKUS];
break;
default:
return perso;
}
return perso;
}
// Original name: endpersovox
void EdenGame::endCharacterSpeech() {
_graphics->restoreUnderSubtitles();
if (_personTalking) {
_voiceChannel->stop();
_personTalking = false;
_musicFadeFlag = 3;
}
if (_soundAllocated) {
free(_voiceSamplesBuffer);
_voiceSamplesBuffer = nullptr;
_soundAllocated = false;
}
}
void EdenGame::fademusicup() {
if (_musicFadeFlag & 2) {
int16 vol = _musicChannel->_volumeLeft;
if (vol < _musicLeftVol) {
vol += 8;
if (vol > _musicLeftVol)
vol = _musicLeftVol;
} else {
vol -= 8;
if (vol < _musicLeftVol)
vol = _musicLeftVol;
}
_musicChannel->setVolumeLeft(vol);
if (vol == _musicLeftVol)
_musicFadeFlag &= ~2;
}
if (_musicFadeFlag & 1) {
int16 vol = _musicChannel->_volumeRight;
if (vol < _musicRightVol) {
vol += 8;
if (vol > _musicRightVol)
vol = _musicRightVol;
} else {
vol -= 8;
if (vol < _musicRightVol)
vol = _musicRightVol;
}
_musicChannel->setVolumeRight(vol);
if (vol == _musicRightVol)
_musicFadeFlag &= ~1;
}
}
void EdenGame::fademusica0(int16 delay) {
int16 volume;
while ((volume = _musicChannel->getVolume()) > 2) {
volume -= 2;
if (volume < 2)
volume = 2;
_musicChannel->setVolume(volume, volume);
wait(delay);
}
}
//// obj.c
// Original name: getobjaddr
object_t *EdenGame::getObjectPtr(int16 id) {
int i;
for (i = 0; i < MAX_OBJECTS; i++) {
if (_objects[i]._id == id)
break;
}
return &_objects[i];
}
void EdenGame::countObjects() {
int16 index = 0;
byte total = 0;
for (int i = 0; i < MAX_OBJECTS; i++) {
int16 count = _objects[i]._count;
if (count == 0)
continue;
if (_objects[i]._flags & ObjectFlags::ofInHands)
count--;
if (count) {
total += count;
while (count--)
_ownObjects[index++] = _objects[i]._id;
}
}
_globals->_objCount = total;
}
void EdenGame::showObjects() {
Icon *icon = &_gameIcons[_invIconsBase];
_globals->_drawFlags &= ~(DrawFlags::drDrawInventory | DrawFlags::drDrawFlag2);
countObjects();
int16 total = _globals->_objCount;
for (int16 i = _invIconsCount; i--; icon++) {
if (total) {
icon->_cursorId &= ~0x8000;
total--;
} else
icon->_cursorId |= 0x8000;
}
useMainBank();
_graphics->drawSprite(55, 0, 176);
icon = &_gameIcons[_invIconsBase];
total = _globals->_objCount;
int16 index = _globals->_inventoryScrollPos;
for (int16 i = _invIconsCount; total-- && i--; icon++) {
char obj = _ownObjects[index++];
icon->_objectId = obj;
_graphics->drawSprite(obj + 9, icon->sx, 178);
}
_paletteUpdateRequired = true;
if ((_globals->_displayFlags & DisplayFlags::dfMirror) || (_globals->_displayFlags & DisplayFlags::dfPanable)) {
_graphics->saveBottomFrieze();
scroll();
}
}
byte * EdenGame::getGlowBuffer() {
return _glowBuffer;
}
void EdenGame::setMusicFade(byte value) {
_musicFadeFlag = value;
}
void EdenGame::winObject(int16 id) {
object_t *object = getObjectPtr(id);
object->_flags |= ObjectFlags::ofFlag1;
object->_count++;
_globals->_curItemsMask |= object->_itemMask;
_globals->_wonItemsMask |= object->_itemMask;
_globals->_curPowersMask |= object->_powerMask;
_globals->_wonPowersMask |= object->_powerMask;
}
void EdenGame::loseObject(int16 id) {
object_t *object = getObjectPtr(id);
if (object->_count > 0)
object->_count--;
if (!object->_count) {
object->_flags &= ~ObjectFlags::ofFlag1;
_globals->_curItemsMask &= ~object->_itemMask;
_globals->_curPowersMask &= ~object->_powerMask;
}
_globals->_curObjectId = 0;
_globals->_curObjectFlags = 0;
_globals->_curObjectCursor = 9;
_gameIcons[16]._cursorId |= 0x8000;
object->_flags &= ~ObjectFlags::ofInHands;
_normalCursor = true;
_currCursor = 0;
_torchCursor = false;
}
void EdenGame::lostObject() {
parlemoiNormalFlag = true;
if (_globals->_curObjectId)
loseObject(_globals->_curObjectId);
}
// Original name: objecthere
bool EdenGame::isObjectHere(int16 id) {
object_t *object = getObjectPtr(id);
for (_currentObjectLocation = &_objectLocations[object->_locations]; *_currentObjectLocation != 0xFFFF; _currentObjectLocation++) {
if (*_currentObjectLocation == _globals->_roomNum)
return true;
}
return false;
}
void EdenGame::objectmain(int16 id) {
object_t *object = getObjectPtr(id);
_gameIcons[16]._cursorId &= ~0x8000;
_globals->_curObjectId = object->_id;
_globals->_curObjectCursor = _globals->_curObjectId + 9;
object->_flags |= ObjectFlags::ofInHands;
_globals->_curObjectFlags = object->_flags;
_currCursor = _globals->_curObjectId + 9;
_normalCursor = false;
}
void EdenGame::getObject(int16 id) {
Room *room = _globals->_roomPtr;
if (_globals->_curObjectId)
return;
if (!isObjectHere(id))
return;
*_currentObjectLocation |= 0x8000;
objectmain(id);
winObject(id);
showObjects();
_globals->_roomImgBank = room->_bank;
_globals->_roomVidNum = room->_video;
displayPlace();
}
void EdenGame::putObject() {
if (!_globals->_curObjectId)
return;
_gameIcons[16]._cursorId |= 0x8000;
object_t *object = getObjectPtr(_globals->_curObjectId);
_globals->_curObjectCursor = 9;
_globals->_curObjectId = 0;
_globals->_curObjectFlags = 0;
object->_flags &= ~ObjectFlags::ofInHands;
_globals->_nextDialogPtr = nullptr;
_closeCharacterDialog = false;
_globals->_dialogType = DialogType::dtTalk;
showObjects();
_normalCursor = true;
}
void EdenGame::newObject(int16 id, int16 arg2) {
object_t *object = getObjectPtr(id);
uint16 e, *t = &_objectLocations[object->_locations];
while ((e = *t) != 0xFFFF) {
e &= ~0x8000;
if ((e >> 8) == arg2)
*t = e;
t++;
}
}
void EdenGame::giveobjectal(int16 id) {
if (id == Objects::obKnife)
_objectLocations[2] = 0;
if (id == Objects::obApple)
_globals->_stepsToFindAppleNormal = 0;
if (id >= Objects::obEyeInTheStorm && id < (Objects::obRiverThatWinds + 1) && _globals->_roomCharacterType == PersonFlags::pftVelociraptor) {
//TODO: fix that cond above
object_t *object = getObjectPtr(id);
_globals->_roomCharacterPtr->_powers &= ~object->_powerMask;
}
winObject(id);
}
void EdenGame::giveObject() {
byte id = _globals->_giveObj1;
if (id) {
_globals->_giveObj1 = 0;
giveobjectal(id);
}
id = _globals->_giveObj2;
if (id) {
_globals->_giveObj2 = 0;
giveobjectal(id);
}
id = _globals->_giveObj3;
if (id) {
_globals->_giveObj3 = 0;
giveobjectal(id);
}
}
// Original name: takeObject
void EdenGame::actionTakeObject() {
objectmain(_curSpot2->_objectId);
_globals->_nextDialogPtr = nullptr;
_closeCharacterDialog = false;
_globals->_dialogType = DialogType::dtTalk;
if (_globals->_inventoryScrollPos)
_globals->_inventoryScrollPos--;
showObjects();
}
////
// Original name: newchampi
void EdenGame::newMushroom() {
if (_objects[Objects::obShroom - 1]._count == 0) {
newObject(Objects::obShroom, _globals->_citadelAreaNum);
newObject(Objects::obBadShroom, _globals->_citadelAreaNum);
}
}
// Original name: newnidv
void EdenGame::newEmptyNest() {
Room *room = _globals->_citaAreaFirstRoom;
if (_objects[Objects::obNest - 1]._count)
return;
object_t *obj = getObjectPtr(Objects::obNest);
for (uint16 *ptr = _objectLocations + obj->_locations; *ptr != 0xFFFF; ptr++) {
if ((*ptr & ~0x8000) >> 8 != _globals->_citadelAreaNum)
continue;
*ptr &= ~0x8000;
for (; room->_id != 0xFF; room++) {
if (room->_location == (*ptr & 0xFF)) {
room->_bank = 279;
room->_id = 9;
room++;
room->_bank = 280;
return;
}
}
}
}
// Original name: newnido
void EdenGame::newNestWithEggs() {
Room *room = _globals->_citaAreaFirstRoom;
if (_objects[Objects::obFullNest - 1]._count)
return;
if (_objects[Objects::obNest - 1]._count)
return;
object_t *obj = getObjectPtr(Objects::obFullNest);
for (uint16 *ptr = _objectLocations + obj->_locations; *ptr != 0xFFFF; ptr++) {
if ((*ptr & ~0x8000) >> 8 != _globals->_citadelAreaNum)
continue;
*ptr &= ~0x8000;
for (; room->_id != 0xFF; room++) {
if (room->_location == (*ptr & 0xFF)) {
room->_bank = 277;
room->_id = 9;
room++;
room->_bank = 278;
return;
}
}
}
}
// Original name: newor
void EdenGame::newGold() {
if (_objects[Objects::obGold - 1]._count == 0)
newObject(Objects::obGold, _globals->_citadelAreaNum);
}
void EdenGame::gotoPanel() {
if (_vm->shouldQuit())
byte_31D64 = _globals->_autoDialog; //TODO: check me
_noPalette = false;
_globals->_iconsIndex = 85;
_globals->_characterPtr = nullptr;
_globals->_drawFlags |= DrawFlags::drDrawMenu;
_globals->_displayFlags = DisplayFlags::dfFlag2;
_globals->_menuFlags = 0;
displayPanel();
_graphics->fadeToBlack(3);
displayTopPanel();
CLBlitter_CopyView2Screen(_graphics->getMainView());
_graphics->SendPalette2Screen(256);
_cursorPosX = 320 / 2;
_cursorPosY = 200 / 2;
_vm->setMousePosition(_mouseCenterX, _mouseCenterY);
}
void EdenGame::setMouseCenterX(uint16 xpos) {
_mouseCenterX = xpos;
}
void EdenGame::setMouseCenterY(uint16 ypos) {
_mouseCenterY = ypos;
}
uint16 EdenGame::getMouseCenterX() {
return _mouseCenterX;
}
uint16 EdenGame::getMouseCenterY() {
return _mouseCenterY;
}
void EdenGame::noclicpanel() {
if (_globals->_menuFlags & MenuFlags::mfFlag4) {
moveTapeCursor();
return;
}
if (_globals->_drawFlags & DrawFlags::drDrawFlag8)
return;
if (_globals->_menuFlags & MenuFlags::mfFlag1) {
changervol();
return;
}
byte num;
if (_curSpot2 >= &_gameIcons[119]) {
debug("noclic: objid = %p, glob3,2 = %2X %2X", (void *)_curSpot2, _globals->_menuItemIdHi, _globals->_menuItemIdLo);
if (_curSpot2->_objectId == (uint16)((_globals->_menuItemIdLo + _globals->_menuItemIdHi) << 8)) //TODO: check me
return;
} else {
int idx = _curSpot2 - &_gameIcons[105];
if (idx == 0) {
_globals->_menuItemIdLo = 1;
num = 1;
goto skip;
}
num = (idx & 0x7F) + 1;
if (num >= 5)
num = 1;
if (num == _globals->_var43)
return;
_globals->_var43 = 0;
}
num = _globals->_menuItemIdLo;
_globals->_menuItemIdLo = _curSpot2->_objectId & 0xFF;
skip:
;
_globals->_menuItemIdHi = (_curSpot2->_objectId & 0xFF00) >> 8;
debug("noclic: new glob3,2 = %2X %2X", _globals->_menuItemIdHi, _globals->_menuItemIdLo);
displayResult();
num &= 0xF0;
if (num != 0x30)
num = _globals->_menuItemIdLo & 0xF0;
if (num == 0x30)
displayCursors();
}
void EdenGame::generique() {
_graphics->drawBlackBars();
display();
_graphics->fadeToBlack(3);
_graphics->clearScreen();
int oldmusic = _globals->_currMusicNum;
_graphics->playHNM(95);
displayPanel();
displayTopPanel();
_paletteUpdateRequired = true;
startmusique(oldmusic);
}
void EdenGame::cancel2() {
drawTopScreen();
showObjects();
_globals->_iconsIndex = 16;
_globals->_drawFlags &= ~DrawFlags::drDrawMenu;
gameToMirror(1);
}
byte *EdenGame::getCurKeepBuf() {
return _cursKeepBuf;
}
bool EdenGame::isMouseHeld() {
return _mouseHeld;
}
void EdenGame::setMouseHeld() {
_mouseHeld = true;
}
void EdenGame::setMouseNotHeld() {
_mouseHeld = false;
}
void EdenGame::testvoice() {
_globals->_frescoNumber = 0;
_globals->_characterPtr = _persons;
_globals->_dialogType = DialogType::dtInspect;
int16 num = (_persons[PER_KING]._id << 3) | _globals->_dialogType;
dialoscansvmas((Dialog *)getElem(_gameDialogs, num));
_graphics->restoreUnderSubtitles();
_graphics->displaySubtitles();
persovox();
waitEndSpeak();
endCharacterSpeech();
_globals->_varCA = 0;
_globals->_dialogType = DialogType::dtTalk;
}
void EdenGame::load() {
char name[132];
_gameLoaded = false;
byte oldMusic = _globals->_currMusicNum; //TODO: from uint16 to byte?!
fademusica0(1);
desktopcolors();
FlushEvents(-1, 0);
// if(OpenDialog(0, 0)) //TODO: write me
{
// TODO
Common::strcpy_s(name, "edsave1.000");
loadgame(name);
}
_vm->hideMouse();
CLBlitter_FillScreenView(0xFFFFFFFF);
_graphics->fadeToBlack(3);
CLBlitter_FillScreenView(0);
if (!_gameLoaded) {
_musicFadeFlag = 3;
musicspy();
_paletteUpdateRequired = true;
return;
}
if ((oldMusic & 0xFF) != _globals->_currMusicNum) { //TODO: r30 is uns char/bug???
oldMusic = _globals->_currMusicNum;
_globals->_currMusicNum = 0;
startmusique(oldMusic);
} else {
_musicFadeFlag = 3;
musicspy();
}
bool talk = _globals->_autoDialog; //TODO check me
initafterload();
_graphics->fadeToBlack(3);
CLBlitter_FillScreenView(0);
CLBlitter_FillView(_graphics->getMainView(), 0);
drawTopScreen();
_globals->_inventoryScrollPos = 0;
showObjects();
updateRoom(_globals->_roomNum);
if (talk) {
_globals->_iconsIndex = 4;
_globals->_autoDialog = true;
parle_moi();
}
}
void EdenGame::initafterload() {
_globals->_characterImageBank = 0;
_globals->_lastPlaceNum = 0;
loadPlace(_globals->_areaPtr->_placeNum);
_gameIcons[18]._cursorId |= 0x8000;
if (_globals->_curAreaType == AreaType::atValley)
_gameIcons[18]._cursorId &= ~0x8000;
_personRoomBankTable[30] = 27;
if (_globals->_phaseNum >= 352)
_personRoomBankTable[30] = 26;
_animateTalking = false;
_animationActive = false;
_globals->_var100 = 0;
_globals->_eventType = EventType::etEventC;
_globals->_valleyVidNum = 0;
_globals->_drawFlags &= ~DrawFlags::drDrawMenu;
_currentTime = _vm->_timerTicks / 100;
_globals->_gameTime = _currentTime;
if (_globals->_roomCharacterType == PersonFlags::pftTyrann)
setChrono(3000);
_adamMapMarkPos.x = -1;
_adamMapMarkPos.y = -1;
}
void EdenGame::save() {
char name[260];
fademusica0(1);
desktopcolors();
FlushEvents(-1, 0);
//SaveDialog(byte_37150, byte_37196->ff_A);
//TODO
Common::strcpy_s(name, "edsave1.000");
saveGame(name);
_vm->hideMouse();
CLBlitter_FillScreenView(0xFFFFFFFF);
_graphics->fadeToBlack(3);
CLBlitter_FillScreenView(0);
_musicFadeFlag = 3;
musicspy();
_paletteUpdateRequired = true;
}
void EdenGame::desktopcolors() {
_graphics->fadeToBlack(3);
CLBlitter_FillScreenView(0xFFFFFFFF);
CLPalette_BeSystem();
_vm->showMouse();
}
void EdenGame::panelrestart() {
_gameLoaded = false;
byte curmus = _globals->_currMusicNum;
byte curlng = _globals->_prefLanguage;
loadrestart();
_globals->_prefLanguage = curlng;
if (!_gameLoaded) //TODO always?
return;
_globals->_characterImageBank = 0;
_globals->_lastPlaceNum = 0;
loadPlace(_globals->_areaPtr->_placeNum);
_globals->_displayFlags = DisplayFlags::dfFlag1;
_gameIcons[18]._cursorId |= 0x8000;
if (_globals->_curAreaType == AreaType::atValley)
_gameIcons[18]._cursorId &= ~0x8000;
_personRoomBankTable[30] = 27;
if (_globals->_phaseNum >= 352)
_personRoomBankTable[30] = 26;
_animateTalking = false;
_animationActive = false;
_globals->_var100 = 0;
_globals->_eventType = 0;
_globals->_valleyVidNum = 0;
_globals->_drawFlags &= ~DrawFlags::drDrawMenu;
_globals->_inventoryScrollPos = 0;
_adamMapMarkPos.x = -1;
_adamMapMarkPos.y = -1;
if (curmus != _globals->_currMusicNum) {
curmus = _globals->_currMusicNum;
_globals->_currMusicNum = 0;
startmusique(curmus);
}
_graphics->fadeToBlack(3);
CLBlitter_FillScreenView(0);
CLBlitter_FillView(_graphics->getMainView(), 0);
drawTopScreen();
showObjects();
saveFriezes();
_graphics->setShowBlackBars(true);
updateRoom(_globals->_roomNum);
}
void EdenGame::reallyquit() {
_quitFlag3 = true;
_quitFlag2 = true;
}
void EdenGame::confirmer(char mode, char yesId) {
_globals->_iconsIndex = 119;
_gameIcons[119]._objectId = yesId;
_confirmMode = mode;
useBank(65);
_graphics->drawSprite(12, 117, 74);
_cursorPosX = 156;
if (_vm->shouldQuit())
_cursorPosX = 136;
_cursorPosY = 88;
}
void EdenGame::confirmYes() {
displayPanel();
_globals->_iconsIndex = 85;
switch (_confirmMode) {
case 1:
panelrestart();
break;
case 2:
reallyquit();
break;
default:
break;
}
}
void EdenGame::confirmNo() {
displayPanel();
_globals->_iconsIndex = 85;
// pomme_q = false;
}
void EdenGame::restart() {
confirmer(1, _curSpot2->_objectId);
}
void EdenGame::edenQuit() {
confirmer(2, _curSpot2->_objectId);
}
// Original name: choixsubtitle
void EdenGame::choseSubtitleOption() {
byte lang = _curSpot2->_objectId & 0xF;
if (lang == _globals->_prefLanguage)
return;
if (lang > 5)
return;
_globals->_prefLanguage = lang;
// save the new preferred language in the config
ConfMan.setInt("PrefLang", lang);
ConfMan.flushToDisk();
_graphics->langbuftopanel();
displayLanguage();
}
// Original name: reglervol
void EdenGame::changeVolume() {
byte *valptr = &_globals->_prefMusicVol[_curSpot2->_objectId & 7];
_cursorPosY = 104 - ((*valptr >> 2) & 0x3F); // TODO: check me
_curSliderValuePtr = valptr;
_globals->_menuFlags |= MenuFlags::mfFlag1;
if (_curSpot2->_objectId & 8)
_globals->_menuFlags |= MenuFlags::mfFlag2;
_curSliderX = _curSpot2->sx;
_curSliderY = _cursorPosY;
}
void EdenGame::changervol() {
if (_mouseHeld) {
restrictCursorArea(_curSliderX - 1, _curSliderX + 3, 40, 110);
int16 delta = _curSliderY - _cursorPosY;
if (delta == 0)
return;
newvol(_curSliderValuePtr, delta);
if (_globals->_menuFlags & MenuFlags::mfFlag2)
newvol(_curSliderValuePtr + 1, delta);
_graphics->cursbuftopanel();
displayCursors();
_curSliderY = _cursorPosY;
} else
_globals->_menuFlags &= ~(MenuFlags::mfFlag1 | MenuFlags::mfFlag2);
}
void EdenGame::newvol(byte *volptr, int16 delta) {
int16 vol = *volptr / 4;
vol += delta;
if (vol < 0)
vol = 0;
if (vol > 63)
vol = 63;
*volptr = vol * 4;
_musicChannel->setVolume(_globals->_prefMusicVol[0], _globals->_prefMusicVol[1]);
}
void EdenGame::playtape() {
if (_globals->_menuItemIdHi & 8)
_globals->_tapePtr++;
for (;; _globals->_tapePtr++) {
if (_globals->_tapePtr == &_tapes[MAX_TAPES]) {
_globals->_tapePtr--;
stopTape();
return;
}
if (_globals->_tapePtr->_textNum)
break;
}
_globals->_menuFlags |= MenuFlags::mfFlag8;
_globals->_drawFlags &= ~DrawFlags::drDrawMenu;
uint16 oldRoomNum = _globals->_roomNum;
uint16 oldParty = _globals->_party;
byte oldBack = _globals->_roomBackgroundBankNum;
perso_t *oldPerso = _globals->_characterPtr;
_globals->_party = _globals->_tapePtr->_party;
_globals->_roomNum = _globals->_tapePtr->_roomNum;
_globals->_roomBackgroundBankNum = _globals->_tapePtr->_backgroundBankNum;
_globals->_dialogPtr = _globals->_tapePtr->_dialog;
_globals->_characterPtr = _globals->_tapePtr->_perso;
endCharacterSpeech();
displayTapeCursor();
if (_globals->_characterPtr != oldPerso
|| _globals->_roomNum != _lastTapeRoomNum) {
_lastTapeRoomNum = _globals->_roomNum;
_globals->_curCharacterAnimPtr = nullptr;
_globals->_varCA = 0;
_globals->_characterImageBank = -1;
AnimEndCharacter();
loadCurrCharacter();
}
displayCharacterBackground();
_globals->_textNum = _globals->_tapePtr->_textNum;
my_bulle();
getDataSync();
displayCharacterPanel();
persovox();
_globals->_roomBackgroundBankNum = oldBack;
_globals->_party = oldParty;
_globals->_roomNum = oldRoomNum;
}
void EdenGame::rewindtape() {
if (_globals->_tapePtr > _tapes) {
_globals->_tapePtr--;
_globals->_menuFlags &= ~MenuFlags::mfFlag8;
displayTapeCursor();
}
}
// Original name: depcurstape
void EdenGame::moveTapeCursor() {
if (_mouseHeld) {
restrictCursorArea(95, 217, 179, 183);
int idx = (_cursorPosX - 97);
if (idx < 0)
idx = 0;
idx /= 8;
tape_t *tape = _tapes + idx;
if (tape >= _tapes + 16)
tape = _tapes + 16 - 1;
if (tape != _globals->_tapePtr) {
_globals->_tapePtr = tape;
displayTapeCursor();
_globals->_menuFlags &= ~MenuFlags::mfFlag8;
}
} else
_globals->_menuFlags &= ~MenuFlags::mfFlag4;
}
void EdenGame::setCursorSaved(bool cursorSaved) {
_cursorSaved = cursorSaved;
}
bool EdenGame::getCursorSaved() {
return _cursorSaved;
}
bool EdenGame::getNoPalette() {
return _noPalette;
}
// Original name: affcurstape
void EdenGame::displayTapeCursor() {
if (_globals->_drawFlags & DrawFlags::drDrawFlag8)
_noPalette = true;
useBank(65);
_graphics->drawSprite(2, 0, 176);
int x = (_globals->_tapePtr - _tapes) * 8 + 97;
_gameIcons[112].sx = x - 3;
_gameIcons[112].ex = x + 3;
_graphics->drawSprite(5, x, 179);
_noPalette = false;
}
void EdenGame::forwardTape() {
if (_globals->_tapePtr < _tapes + 16) {
_globals->_tapePtr++;
_globals->_menuFlags &= ~MenuFlags::mfFlag8;
displayTapeCursor();
}
}
void EdenGame::stopTape() {
if (!(_globals->_drawFlags & DrawFlags::drDrawFlag8))
return;
_globals->_menuFlags &= ~MenuFlags::mfFlag8;
_globals->_drawFlags &= ~DrawFlags::drDrawFlag8;
_globals->_menuFlags |= MenuFlags::mfFlag10;
_globals->_iconsIndex = 85;
_globals->_characterPtr = nullptr;
_lastTapeRoomNum = 0;
endCharacterSpeech();
fin_perso();
displayPanel();
displayTopPanel();
_paletteUpdateRequired = true;
}
void EdenGame::clickTapeCursor() {
_globals->_menuFlags |= MenuFlags::mfFlag4;
}
// Original name: affpanel
void EdenGame::displayPanel() {
useBank(65);
_graphics->drawSprite(0, 0, 16);
_graphics->paneltobuf();
displayLanguage();
displayCursors();
displayTapeCursor();
}
// Original name: afflangue
void EdenGame::displayLanguage() {
useBank(65);
if (_globals->_prefLanguage > 5)
return;
_graphics->drawSprite(6, 8, _globals->_prefLanguage * 9 + 43); //TODO: * FONT_HEIGHT
_graphics->drawSprite(7, 77, _globals->_prefLanguage * 9 + 44);
}
// Original name: affcursvol
void EdenGame::displayVolCursor(int16 x, int16 vol1, int16 vol2) {
int16 slider = 3;
if (_lastMenuItemIdLo && (_lastMenuItemIdLo & 9) != 1) //TODO check me
slider = 4;
_graphics->drawSprite(slider, x, 104 - vol1);
slider = 3;
if ((_lastMenuItemIdLo & 9) != 0)
slider = 4;
_graphics->drawSprite(slider, x + 12, 104 - vol2);
}
// Original name: affcurseurs
void EdenGame::displayCursors() {
useBank(65);
if (_globals->_drawFlags & DrawFlags::drDrawFlag8)
return;
selectCursor(48);
displayVolCursor(114, _globals->_prefMusicVol[0] / 4, _globals->_prefMusicVol[1] / 4);
selectCursor(50);
displayVolCursor(147, _globals->_prefVoiceVol[0] / 4, _globals->_prefVoiceVol[1] / 4);
selectCursor(52);
displayVolCursor(179, _globals->_prefSoundVolume[0] / 4, _globals->_prefSoundVolume[1] / 4);
}
// Original name: curseurselect
void EdenGame::selectCursor(int itemId) {
_lastMenuItemIdLo = _globals->_menuItemIdLo;
if ((_lastMenuItemIdLo & ~9) != itemId)
_lastMenuItemIdLo = 0;
}
// Original name: afftoppano
void EdenGame::displayTopPanel() {
_graphics->drawSprite(1, 0, 0);
}
// Original name: affresult
void EdenGame::displayResult() {
_graphics->restoreUnderSubtitles();
_globals->_characterPtr = &_persons[19];
_globals->_dialogType = DialogType::dtInspect;
int16 num = (_persons[PER_UNKN_156]._id << 3) | _globals->_dialogType;
if (dialoscansvmas((Dialog *)getElem(_gameDialogs, num)))
_graphics->displaySubtitles();
_globals->_varCA = 0;
_globals->_dialogType = DialogType::dtTalk;
_globals->_characterPtr = nullptr;
}
// Original name: limitezonecurs
void EdenGame::restrictCursorArea(int16 xmin, int16 xmax, int16 ymin, int16 ymax) {
_cursorPosX = CLIP(_cursorPosX, xmin, xmax);
_cursorPosY = CLIP(_cursorPosY, ymin, ymax);
}
// Original name: PommeQ
void EdenGame::edenShudown() {
Icon *icon = &_gameIcons[85];
if (_globals->_displayFlags & DisplayFlags::dfFrescoes) {
_torchCursor = false;
_cursorSaved = true;
if (_globals->_displayFlags & DisplayFlags::dfPerson)
closeCharacterScreen();
_globals->_displayFlags = DisplayFlags::dfFlag1;
resetScroll();
_globals->_var100 = 0xFF;
updateRoom(_globals->_roomNum);
}
if (_globals->_displayFlags & DisplayFlags::dfPerson)
closeCharacterScreen();
if (_globals->_displayFlags & DisplayFlags::dfPanable)
resetScroll();
if (_globals->_displayFlags & DisplayFlags::dfMirror)
resetScroll();
if (_globals->_drawFlags & DrawFlags::drDrawFlag8)
stopTape();
if (_personTalking)
endCharacterSpeech();
_globals->_var103 = 0;
_globals->_mirrorEffect = 0;
putObject();
_currCursor = 53;
if (_globals->_displayFlags != DisplayFlags::dfFlag2)
gotoPanel();
_curSpot2 = icon + 7; //TODO
reallyquit();
}
void EdenGame::habitants(perso_t *perso) {
char persType = perso->_flags & PersonFlags::pfTypeMask; //TODO rename
if (persType && persType != PersonFlags::pfType2) {
_globals->_roomCharacterPtr = perso;
_globals->_roomCharacterType = persType;
_globals->_roomCharacterFlags = perso->_flags;
_globals->_roomPersoItems = perso->_items;
_globals->_roomCharacterPowers = perso->_powers;
_globals->_partyOutside |= perso->_partyMask;
if (_globals->_roomCharacterType == PersonFlags::pftTriceraptor)
removeInfo(_globals->_areaNum + ValleyNews::vnTriceraptorsIn);
else if (_globals->_roomCharacterType == PersonFlags::pftVelociraptor)
removeInfo(_globals->_areaNum + ValleyNews::vnVelociraptorsIn);
} else if (!(perso->_flags & PersonFlags::pfInParty))
_globals->_partyOutside |= perso->_partyMask;
}
void EdenGame::suiveurs(perso_t *perso) {
char persType = perso->_flags & PersonFlags::pfTypeMask;
if (persType == 0 || persType == PersonFlags::pfType2) {
if (perso->_flags & PersonFlags::pfInParty)
_globals->_party |= perso->_partyMask;
}
}
void EdenGame::evenements(perso_t *perso) {
if (_globals->_var113)
return;
if (perso >= &_persons[PER_UNKN_18C])
return;
if (!dialogEvent(perso))
return;
_globals->_var113++;
_globals->_oldDisplayFlags = 1;
perso = _globals->_characterPtr;
initCharacterPointers(perso);
if (!(perso->_partyMask & PersonMask::pmLeader))
_globals->_var60 = 1;
_globals->_eventType = 0;
}
void EdenGame::followme(perso_t *perso) {
if (perso->_flags & PersonFlags::pfTypeMask)
return;
if (perso->_flags & PersonFlags::pfInParty)
perso->_roomNum = _destinationRoom;
}
void EdenGame::rangermammi(perso_t *perso, Room *room) {
Room *found_room = nullptr;
if (!(perso->_partyMask & PersonMask::pmLeader))
return;
for (; room->_id != 0xFF; room++) {
if (room->_flags & RoomFlags::rfHasCitadel) {
found_room = room;
break;
}
if (room->_party != 0xFFFF && (room->_party & PersonMask::pmLeader))
found_room = room; //TODO: no brk?
}
if (!found_room)
return;
perso->_roomNum &= ~0xFF;
perso->_roomNum |= found_room->_location;
perso->_flags &= ~PersonFlags::pfInParty;
_globals->_party &= ~perso->_partyMask;
}
void EdenGame::perso_ici(int16 action) {
perso_t *perso = &_persons[PER_UNKN_156];
// room_t *room = p_global->last_area_ptr->room_ptr; //TODO: compiler opt bug? causes access to zero ptr??? last_area_ptr == 0
switch (action) {
case 0:
suiveurs(perso);
break;
case 1:
habitants(perso);
break;
case 3:
evenements(perso);
break;
case 4:
followme(perso);
break;
case 5:
rangermammi(perso, _globals->_lastAreaPtr->_citadelRoomPtr);
break;
default:
break;
}
perso = _persons;
do {
if (perso->_roomNum == _globals->_roomNum && !(perso->_flags & PersonFlags::pf80)) {
switch (action) {
case 0:
suiveurs(perso);
break;
case 1:
habitants(perso);
break;
case 3:
evenements(perso);
break;
case 4:
followme(perso);
break;
case 5:
rangermammi(perso, _globals->_lastAreaPtr->_citadelRoomPtr);
break;
default:
break;
}
}
perso++;
} while (perso->_roomNum != 0xFFFF);
}
// Original name: setpersohere
void EdenGame::setCharacterHere() {
debug("setCharacterHere, perso is %d", (int)(_globals->_characterPtr - _persons));
_globals->_partyOutside = 0;
_globals->_party = 0;
_globals->_roomCharacterPtr = nullptr;
_globals->_roomCharacterType = 0;
_globals->_roomCharacterFlags = 0;
perso_ici(1);
perso_ici(0);
if (_globals->_roomCharacterType == PersonFlags::pftTyrann)
removeInfo(_globals->_areaNum + ValleyNews::vnTyrannIn);
if (_globals->_roomCharacterType == PersonFlags::pftTriceraptor)
removeInfo(_globals->_areaNum + ValleyNews::vnTriceraptorsIn);
if (_globals->_roomCharacterType == PersonFlags::pftVelociraptor) {
removeInfo(_globals->_areaNum + ValleyNews::vnTyrannIn);
removeInfo(_globals->_areaNum + ValleyNews::vnTyrannLost);
removeInfo(_globals->_areaNum + ValleyNews::vnVelociraptorsLost);
}
}
void EdenGame::faire_suivre(int16 roomNum) {
_destinationRoom = roomNum;
perso_ici(4);
}
// Original name: suis_moi5
void EdenGame::AddCharacterToParty() {
debug("adding person %d to party", (int)(_globals->_characterPtr - _persons));
_globals->_characterPtr->_flags |= PersonFlags::pfInParty;
_globals->_characterPtr->_roomNum = _globals->_roomNum;
_globals->_party |= _globals->_characterPtr->_partyMask;
_globals->_drawFlags |= DrawFlags::drDrawTopScreen;
}
// Original name: suis_moi
void EdenGame::addToParty(int16 index) {
perso_t *old_perso = _globals->_characterPtr;
_globals->_characterPtr = &_persons[index];
AddCharacterToParty();
_globals->_characterPtr = old_perso;
}
// Original name: reste_ici5
void EdenGame::removeCharacterFromParty() {
debug("removing person %d from party", (int)(_globals->_characterPtr - _persons));
_globals->_characterPtr->_flags &= ~PersonFlags::pfInParty;
_globals->_partyOutside |= _globals->_characterPtr->_partyMask;
_globals->_party &= ~_globals->_characterPtr->_partyMask;
_globals->_drawFlags |= DrawFlags::drDrawTopScreen;
}
// Original name: reste_ici
void EdenGame::removeFromParty(int16 index) {
perso_t *old_perso = _globals->_characterPtr;
_globals->_characterPtr = &_persons[index];
removeCharacterFromParty();
_globals->_characterPtr = old_perso;
}
// Original name: eloipart
void EdenGame::handleEloiDeparture() {
removeFromParty(PER_ELOI);
_globals->_gameFlags &= ~GameFlags::gfFlag4000;
_persons[PER_ELOI]._roomNum = 0;
_globals->_partyOutside &= ~_persons[PER_ELOI]._partyMask;
if (_globals->_roomNum == 2817)
setChrono(3000);
_globals->_eloiDepartureDay = _globals->_gameDays;
_globals->_eloiHaveNews = 0;
unlockInfo();
}
// Original name: eloirevientq
bool EdenGame::checkEloiReturn() {
if (_globals->_phaseNum < 304)
return true;
if ((_globals->_phaseNum <= 353) || (_globals->_phaseNum == 370) || (_globals->_phaseNum == 384))
return false;
if (_globals->_areaNum != Areas::arShandovra)
return true;
if (_globals->_phaseNum < 480)
return false;
return true;
}
// Original name: eloirevient
void EdenGame::handleEloiReturn() {
if (_globals->_areaPtr->_type == AreaType::atValley && !_persons[PER_ELOI]._roomNum)
_persons[PER_ELOI]._roomNum = (_globals->_roomNum & 0xFF00) + 1;
}
//// phase.c
void EdenGame::incPhase() {
struct phase_t {
int16 _id;
void (EdenGame::*disp)();
};
static const phase_t phases[] = {
{ 65, &EdenGame::dialautoon },
{ 113, &EdenGame::phase113 },
{ 129, &EdenGame::dialautoon },
{ 130, &EdenGame::phase130 },
{ 161, &EdenGame::phase161 },
{ 211, &EdenGame::dialautoon },
{ 226, &EdenGame::phase226 },
{ 257, &EdenGame::phase257 },
{ 353, &EdenGame::phase353 },
{ 369, &EdenGame::phase369 },
{ 371, &EdenGame::phase371 },
{ 385, &EdenGame::phase385 },
{ 386, &EdenGame::dialonfollow },
{ 418, &EdenGame::phase418 },
{ 433, &EdenGame::phase433 },
{ 434, &EdenGame::phase434 },
{ 449, &EdenGame::dialautoon },
{ 497, &EdenGame::dialautoon },
{ 513, &EdenGame::phase513 },
{ 514, &EdenGame::phase514 },
{ 529, &EdenGame::phase529 },
{ 545, &EdenGame::phase545 },
{ 561, &EdenGame::phase561 },
{ -1, nullptr }
};
_globals->_phaseNum++;
debug("!!! next phase - %4X , room %4X", _globals->_phaseNum, _globals->_roomNum);
_globals->_phaseActionsCount = 0;
for (const phase_t *phase = phases; phase->_id != -1; phase++) {
if (_globals->_phaseNum == phase->_id) {
(this->*phase->disp)();
break;
}
}
}
void EdenGame::phase113() {
removeFromParty(PER_DINA);
_persons[PER_DINA]._roomNum = 274;
}
void EdenGame::phase130() {
dialautoon();
removeFromParty(PER_MONK);
}
void EdenGame::phase161() {
Area *area = _globals->_areaPtr;
addToParty(PER_MAMMI);
_persons[PER_MAMMI]._flags |= PersonFlags::pf10;
area->_flags |= AreaFlags::afFlag1;
_globals->_curAreaFlags |= AreaFlags::afFlag1;
}
void EdenGame::phase226() {
newObject(16, 3);
newObject(16, 4);
newObject(16, 5);
}
void EdenGame::phase257() {
_gameIcons[127]._cursorId &= ~0x8000;
_globals->_characterBackgroundBankIdx = 58;
dialautooff();
}
void EdenGame::phase353() {
removeFromParty(PER_DINA);
_persons[PER_DINA]._roomNum = 0;
_tabletView[1] = 88;
}
void EdenGame::phase369() {
addToParty(PER_ELOI);
_globals->_narratorSequence = 2;
_gameRooms[334]._exits[0] = 134;
_gameRooms[335]._exits[0] = 134;
}
void EdenGame::phase371() {
handleEloiReturn();
_gameIcons[128]._cursorId &= ~0x8000;
_gameIcons[129]._cursorId &= ~0x8000;
_gameIcons[127]._cursorId |= 0x8000;
_globals->_characterBackgroundBankIdx = 59;
_gameRooms[334]._exits[0] = 0xFF;
_gameRooms[335]._exits[0] = 0xFF;
_gameIcons[123]._objectId = 9;
_gameIcons[124]._objectId = 26;
_gameIcons[125]._objectId = 42;
_gameIcons[126]._objectId = 56;
}
void EdenGame::phase385() {
dialautooff();
handleEloiReturn();
_globals->_nextInfoIdx = 0;
_globals->_lastInfoIdx = 0;
updateInfoList();
_globals->_lastInfo = 0;
}
void EdenGame::phase418() {
loseObject(Objects::obHorn);
dialautoon();
addToParty(PER_JABBER);
}
void EdenGame::phase433() {
dialautoon();
_persons[PER_MAMMI_4]._flags &= ~PersonFlags::pf80;
_persons[PER_JABBER]._flags &= ~PersonFlags::pf80;
setCharacterHere();
_globals->_chronoFlag = 0;
_globals->_chrono = 0;
}
void EdenGame::phase434() {
_globals->_roomNum = 275;
_gameRooms[16]._bank = 44;
_gameRooms[18]._bank = 44;
_gameIcons[132]._cursorId &= ~0x8000;
_globals->_characterBackgroundBankIdx = 61;
_gameRooms[118]._exits[2] = 0xFF;
abortDialogue();
_gameRooms[7]._bank = 322;
removeFromParty(PER_EVE);
removeFromParty(PER_MONK);
removeFromParty(PER_ELOI);
removeFromParty(PER_GUARDS);
removeFromParty(PER_JABBER);
_globals->_drawFlags |= DrawFlags::drDrawTopScreen;
}
void EdenGame::phase513() {
_globals->_lastDialogPtr = nullptr;
parlemoiNormalFlag = false;
dialautoon();
}
void EdenGame::phase514() {
_gameRooms[123]._exits[2] = 1;
}
void EdenGame::phase529() {
_gameIcons[133]._cursorId &= ~0x8000;
_globals->_characterBackgroundBankIdx = 63;
}
void EdenGame::phase545() {
}
void EdenGame::phase561() {
_globals->_narratorSequence = 10;
}
void EdenGame::bigphase1() {
typedef void (EdenGame::*Phase)();
static const Phase bigphases[] = {
&EdenGame::phase16,
&EdenGame::phase32,
&EdenGame::phase48,
&EdenGame::phase64,
&EdenGame::phase80,
&EdenGame::phase96,
&EdenGame::phase112,
&EdenGame::phase128,
&EdenGame::phase144,
&EdenGame::phase160,
&EdenGame::phase176,
&EdenGame::phase192,
&EdenGame::phase208,
&EdenGame::phase224,
&EdenGame::phase240,
&EdenGame::phase256,
&EdenGame::phase272,
&EdenGame::phase288,
&EdenGame::phase304,
&EdenGame::phase320,
&EdenGame::phase336,
&EdenGame::phase352,
&EdenGame::phase368,
&EdenGame::phase384,
&EdenGame::phase400,
&EdenGame::phase416,
&EdenGame::phase432,
&EdenGame::phase448,
&EdenGame::phase464,
&EdenGame::phase480,
&EdenGame::phase496,
&EdenGame::phase512,
&EdenGame::phase528,
&EdenGame::phase544,
&EdenGame::phase560
};
int16 phase = (_globals->_phaseNum & ~3) + 0x10; //TODO: check me
debug("!!! big phase - %4X", phase);
_globals->_phaseActionsCount = 0;
_globals->_phaseNum = phase;
if (phase > 560)
return;
phase >>= 4;
(this->*bigphases[phase - 1])();
}
void EdenGame::bigphase() {
if (!(_globals->_dialogPtr->_flags & DialogFlags::dfSpoken))
bigphase1();
}
void EdenGame::phase16() {
dialautoon();
}
void EdenGame::phase32() {
word_31E7A &= ~0x8000;
}
void EdenGame::phase48() {
_gameRooms[8]._exits[1] = 22;
dialautoon();
}
void EdenGame::phase64() {
addToParty(PER_DINA);
_persons[PER_ELOI]._roomNum = 259;
}
void EdenGame::phase80() {
_persons[PER_TAU]._roomNum = 0;
}
void EdenGame::phase96() {
}
void EdenGame::phase112() {
giveObject();
}
void EdenGame::phase128() {
addToParty(PER_DINA);
giveObject();
}
void EdenGame::phase144() {
addToParty(PER_ELOI);
_gameRooms[113]._video = 0;
_gameRooms[113]._bank = 317;
}
void EdenGame::phase160() {
}
void EdenGame::phase176() {
dialonfollow();
}
void EdenGame::phase192() {
Area *area = _globals->_areaPtr;
addToParty(PER_MAMMI_1);
_persons[PER_MAMMI_1]._flags |= PersonFlags::pf10;
dialautoon();
area->_flags |= AreaFlags::afFlag1;
_globals->_curAreaFlags |= AreaFlags::afFlag1;
}
void EdenGame::phase208() {
handleEloiReturn();
}
void EdenGame::phase224() {
_gameIcons[126]._cursorId &= ~0x8000;
_globals->_characterBackgroundBankIdx = 57;
dialautooff();
}
void EdenGame::phase240() {
Area *area = _globals->_areaPtr;
addToParty(PER_MAMMI_2);
_persons[PER_MAMMI_2]._flags |= PersonFlags::pf10;
area->_flags |= AreaFlags::afFlag1;
_globals->_curAreaFlags |= AreaFlags::afFlag1;
}
void EdenGame::phase256() {
dialautoon();
}
void EdenGame::phase272() {
dialautoon();
_globals->_eloiHaveNews = 0;
}
void EdenGame::phase288() {
setChoiceYes();
_persons[PER_MUNGO]._roomNum = 0;
removeFromParty(PER_MUNGO);
addToParty(PER_ELOI);
_globals->_narratorSequence = 8;
}
void EdenGame::phase304() {
Area *area = _globals->_areaPtr;
addToParty(PER_EVE);
addToParty(PER_MAMMI_5);
_persons[PER_MAMMI_5]._flags |= PersonFlags::pf10;
dialautoon();
area->_flags |= AreaFlags::afFlag1;
_globals->_curAreaFlags |= AreaFlags::afFlag1;
}
void EdenGame::phase320() {
dialonfollow();
}
void EdenGame::phase336() {
_gameRooms[288]._exits[0] = 135;
_gameRooms[289]._exits[0] = 135;
loseObject(_globals->_curObjectId);
dialautoon();
}
void EdenGame::phase352() {
_personRoomBankTable[30] = 26;
_persons[PER_EVE]._spriteBank = 9;
_persons[PER_EVE]._targetLoc = 8;
_followerList[13]._spriteNum = 2;
dialautoon();
_gameRooms[288]._exits[0] = 0xFF;
_gameRooms[289]._exits[0] = 0xFF;
_gameRooms[288]._flags &= ~RoomFlags::rf02;
_gameRooms[289]._flags &= ~RoomFlags::rf02;
}
void EdenGame::phase368() {
removeFromParty(PER_EVE);
dialautoon();
_persons[PER_ELOI]._roomNum = 1811;
_persons[PER_DINA]._roomNum = 1607;
}
void EdenGame::phase384() {
Area *area = _globals->_areaPtr;
addToParty(PER_EVE);
removeFromParty(PER_DINA);
dialautoon();
area->_flags |= AreaFlags::afFlag1;
_globals->_curAreaFlags |= AreaFlags::afFlag1;
handleEloiDeparture();
}
void EdenGame::phase400() {
dialonfollow();
_persons[PER_KING]._roomNum = 0;
_persons[PER_MONK]._roomNum = 259;
_globals->_eloiHaveNews = 0;
_objectLocations[20] = 259;
}
void EdenGame::phase416() {
addToParty(PER_MONK);
_gameIcons[130]._cursorId &= ~0x8000;
_globals->_characterBackgroundBankIdx = 60;
_gameRooms[0]._exits[0] = 138;
}
void EdenGame::phase432() {
_globals->_narratorSequence = 3;
_persons[PER_MAMMI_4]._flags |= PersonFlags::pf80;
_persons[PER_JABBER]._flags |= PersonFlags::pf80;
_persons[PER_ELOI]._roomNum = 257;
_gameRooms[0]._exits[0] = 0xFF;
_globals->_drawFlags |= DrawFlags::drDrawTopScreen;
}
void EdenGame::phase448() {
dialautoon();
handleEloiDeparture();
}
void EdenGame::phase464() {
_globals->_areaPtr->_flags |= AreaFlags::afFlag1;
_globals->_curAreaFlags |= AreaFlags::afFlag1;
_persons[PER_MAMMI_6]._flags |= PersonFlags::pf10;
addToParty(PER_SHAZIA);
_globals->_citadelAreaNum = _globals->_areaNum;
naitredino(8);
}
void EdenGame::phase480() {
giveObject();
newValley();
handleEloiReturn();
_tabletView[1] = 94;
}
void EdenGame::phase496() {
dialautoon();
_globals->_lastDialogPtr = nullptr;
parlemoiNormalFlag = false;
}
void EdenGame::phase512() {
removeFromParty(PER_MONK);
removeFromParty(PER_EVE);
removeFromParty(PER_SHAZIA);
removeFromParty(PER_GUARDS);
}
void EdenGame::phase528() {
_globals->_narratorSequence = 11;
addToParty(PER_MONK);
addToParty(PER_ELOI);
addToParty(PER_EVE);
addToParty(PER_SHAZIA);
addToParty(PER_GUARDS);
}
void EdenGame::phase544() {
handleEloiDeparture();
dialautoon();
removeFromParty(PER_SHAZIA);
removeFromParty(PER_GUARDS);
}
void EdenGame::phase560() {
_persons[PER_ELOI]._roomNum = 3073;
_gameRooms[127]._exits[1] = 0;
}
void EdenGame::saveGame(char *name) {
Common::OutSaveFile *fh = g_system->getSavefileManager()->openForSaving(name);
if (!fh)
return;
Common::Serializer s(nullptr, fh);
syncGame(s);
delete fh;
}
void EdenGame::syncGame(Common::Serializer s) {
syncGlobalPointers(s);
syncGlobalValues(s);
// _gameIcons
// CHECKME: only from #123 to #133?
for (int i = 123; i < 134; i++) {
s.syncAsSint16LE(_gameIcons[i].sx);
s.syncAsSint16LE(_gameIcons[i].sy);
s.syncAsSint16LE(_gameIcons[i].ex);
s.syncAsSint16LE(_gameIcons[i].ey);
s.syncAsUint16LE(_gameIcons[i]._cursorId);
s.syncAsUint16LE(_gameIcons[i]._actionId);
s.syncAsUint16LE(_gameIcons[i]._objectId);
}
syncCitadelRoomPointers(s);
// _areasTable
for (int i = 0; i < 12; i++) {
s.syncAsByte(_areasTable[i]._num);
s.syncAsByte(_areasTable[i]._type);
s.syncAsUint16LE(_areasTable[i]._flags);
s.syncAsUint16LE(_areasTable[i]._firstRoomIdx);
s.syncAsByte(_areasTable[i]._citadelLevel);
s.syncAsByte(_areasTable[i]._placeNum);
s.syncAsSint16LE(_areasTable[i]._visitCount);
}
// _gameRooms
for (int i = 0; i < 423; i++) {
s.syncAsByte(_gameRooms[i]._id);
for (int j = 0; j < 4; j++)
s.syncAsByte(_gameRooms[i]._exits[j]);
s.syncAsByte(_gameRooms[i]._flags);
s.syncAsUint16LE(_gameRooms[i]._bank);
s.syncAsUint16LE(_gameRooms[i]._party);
s.syncAsByte(_gameRooms[i]._level);
s.syncAsByte(_gameRooms[i]._video);
s.syncAsByte(_gameRooms[i]._location);
s.syncAsByte(_gameRooms[i]._backgroundBankNum);
}
// _Objects
for (int i = 0; i < 42; i++) {
s.syncAsByte(_objects[i]._id);
s.syncAsByte(_objects[i]._flags);
s.syncAsSint16LE(_objects[i]._locations);
s.syncAsUint16LE(_objects[i]._itemMask);
s.syncAsUint16LE(_objects[i]._powerMask);
s.syncAsSint16LE(_objects[i]._count);
}
for (int i = 0; i < 45; i++)
s.syncAsUint16LE(_objectLocations[i]);
// _followerList[13]
// CHECKME: Only #13?
s.syncAsByte(_followerList[13]._id);
s.syncAsByte(_followerList[13]._spriteNum);
s.syncAsSint16LE(_followerList[13].sx);
s.syncAsSint16LE(_followerList[13].sy);
s.syncAsSint16LE(_followerList[13].ex);
s.syncAsSint16LE(_followerList[13].ey);
s.syncAsSint16LE(_followerList[13]._spriteBank);
s.syncAsSint16LE(_followerList[13].ff_C);
s.syncAsSint16LE(_followerList[13].ff_E);
// _persons
for (int i = 0; i < 58; i++) {
s.syncAsUint16LE(_persons[i]._roomNum);
s.syncAsUint16LE(_persons[i]._actionId);
s.syncAsUint16LE(_persons[i]._partyMask);
s.syncAsByte(_persons[i]._id);
s.syncAsByte(_persons[i]._flags);
s.syncAsByte(_persons[i]._roomBankId);
s.syncAsByte(_persons[i]._spriteBank);
s.syncAsUint16LE(_persons[i]._items);
s.syncAsUint16LE(_persons[i]._powers);
s.syncAsByte(_persons[i]._targetLoc);
s.syncAsByte(_persons[i]._lastLoc);
s.syncAsByte(_persons[i]._speed);
s.syncAsByte(_persons[i]._steps);
}
syncTapePointers(s);
// _tapes
for (int i = 0; i < MAX_TAPES; i++) {
s.syncAsSint16LE(_tapes[i]._textNum);
s.syncAsSint16LE(_tapes[i]._party);
s.syncAsSint16LE(_tapes[i]._roomNum);
s.syncAsSint16LE(_tapes[i]._backgroundBankNum);
}
// _tabletView
// CHECKME: Only 6 out of 12?
for (int i = 0; i < 6; i++)
s.syncAsByte(_tabletView[i]);
// _gameDialogs
for (int i = 0; i < 10240; i++)
s.syncAsByte(_gameDialogs[i]);
}
void EdenGame::loadrestart() {
_quitFlag3 = true;
/*
assert(0); //TODO: this won't work atm - all snapshots are BE
int32 offs = 0;
int32 size;
size = (char *)(&_globals->_saveEnd) - (char *)(_globals);
loadpartoffile(2495, _globals, offs, size);
offs += size;
vavaoffsetin();
size = (char *)(&_gameIcons[134]) - (char *)(&_gameIcons[123]);
loadpartoffile(2495, &_gameIcons[123], offs, size);
offs += size;
size = (char *)(&_areasTable[12]) - (char *)(&_areasTable[0]);
loadpartoffile(2495, &_areasTable[0], offs, size);
offs += size;
lieuoffsetin();
size = (char *)(&_gameRooms[423]) - (char *)(&_gameRooms[0]);
loadpartoffile(2495, &_gameRooms[0], offs, size);
offs += size;
size = (char *)(&_objects[42]) - (char *)(&_objects[0]);
loadpartoffile(2495, &_objects[0], offs, size);
offs += size;
size = (char *)(&_objectLocations[45]) - (char *)(&_objectLocations[0]);
loadpartoffile(2495, &_objectLocations[0], offs, size);
offs += size;
size = (char *)(&_followerList[14]) - (char *)(&_followerList[13]);
loadpartoffile(2495, &_followerList[13], offs, size);
offs += size;
size = (char *)(&_persons[PER_UNKN_3DE]) - (char *)(&_persons[PER_KING]);
loadpartoffile(2495, &_persons[PER_KING], offs, size);
offs += size;
size = (char *)(&_tapes[16]) - (char *)(&_tapes[0]);
loadpartoffile(2495, &_tapes[0], offs, size);
offs += size;
bandeoffsetin();
size = (char *)(&_tabletView[6]) - (char *)(&_tabletView[0]);
loadpartoffile(2495, &_tabletView[0], offs, size);
offs += size;
size = (char *)(&_gameDialogs[10240]) - (char *)(&_gameDialogs[0]); //TODO: const size 10240
loadpartoffile(2495, &_gameDialogs[0], offs, size);
_gameLoaded = true;
*/
}
void EdenGame::loadgame(char *name) {
Common::InSaveFile *fh = g_system->getSavefileManager()->openForLoading(name);
if (!fh)
return;
Common::Serializer s(fh, nullptr);
syncGame(s);
delete fh;
_gameLoaded = true;
}
#define NULLPTR 0xFFFFFF
#define IDXOUT(val, base, typ, idx) do { if (val) (idx) = ((byte*)val - (byte*)base) / sizeof(typ); else (idx) = NULLPTR; } while (false)
#define OFSIN(val, base, typ) do { if ((void*)(val) != NULLPTR) (val) = (typ*)((char*)(val) + (size_t)(base)); else (val) = 0; } while (false)
void EdenGame::syncGlobalPointers(Common::Serializer s) {
uint32 dialogIdx = 0, nextDialogIdx = 0, narratorDialogIdx = 0, lastDialogIdx = 0, tapeIdx = 0, nextRoomIconIdx = 0, roomIdx = 0;
uint32 citaAreaFirstRoomIdx = 0, areaIdx = 0, lastAreaIdx = 0, curAreaIdx = 0, characterIdx = 0, roomCharacterIdx = 0;
if (s.isSaving()) {
IDXOUT(_globals->_dialogPtr, _gameDialogs, Dialog, dialogIdx);
IDXOUT(_globals->_nextDialogPtr, _gameDialogs, Dialog, nextDialogIdx);
IDXOUT(_globals->_narratorDialogPtr, _gameDialogs, Dialog, narratorDialogIdx);
IDXOUT(_globals->_lastDialogPtr, _gameDialogs, Dialog, lastDialogIdx);
IDXOUT(_globals->_tapePtr, _tapes, tape_t, tapeIdx);
IDXOUT(_globals->_nextRoomIcon, _gameIcons, Icon, nextRoomIconIdx);
IDXOUT(_globals->_roomPtr, _gameRooms, Room, roomIdx);
IDXOUT(_globals->_citaAreaFirstRoom, _gameRooms, Room, citaAreaFirstRoomIdx);
IDXOUT(_globals->_areaPtr, _areasTable, Area, areaIdx);
IDXOUT(_globals->_lastAreaPtr, _areasTable, Area, lastAreaIdx);
IDXOUT(_globals->_curAreaPtr, _areasTable, Area, curAreaIdx);
IDXOUT(_globals->_characterPtr, _persons, perso_t, characterIdx);
IDXOUT(_globals->_roomCharacterPtr, _persons, perso_t, roomCharacterIdx);
}
s.syncAsUint32LE(dialogIdx);
s.syncAsUint32LE(nextDialogIdx);
s.syncAsUint32LE(narratorDialogIdx);
s.syncAsUint32LE(lastDialogIdx);
s.syncAsUint32LE(tapeIdx);
s.syncAsUint32LE(nextRoomIconIdx);
s.syncAsUint32LE(roomIdx);
s.syncAsUint32LE(citaAreaFirstRoomIdx);
s.syncAsUint32LE(areaIdx);
s.syncAsUint32LE(lastAreaIdx);
s.syncAsUint32LE(curAreaIdx);
s.syncAsUint32LE(characterIdx);
s.syncAsUint32LE(roomCharacterIdx);
if (s.isLoading()) {
_globals->_dialogPtr = (dialogIdx == NULLPTR) ? nullptr : (Dialog *)getElem(_gameDialogs, dialogIdx);
_globals->_nextDialogPtr = (nextDialogIdx == NULLPTR) ? nullptr : (Dialog *)getElem(_gameDialogs, nextDialogIdx);
_globals->_narratorDialogPtr = (narratorDialogIdx == NULLPTR) ? nullptr : (Dialog *)getElem(_gameDialogs, narratorDialogIdx);
_globals->_lastDialogPtr = (lastDialogIdx == NULLPTR) ? nullptr : (Dialog *)getElem(_gameDialogs, lastDialogIdx);
_globals->_tapePtr = (tapeIdx == NULLPTR) ? nullptr : &_tapes[tapeIdx];
_globals->_nextRoomIcon = (nextRoomIconIdx == NULLPTR) ? nullptr : &_gameIcons[nextRoomIconIdx];
_globals->_roomPtr = (roomIdx == NULLPTR) ? nullptr : &_gameRooms[roomIdx];
_globals->_citaAreaFirstRoom = (citaAreaFirstRoomIdx == NULLPTR) ? nullptr : &_gameRooms[citaAreaFirstRoomIdx];
_globals->_areaPtr = (areaIdx == NULLPTR) ? nullptr : &_areasTable[areaIdx];
_globals->_lastAreaPtr = (lastAreaIdx == NULLPTR) ? nullptr : &_areasTable[lastAreaIdx];
_globals->_curAreaPtr = (curAreaIdx == NULLPTR) ? nullptr : &_areasTable[curAreaIdx];
_globals->_characterPtr = (characterIdx == NULLPTR) ? nullptr : &_persons[characterIdx];
_globals->_roomCharacterPtr = (roomCharacterIdx == NULLPTR) ? nullptr : &_persons[roomCharacterIdx];
}
}
void EdenGame::syncGlobalValues(Common::Serializer s) {
s.syncAsByte(_globals->_areaNum);
s.syncAsByte(_globals->_areaVisitCount);
s.syncAsByte(_globals->_menuItemIdLo);
s.syncAsByte(_globals->_menuItemIdHi);
s.syncAsUint16LE(_globals->_randomNumber);
s.syncAsUint16LE(_globals->_gameTime);
s.syncAsUint16LE(_globals->_gameDays);
s.syncAsUint16LE(_globals->_chrono);
s.syncAsUint16LE(_globals->_eloiDepartureDay);
s.syncAsUint16LE(_globals->_roomNum);
s.syncAsUint16LE(_globals->_newRoomNum);
s.syncAsUint16LE(_globals->_phaseNum);
s.syncAsUint16LE(_globals->_metPersonsMask1);
s.syncAsUint16LE(_globals->_party);
s.syncAsUint16LE(_globals->_partyOutside);
s.syncAsUint16LE(_globals->_metPersonsMask2);
s.syncAsUint16LE(_globals->_var1C);
s.syncAsUint16LE(_globals->_phaseActionsCount);
s.syncAsUint16LE(_globals->_curAreaFlags);
s.syncAsUint16LE(_globals->_curItemsMask);
s.syncAsUint16LE(_globals->_curPowersMask);
s.syncAsUint16LE(_globals->_curPersoItems);
s.syncAsUint16LE(_globals->_curCharacterPowers);
s.syncAsUint16LE(_globals->_wonItemsMask);
s.syncAsUint16LE(_globals->_wonPowersMask);
s.syncAsUint16LE(_globals->_stepsToFindAppleFast);
s.syncAsUint16LE(_globals->_stepsToFindAppleNormal);
s.syncAsUint16LE(_globals->_roomPersoItems);
s.syncAsUint16LE(_globals->_roomCharacterPowers);
s.syncAsUint16LE(_globals->_gameFlags);
s.syncAsUint16LE(_globals->_curVideoNum);
s.syncAsUint16LE(_globals->_morkusSpyVideoNum1);
s.syncAsUint16LE(_globals->_morkusSpyVideoNum2);
s.syncAsUint16LE(_globals->_morkusSpyVideoNum3);
s.syncAsUint16LE(_globals->_morkusSpyVideoNum4);
s.syncAsByte(_globals->_newMusicType);
s.syncAsByte(_globals->_var43);
s.syncAsByte(_globals->_videoSubtitleIndex);
s.syncAsByte(_globals->_partyInstruments);
s.syncAsByte(_globals->_monkGotRing);
s.syncAsByte(_globals->_chronoFlag);
s.syncAsByte(_globals->_curRoomFlags);
s.syncAsByte(_globals->_endGameFlag);
s.syncAsByte(_globals->_lastInfo);
byte autoDialog = 0;
if (s.isSaving())
autoDialog = _globals->_autoDialog ? 1 : 0;
s.syncAsByte(autoDialog);
if (s.isLoading())
_globals->_autoDialog = (autoDialog == 1);
s.syncAsByte(_globals->_worldTyranSighted);
s.syncAsByte(_globals->_var4D);
s.syncAsByte(_globals->_var4E);
s.syncAsByte(_globals->_worldGaveGold);
s.syncAsByte(_globals->_worldHasTriceraptors);
s.syncAsByte(_globals->_worldHasVelociraptors);
s.syncAsByte(_globals->_worldHasTyran);
s.syncAsByte(_globals->_var53);
s.syncAsByte(_globals->_var54);
s.syncAsByte(_globals->_var55);
s.syncAsByte(_globals->_gameHours);
s.syncAsByte(_globals->_textToken1);
s.syncAsByte(_globals->_textToken2);
s.syncAsByte(_globals->_eloiHaveNews);
s.syncAsByte(_globals->_dialogFlags);
s.syncAsByte(_globals->_curAreaType);
s.syncAsByte(_globals->_curCitadelLevel);
s.syncAsByte(_globals->_newLocation);
s.syncAsByte(_globals->_prevLocation);
s.syncAsByte(_globals->_curPersoFlags);
s.syncAsByte(_globals->_var60);
s.syncAsByte(_globals->_eventType);
s.syncAsByte(_globals->_var62);
s.syncAsByte(_globals->_curObjectId);
s.syncAsByte(_globals->_curObjectFlags);
s.syncAsByte(_globals->_var65);
s.syncAsByte(_globals->_roomCharacterType);
s.syncAsByte(_globals->_roomCharacterFlags);
s.syncAsByte(_globals->_narratorSequence);
s.syncAsByte(_globals->_var69);
s.syncAsByte(_globals->_var6A);
s.syncAsByte(_globals->_frescoNumber);
s.syncAsByte(_globals->_var6C);
s.syncAsByte(_globals->_var6D);
s.syncAsByte(_globals->_labyrinthDirections);
s.syncAsByte(_globals->_labyrinthRoom);
/*
CHECKME: *_sentenceBufferPtr
*/
s.syncAsByte(_globals->_lastInfoIdx);
s.syncAsByte(_globals->_nextInfoIdx);
/*
CHECKME
* _persoSpritePtr
* _persoSpritePtr2
* _curCharacterAnimPtr
* _varC2
*/
s.syncAsSint16LE(_globals->_iconsIndex);
s.syncAsSint16LE(_globals->_curObjectCursor);
s.syncAsSint16LE(_globals->_varCA);
s.syncAsSint16LE(_globals->_varCC);
s.syncAsSint16LE(_globals->_characterImageBank);
s.syncAsUint16LE(_globals->_roomImgBank);
s.syncAsUint16LE(_globals->_characterBackgroundBankIdx);
s.syncAsUint16LE(_globals->_varD4);
s.syncAsUint16LE(_globals->_frescoeWidth);
s.syncAsUint16LE(_globals->_frescoeImgBank);
s.syncAsUint16LE(_globals->_varDA);
s.syncAsUint16LE(_globals->_varDC);
s.syncAsUint16LE(_globals->_roomBaseX);
s.syncAsUint16LE(_globals->_varE0);
s.syncAsUint16LE(_globals->_dialogType);
s.syncAsUint16LE(_globals->_varE4);
s.syncAsUint16LE(_globals->_currMusicNum);
s.syncAsSint16LE(_globals->_textNum);
s.syncAsUint16LE(_globals->_travelTime);
s.syncAsUint16LE(_globals->_varEC);
s.syncAsByte(_globals->_displayFlags);
s.syncAsByte(_globals->_oldDisplayFlags);
s.syncAsByte(_globals->_drawFlags);
s.syncAsByte(_globals->_varF1);
s.syncAsByte(_globals->_varF2);
s.syncAsByte(_globals->_menuFlags);
s.syncAsByte(_globals->_varF4);
s.syncAsByte(_globals->_varF5);
s.syncAsByte(_globals->_varF6);
s.syncAsByte(_globals->_varF7);
s.syncAsByte(_globals->_varF8);
s.syncAsByte(_globals->_varF9);
s.syncAsByte(_globals->_varFA);
s.syncAsByte(_globals->_animationFlags);
s.syncAsByte(_globals->_giveObj1);
s.syncAsByte(_globals->_giveObj2);
s.syncAsByte(_globals->_giveObj3);
s.syncAsByte(_globals->_var100);
s.syncAsByte(_globals->_roomVidNum);
s.syncAsByte(_globals->_mirrorEffect);
s.syncAsByte(_globals->_var103);
s.syncAsByte(_globals->_roomBackgroundBankNum);
s.syncAsByte(_globals->_valleyVidNum);
s.syncAsByte(_globals->_updatePaletteFlag);
s.syncAsByte(_globals->_inventoryScrollPos);
s.syncAsByte(_globals->_objCount);
s.syncAsByte(_globals->_textBankIndex);
s.syncAsByte(_globals->_prefLanguage);
for (int i = 0; i < 2; i++) {
s.syncAsByte(_globals->_prefMusicVol[i]);
s.syncAsByte(_globals->_prefVoiceVol[i]);
s.syncAsByte(_globals->_prefSoundVolume[i]);
}
s.syncAsByte(_globals->_citadelAreaNum);
s.syncAsByte(_globals->_var113);
s.syncAsByte(_globals->_lastPlaceNum);
s.syncAsByte(_globals->_saveEnd);
}
void EdenGame::syncCitadelRoomPointers(Common::Serializer s) {
uint32 citadelRoomIdx = 0;
for (int i = 0; i < 12; i++) {
if (s.isSaving()) {
IDXOUT(_areasTable[i]._citadelRoomPtr, _gameRooms, Room, citadelRoomIdx);
}
s.syncAsUint32LE(citadelRoomIdx);
if (s.isLoading())
_areasTable[i]._citadelRoomPtr = (citadelRoomIdx == NULLPTR) ? nullptr : &_gameRooms[citadelRoomIdx];
}
}
void EdenGame::syncTapePointers(Common::Serializer s) {
int persoIdx = 0;
for (int i = 0; i < 16; i++) {
int index = 0, subIndex = 0;
if (s.isSaving()) {
index = NULLPTR;
char *closerPtr = nullptr;
for (int j = (getElem((char *)_gameDialogs, 0) - (char *)_gameDialogs) / sizeof(char *) - 1; j >= 0; j--) {
char *tmpPtr = getElem((char *)_gameDialogs, j);
if ((tmpPtr <= (char *)_tapes[i]._dialog) && (tmpPtr > closerPtr)) {
index = j;
closerPtr = tmpPtr;
}
}
subIndex = NULLPTR;
if (index != NULLPTR)
subIndex = ((char *)_tapes[i]._dialog - closerPtr);
IDXOUT(_tapes[i]._perso, _persons, perso_t, persoIdx);
}
s.syncAsUint32LE(persoIdx);
s.syncAsUint32LE(index);
s.syncAsUint32LE(subIndex);
if (s.isLoading()) {
_tapes[i]._perso = (persoIdx == NULLPTR) ? nullptr : &_persons[persoIdx];
char *tmpPtr = nullptr;
if (index != NULLPTR) {
tmpPtr = getElem((char *)_gameDialogs, index);
if (subIndex != NULLPTR)
tmpPtr += subIndex;
}
_tapes[i]._dialog = (Dialog *)tmpPtr;
}
}
}
char EdenGame::testCondition(int16 index) {
bool endFl = false;
uint16 stack[32];
uint16 *sp = stack;
assert(index > 0);
_codePtr = (byte *)getElem(_gameConditions, (index - 1));
uint16 value;
do {
value = fetchValue();
for (;;) {
byte op = *_codePtr++;
if (op == 0xFF) {
endFl = true;
break;
}
if ((op & 0x80) == 0) {
uint16 value2 = fetchValue();
value = operation(op, value, value2);
} else {
assert(sp < stack + 32);
*sp++ = value;
*sp++ = op;
break;
}
}
} while (!endFl);
if (sp != stack) {
*sp++ = value;
uint16 *sp2 = stack;
value = *sp2++;
do {
byte op = *sp2++;
uint16 value2 = *sp2++;
value = operation(op, value, value2);
} while (sp2 != sp);
}
// if (value)
debug("cond %d(-1) returns %s", index, value ? "TRUE" : "false");
// if (index == 402) debug("(glob_61.b == %X) & (glob_12.w == %X) & (glob_4C.b == %X) & (glob_4E.b == %X)", p_global->eventType, p_global->phaseNum, p_global->worldTyrannSighted, p_global->ff_4E);
return value != 0;
}
// Original name: opera_add
uint16 EdenGame::operAdd(uint16 v1, uint16 v2) {
return v1 + v2;
}
// Original name: opera_sub
uint16 EdenGame::operSub(uint16 v1, uint16 v2) {
return v1 - v2;
}
// Original name: opera_and
uint16 EdenGame::operLogicalAnd(uint16 v1, uint16 v2) {
return v1 & v2;
}
// Original name: opera_or
uint16 EdenGame::operLogicalOr(uint16 v1, uint16 v2) {
return v1 | v2;
}
// Original name: opera_egal
uint16 EdenGame::operIsEqual(uint16 v1, uint16 v2) {
return v1 == v2 ? -1 : 0;
}
// Original name: opera_petit
uint16 EdenGame::operIsSmaller(uint16 v1, uint16 v2) {
return v1 < v2 ? -1 : 0; //TODO: all comparisons are unsigned!
}
// Original name: opera_grand
uint16 EdenGame::operIsGreater(uint16 v1, uint16 v2) {
return v1 > v2 ? -1 : 0;
}
// Original name: opera_diff
uint16 EdenGame::operIsDifferent(uint16 v1, uint16 v2) {
return v1 != v2 ? -1 : 0;
}
// Original name: opera_petega
uint16 EdenGame::operIsSmallerOrEqual(uint16 v1, uint16 v2) {
return v1 <= v2 ? -1 : 0;
}
// Original name: opera_graega
uint16 EdenGame::operIsGreaterOrEqual(uint16 v1, uint16 v2) {
return v1 >= v2 ? -1 : 0;
}
// Original name: opera_faux
uint16 EdenGame::operFalse(uint16 v1, uint16 v2) {
return 0;
}
uint16 EdenGame::operation(byte op, uint16 v1, uint16 v2) {
typedef uint16 (EdenGame::*Operation)(uint16, uint16);
static const Operation operations[16] = {
&EdenGame::operIsEqual,
&EdenGame::operIsSmaller,
&EdenGame::operIsGreater,
&EdenGame::operIsDifferent,
&EdenGame::operIsSmallerOrEqual,
&EdenGame::operIsGreaterOrEqual,
&EdenGame::operAdd,
&EdenGame::operSub,
&EdenGame::operLogicalAnd,
&EdenGame::operLogicalOr,
&EdenGame::operFalse,
&EdenGame::operFalse,
&EdenGame::operFalse,
&EdenGame::operFalse,
&EdenGame::operFalse,
&EdenGame::operFalse
};
return (this->*operations[(op & 0x1F) >> 1])(v1, v2);
}
#define VAR(ofs, var) case ofs: return _globals->var;
uint8 EdenGame::getByteVar(uint16 offset) {
switch (offset) {
VAR(0, _areaNum);
VAR(1, _areaVisitCount);
VAR(2, _menuItemIdLo);
VAR(3, _menuItemIdHi); //TODO: pad?
VAR(0x42, _newMusicType);
VAR(0x43, _var43);
VAR(0x44, _videoSubtitleIndex);
VAR(0x45, _partyInstruments); // &1 - Bell for Monk, &2 - Drum for Thugg
VAR(0x46, _monkGotRing);
VAR(0x47, _chronoFlag);
VAR(0x48, _curRoomFlags);
VAR(0x49, _endGameFlag);
VAR(0x4A, _lastInfo);
VAR(0x4B, _autoDialog);
VAR(0x4C, _worldTyranSighted);
VAR(0x4D, _var4D);
VAR(0x4E, _var4E);
VAR(0x4F, _worldGaveGold);
VAR(0x50, _worldHasTriceraptors);
VAR(0x51, _worldHasVelociraptors);
VAR(0x52, _worldHasTyran);
VAR(0x53, _var53);
VAR(0x54, _var54); //CHEKME: Used?
VAR(0x55, _var55); //TODO: pad?
VAR(0x56, _gameHours);
VAR(0x57, _textToken1);
VAR(0x58, _textToken2); //TODO: pad?
VAR(0x59, _eloiHaveNews);
VAR(0x5A, _dialogFlags);
VAR(0x5B, _curAreaType);
VAR(0x5C, _curCitadelLevel);
VAR(0x5D, _newLocation);
VAR(0x5E, _prevLocation);
VAR(0x5F, _curPersoFlags);
VAR(0x60, _var60);
VAR(0x61, _eventType);
VAR(0x62, _var62); //TODO: pad?
VAR(0x63, _curObjectId);
VAR(0x64, _curObjectFlags);
VAR(0x65, _var65); //TODO: pad?
VAR(0x66, _roomCharacterType);
VAR(0x67, _roomCharacterFlags);
VAR(0x68, _narratorSequence);
VAR(0x69, _var69);
VAR(0x6A, _var6A);
VAR(0x6B, _frescoNumber);
VAR(0x6C, _var6C); //TODO: pad?
VAR(0x6D, _var6D); //TODO: pad?
VAR(0x6E, _labyrinthDirections);
VAR(0x6F, _labyrinthRoom);
default:
error("Undefined byte variable access (0x%X)", offset);
}
return 0;
}
uint16 EdenGame::getWordVar(uint16 offset) {
switch (offset) {
VAR(4, _randomNumber); //TODO: this is randomized in pc ver and used by some conds. always zero on mac
VAR(6, _gameTime);
VAR(8, _gameDays);
VAR(0xA, _chrono);
VAR(0xC, _eloiDepartureDay);
VAR(0xE, _roomNum); // current room number
VAR(0x10, _newRoomNum); // target room number selected on world map
VAR(0x12, _phaseNum);
VAR(0x14, _metPersonsMask1);
VAR(0x16, _party);
VAR(0x18, _partyOutside);
VAR(0x1A, _metPersonsMask2);
VAR(0x1C, _var1C); //TODO: write-only?
VAR(0x1E, _phaseActionsCount);
VAR(0x20, _curAreaFlags);
VAR(0x22, _curItemsMask);
VAR(0x24, _curPowersMask);
VAR(0x26, _curPersoItems);
VAR(0x28, _curCharacterPowers);
VAR(0x2A, _wonItemsMask);
VAR(0x2C, _wonPowersMask);
VAR(0x2E, _stepsToFindAppleFast);
VAR(0x30, _stepsToFindAppleNormal);
VAR(0x32, _roomPersoItems); //TODO: write-only?
VAR(0x34, _roomCharacterPowers); //TODO: write-only?
VAR(0x36, _gameFlags);
VAR(0x38, _curVideoNum);
VAR(0x3A, _morkusSpyVideoNum1); //TODO: pad?
VAR(0x3C, _morkusSpyVideoNum2); //TODO: pad?
VAR(0x3E, _morkusSpyVideoNum3); //TODO: pad?
VAR(0x40, _morkusSpyVideoNum4); //TODO: pad?
default:
error("Undefined word variable access (0x%X)", offset);
}
return 0;
}
#undef VAR
// Original name: cher_valeur
uint16 EdenGame::fetchValue() {
uint16 val;
byte typ = *_codePtr++;
if (typ < 0x80) {
byte ofs = *_codePtr++;
val = (typ == 1) ? getByteVar(ofs) : getWordVar(ofs);
} else if (typ == 0x80)
val = *_codePtr++;
else {
val = READ_LE_UINT16(_codePtr);
_codePtr += 2;
}
return val;
}
// Original name: ret
void EdenGame::actionNop() {
}
//// cube.c
// Original name: make_tabcos
void EdenGame::initSinCosTable() {
for (int i = 0; i < 361; i++) {
_cosTable[i] = (int)(cos(3.1416 * i / 180.0) * 255.0);
_sinTable[i] = (int)(sin(3.1416 * i / 180.0) * 255.0);
}
}
void EdenGame::makeMatriceFix() {
int16 rotAngleTheta = _rotationAngleX;
int16 rotAnglePhi = _rotationAngleY;
int16 rotAnglePsi = _rotationAngleZ;
_passMat31 = (_cosTable[rotAnglePhi] * _cosTable[rotAngleTheta]) >> 8;
_passMat32 = (_sinTable[rotAnglePhi] * _cosTable[rotAngleTheta]) >> 8;
_passMat33 = -_sinTable[rotAngleTheta];
_passMat21 = ((-_sinTable[rotAnglePhi] * _cosTable[rotAnglePsi]) >> 8)
+ ((_sinTable[rotAnglePsi] * ((_cosTable[rotAnglePhi] * _sinTable[rotAngleTheta]) >> 8)) >> 8);
_passMat22 = ((_cosTable[rotAnglePhi] * _cosTable[rotAnglePsi]) >> 8)
+ ((_sinTable[rotAnglePsi] * ((_sinTable[rotAnglePhi] * _sinTable[rotAngleTheta]) >> 8)) >> 8);
_passMat23 = (_cosTable[rotAngleTheta] * _sinTable[rotAnglePsi]) >> 8;
_passMat11 = ((_sinTable[rotAnglePhi] * _sinTable[rotAnglePsi]) >> 8)
+ ((_cosTable[rotAnglePsi] * ((_cosTable[rotAnglePhi] * _sinTable[rotAngleTheta]) >> 8)) >> 8);
_passMat12 = ((-_cosTable[rotAnglePhi] * _sinTable[rotAnglePsi]) >> 8)
+ ((_cosTable[rotAnglePsi] * ((_sinTable[rotAnglePhi] * _sinTable[rotAngleTheta]) >> 8)) >> 8);
_passMat13 = (_cosTable[rotAngleTheta] * _cosTable[rotAnglePsi]) >> 8;
}
void EdenGame::projectionFix(Cube *cubep, int n) {
for (int i = 0; i < n; i++) {
int x = cubep->_vertices[i].x;
int y = cubep->_vertices[i].y;
int z = cubep->_vertices[i].z;
int transformX = _passMat31 * x + _passMat21 * y + _passMat11 * z + (int)(_translationX * 256.0F);
int transformY = _passMat32 * x + _passMat22 * y + _passMat12 * z + (int)(_translationY * 256.0F);
int transformZ = _passMat33 * x + _passMat23 * y + _passMat13 * z + (int)(_translationZ * 256.0F);
transformZ >>= 8;
if (transformZ == -256)
transformZ++;
cubep->_projection[i].x = transformX / (transformZ + 256) + _cursorPosX + 14 + _scrollPos;
cubep->_projection[i].y = transformY / (transformZ + 256) + _cursorPosY + 14;
cubep->_projection[i].z = transformZ;
}
}
// Original name init_cube
void EdenGame::initCubeMac() {
loadMap(2493, _cubeTexture);
NEWcharge_objet_mob(&_cube, 2494, _cubeTexture);
initSinCosTable();
}
void EdenGame::engineMac() {
Eden_dep_and_rot();
makeMatriceFix();
projectionFix(&_cube, _cubeFaces);
displayObject(&_cube);
}
// Original name: affiche_objet
void EdenGame::displayObject(Cube *cubep) {
for (int i = 0; i < cubep->_num; i++)
displayPolygoneMapping(cubep, cubep->_faces[i]);
}
// Original name: NEWcharge_map
void EdenGame::loadMap(int file_id, byte *buffer) {
if (_vm->getPlatform() == Common::kPlatformMacintosh) {
loadpartoffile(file_id, buffer, 32, 256 * 3);
_graphics->setPaletteColor(buffer);
loadpartoffile(file_id, buffer, 32 + 256 * 3, 0x4000);
} else {
#if 0
// Fake Mac cursor on PC
Common::File f;
if (f.open("curs.raw")) {
f.seek(32);
f.read(buffer, 256 * 3);
for (i = 0; i < 256; i++) {
color3_t color;
color.r = buffer[i * 3] << 8;
color.g = buffer[i * 3 + 1] << 8;
color.b = buffer[i * 3 + 2] << 8;
CLPalette_SetRGBColor(global_palette, i, &color);
}
CLPalette_Send2Screen(global_palette, 0, 256);
f.read(buffer, 0x4000);
f.close();
}
else
error("can not load cursor texture");
#endif
}
}
void EdenGame::NEWcharge_objet_mob(Cube *cubep, int fileNum, byte *texturePtr) {
char *tmp1 = new char[454];
if (_vm->getPlatform() == Common::kPlatformMacintosh)
loadpartoffile(fileNum, tmp1, 0, 454);
else {
#if 0
// Fake Mac cursor on PC
Common::File f;
if (f.open("curseden.mob")) {
f.read(tmp1, 454);
f.close();
}
else
::error("can not load cursor model");
#endif
}
char *next = tmp1;
char error;
_cubeFaces = nextVal(&next, &error);
Point3D *vertices = (Point3D *)malloc(_cubeFaces * sizeof(*vertices));
Point3D *projection = (Point3D *)malloc(_cubeFaces * sizeof(*projection));
for (int i = 0; i < _cubeFaces; i++) {
vertices[i].x = nextVal(&next, &error);
vertices[i].y = nextVal(&next, &error);
vertices[i].z = nextVal(&next, &error);
}
int count2 = nextVal(&next, &error);
CubeFace **tmp4 = (CubeFace **)malloc(count2 * sizeof(*tmp4));
for (int i = 0; i < count2; i++) {
tmp4[i] = (CubeFace *)malloc(sizeof(CubeFace));
tmp4[i]->tri = 3;
char textured = nextVal(&next, &error);
tmp4[i]->ff_5 = nextVal(&next, &error);
tmp4[i]->_indices = (uint16 *)malloc(3 * sizeof(*tmp4[i]->_indices));
tmp4[i]->_uv = (int16 *)malloc(3 * 2 * sizeof(*tmp4[i]->_uv));
for (int j = 0; j < 3; j++) {
tmp4[i]->_indices[j] = nextVal(&next, &error);
if (textured) {
tmp4[i]->_uv[j * 2] = nextVal(&next, &error);
tmp4[i]->_uv[j * 2 + 1] = nextVal(&next, &error);
}
}
if (textured) {
tmp4[i]->ff_4 = 3;
tmp4[i]->_texturePtr = texturePtr;
} else
tmp4[i]->ff_4 = 0;
}
delete[] tmp1;
cubep->_num = count2;
cubep->_faces = tmp4;
cubep->_projection = projection;
cubep->_vertices = vertices;
}
void EdenGame::DELETEcharge_objet_mob(Cube *cubep) {
for (int i = 0; i < cubep->_num; i++) {
free(cubep->_faces[i]->_indices);
free(cubep->_faces[i]->_uv);
free(cubep->_faces[i]);
}
free(cubep->_faces);
free(cubep->_projection);
free(cubep->_vertices);
}
int EdenGame::nextVal(char **ptr, char *error) {
char c = 0;
char *p = *ptr;
int val = strtol(p, nullptr, 10);
while ((*p >= '0' && *p <= '9' && *p != 0) || *p == '-')
p++;
while ((*p == 13 || *p == 10 || *p == ',' || *p == ' ') && *p)
c = *p++;
*error = c == 10;
*ptr = p;
return val;
}
void EdenGame::selectMap(int16 num) {
_cursCurPCMap = num;
int16 k = 0;
int mode = _mapMode[num];
int16 x = (num & 7) * 32;
int16 y = (num & 0x18) * 4;
for (int i = 0; i < 6 * 2; i++) {
for (int j = 0; j < 3; j++) {
_cube._faces[i]->_uv[j * 2 ] = x + _cubeTextureCoords[mode][k++];
_cube._faces[i]->_uv[j * 2 + 1] = y + _cubeTextureCoords[mode][k++];
}
}
}
void EdenGame::Eden_dep_and_rot() {
int16 curs = _currCursor;
if (_normalCursor && (_globals->_drawFlags & DrawFlags::drDrawFlag20))
curs = 10;
selectMap(curs);
_cursorNewTick = g_system->getMillis();
if (_cursorNewTick - _cursorOldTick < 1)
return;
_cursorOldTick = _cursorNewTick;
switch (_currCursor) {
case 0:
_rotationAngleZ = (_rotationAngleZ + 2) % 360;
_rotationAngleX = (_rotationAngleX + 2) % 360;
restoreZDEP();
break;
case 1:
_rotationAngleZ = 0;
_rotationAngleX -= 2;
if (_rotationAngleX < 0)
_rotationAngleX += 360;
restoreZDEP();
break;
case 2:
_rotationAngleZ = (_rotationAngleZ + 2) % 360;
_rotationAngleX = 0;
restoreZDEP();
break;
case 3:
_rotationAngleZ -= 2;
if (_rotationAngleZ < 0)
_rotationAngleZ += 360;
_rotationAngleX = 0;
restoreZDEP();
break;
case 4:
_rotationAngleZ = 0;
_rotationAngleX = (_rotationAngleX + 2) % 360;
restoreZDEP();
break;
case 5:
_rotationAngleZ = 0;
_rotationAngleX = 0;
_translationZ += _zDirection * Z_STEP;
if ((_translationZ < -3600 + Z_RESET) || _translationZ > Z_RESET)
_zDirection = -_zDirection;
break;
case 6:
_rotationAngleZ = 0;
_rotationAngleX = 0;
_translationZ = Z_RESET;
break;
case 7:
_rotationAngleZ -= 2;
if (_rotationAngleZ < 0)
_rotationAngleZ += 360;
_rotationAngleX = 0;
restoreZDEP();
break;
case 8:
_rotationAngleZ = 0;
_rotationAngleX = 0;
_translationZ = Z_RESET;
break;
case 9:
_rotationAngleZ = 0;
_rotationAngleX = 0;
_translationZ = Z_RESET;
break;
default:
break;
}
}
void EdenGame::restoreZDEP() {
_zDirection = Z_UP;
if (_translationZ < Z_RESET)
_translationZ += _zDirection * Z_STEP;
if (_translationZ > Z_RESET)
_translationZ -= _zDirection * Z_STEP;
}
// Original name: affiche_polygone_mapping
void EdenGame::displayPolygoneMapping(Cube *cubep, CubeFace *face) {
uint16 *indices = face->_indices;
int idx = indices[0];
int16 projX0 = cubep->_projection[idx].x;
int16 projY0 = cubep->_projection[idx].y;
idx = indices[1];
int16 projX1 = cubep->_projection[idx].x;
int16 projY1 = cubep->_projection[idx].y;
idx = indices[2];
int16 projX2 = cubep->_projection[idx].x;
int16 projY2 = cubep->_projection[idx].y;
if ((projY1 - projY0) * (projX2 - projX0) - (projY2 - projY0) * (projX1 - projX0) > 0)
return;
int16 *uv = face->_uv;
int16 ymin = 200; // min y
int16 ymax = 0; // max y
idx = indices[0];
int16 r20 = cubep->_projection[idx].x;
int16 r30 = cubep->_projection[idx].y;
int16 r19 = *uv++;
int16 r18 = *uv++;
indices++;
for (int i = 0; i < face->tri - 1; i++, indices++) {
idx = indices[0];
int16 r26 = cubep->_projection[idx].x;
int16 r31 = cubep->_projection[idx].y;
uint16 r25 = *uv++; //TODO: unsigned
int16 r24 = *uv++; //TODO: unsigned
ymin = MIN(r30, ymin);
ymax = MAX(r30, ymax);
ymin = MIN(r31, ymin);
ymax = MAX(r31, ymax);
drawMappingLine(r20, r30, r26, r31, r19, r18, r25, r24, _lines);
r20 = r26;
r30 = r31;
r19 = r25;
r18 = r24;
}
idx = face->_indices[0];
int16 r26 = cubep->_projection[idx].x;
int16 r31 = cubep->_projection[idx].y;
uv = face->_uv;
uint16 r25 = *uv++;
int16 r24 = *uv;
ymin = MIN(r30, ymin);
ymax = MAX(r30, ymax);
ymin = MIN(r31, ymin);
ymax = MAX(r31, ymax);
drawMappingLine(r20, r30, r26, r31, r19, r18, r25, r24, _lines);
displayMappingLine(ymin, ymax, _graphics->getMainView()->_bufferPtr, face->_texturePtr);
}
// Original name: trace_ligne_mapping
void EdenGame::drawMappingLine(int16 r3, int16 r4, int16 r5, int16 r6, int16 r7, int16 r8, int16 r9, int16 r10, int16 *linesp) {
int16 r26 = r6 - r4;
if (r26 <= 0) {
if (r26 == 0) {
linesp += r4 * 8;
if (r5 - r3 > 0) {
linesp[0] = r3;
linesp[1] = r5;
linesp[4] = r7;
linesp[5] = r9;
linesp[6] = r8;
linesp[7] = r10;
} else {
linesp[0] = r5;
linesp[1] = r3;
linesp[4] = r9;
linesp[5] = r7;
linesp[6] = r10;
linesp[7] = r8;
}
return;
}
int16 t = r3;
r3 = r5;
r5 = t;
t = r7;
r7 = r9;
r9 = t;
t = r8;
r8 = r10;
r10 = t;
linesp += r6 * 8;
r26 = -r26;
} else
linesp += r4 * 8 + 1; //TODO wha???
int r30 = r3 << 16;
int r29 = r7 << 16;
int r28 = r8 << 16;
int r25 = ((r5 - r3) << 16) / r26;
int r24 = ((r9 - r7) << 16) / r26;
int r23 = ((r10 - r8) << 16) / r26;
for (int i = 0; i < r26; i++) {
linesp[0] = r30 >> 16;
linesp[4] = r29 >> 16;
linesp[6] = r28 >> 16;
r30 += r25;
r29 += r24;
r28 += r23;
linesp += 8;
}
}
// Original name: affiche_ligne_mapping
void EdenGame::displayMappingLine(int16 r3, int16 r4, byte *target, byte *texture) {
int16 height = r4 - r3;
byte *trg_line = _graphics->getMainView()->_bufferPtr + r3 * 640; //TODO: target??
int16 *line = &_lines[r3 * 8];
// debug("curs: beg draw %d - %d", r3, r4);
for (int r22 = height; r22; r22--, line += 8, trg_line += 640) {
int16 r29 = line[0];
int16 r28 = line[1];
int16 len = r28 - r29;
if (len < 0)
break;
if (len == 0)
continue;
// debug("curs: lin draw %d", r4 - height);
uint16 r31 = line[4] << 8;
uint16 r30 = line[6] << 8;
int16 r21 = line[5] - line[4];
int16 r20 = line[7] - line[6];
int16 r26 = (r21 << 8) / len;
int16 r25 = (r20 << 8) / len;
byte *trg = trg_line + r29;
#if 1
while (r29++ < r28) {
*trg++ = texture[(r30 & 0xFF00) | (r31 >> 8)];
r31 += r26;
r30 += r25;
}
#endif
}
}
// PC cursor
CubeCursor _cursorsPC[9] = {
{ { 0, 0, 0, 0, 0, 0 }, 3, 2 },
{ { 1, 1, 0, 1, 1, 0 }, 2, -2 },
{ { 2, 2, 2, 2, 2, 2 }, 1, 2 },
{ { 3, 3, 3, 3, 3, 3 }, 1, -2 },
{ { 4, 4, 4, 4, 4, 4 }, 2, 2 },
{ { 5, 5, 5, 5, 5, 5 }, 4, 0 },
{ { 6, 6, 6, 6, 6, 6 }, 1, 2 },
{ { 7, 7, 7, 7, 7, 7 }, 1, -2 },
// { { 0, 8, 0, 0, 8, 8 }, 2, 2 },
{ { 0, 8, 0, 0, 8, 8 }, 2, 2 }
};
XYZ _cubePC[6][3] = {
{ { -15, -15, -15 }, { -15, 15, -15 }, { 15, 15, -15 } },
{ { -15, -15, 15 }, { -15, 15, 15 }, { -15, 15, -15 } },
{ { -15, -15, 15 }, { -15, -15, -15 }, { 15, -15, -15 } },
{ { 15, -15, 15 }, { 15, 15, 15 }, { -15, 15, 15 } },
{ { 15, -15, -15 }, { 15, 15, -15 }, { 15, 15, 15 } },
{ { 15, 15, 15 }, { 15, 15, -15 }, { -15, 15, -15 } }
};
signed short cosineTable[] = {
// = cos(n) << 7; n += 10;
128, 126, 120, 111, 98, 82, 64, 44, 22, 0, -22, -44, -64, -82, -98, -111, -120, -126,
-128, -126, -120, -111, -98, -82, -64, -44, -22, 0, 22, 44, 64, 82, 98, 111, 120, 126,
128, 126, 120, 111, 98, 82, 64, 44, 22, 0
};
void EdenGame::makeTables() {
for (int i = -15; i < 15; i++) {
int v = (i * 11) / 15 + 11;
tab1[i + 15] = v;
tab2[i + 15] = v * 22;
}
for (int i = 0; i < 36; i++) {
for (int j = -35; j < 36; j++)
tab3[i][j + 35] = (cosineTable[i] * j) >> 7;
}
}
void EdenGame::getSinCosTables(unsigned short angle, signed char **cos_table, signed char **sin_table) {
angle /= 2;
*cos_table = tab3[angle] + 35;
angle += 9;
if (angle >= 36)
angle -= 36;
*sin_table = tab3[angle] + 35;
}
void EdenGame::rotatePoint(XYZ *point, XYZ *rpoint) {
// see http://www.cprogramming.com/tutorial/3d/rotation.html
XYZ xrot;
xrot.x = point->x;
xrot.y = _cosX[point->y] + _sinX[point->z];
xrot.z = _sinX[-point->y] + _cosX[point->z];
rpoint->x = _cosY[xrot.x] + _sinY[-xrot.z];
rpoint->y = xrot.y;
rpoint->z = _sinY[xrot.x] + _cosY[xrot.z];
rpoint->z += _zoomZ;
}
void EdenGame::mapPoint(XYZ *point, short *x, short *y) {
*y = ((12800 / point->z) * point->y) >> 7;
*x = ((12800 / point->z) * point->x) >> 7;
}
short EdenGame::calcFaceArea(XYZ *face) {
XYZ rpoint;
short x[3], y[3];
for (int i = 0; i < 3; i++) {
rotatePoint(&face[i], &rpoint);
mapPoint(&rpoint, &x[i], &y[i]);
}
short area = (y[1] - y[0]) * (x[2] - x[0]) - (y[2] - y[0]) * (x[1] - x[0]);
return area;
}
void EdenGame::paintPixel(XYZ *point, unsigned char pixel) {
short x, y;
mapPoint(point, &x, &y);
_cursorCenter[y * 40 + x] = pixel;
}
void EdenGame::paintFace0(XYZ *point) {
XYZ rpoint;
for (int y = -15; y < 15; y++) {
for (int x = -15; x < 15; x++) {
point->x = x;
point->y = y;
rotatePoint(point, &rpoint);
paintPixel(&rpoint, _face[0][tab1[x + 15] + tab2[y + 15]]);
}
}
}
void EdenGame::paintFace1(XYZ *point) {
XYZ rpoint;
for (int y = -15; y < 15; y++) {
for (int x = -15; x < 15; x++) {
point->y = y;
point->z = -x;
rotatePoint(point, &rpoint);
paintPixel(&rpoint, _face[1][tab1[x + 15] + tab2[y + 15]]);
}
}
}
void EdenGame::paintFace2(XYZ *point) {
XYZ rpoint;
for (int y = -15; y < 15; y++) {
for (int x = -15; x < 15; x++) {
point->x = x;
point->z = -y;
rotatePoint(point, &rpoint);
paintPixel(&rpoint, _face[2][tab1[x + 15] + tab2[y + 15]]);
}
}
}
void EdenGame::paintFace3(XYZ *point) {
XYZ rpoint;
for (int y = -15; y < 15; y++) {
for (int x = -15; x < 15; x++) {
point->x = -x;
point->y = -y;
rotatePoint(point, &rpoint);
paintPixel(&rpoint, _face[3][tab1[x + 15] + tab2[y + 15]]);
}
}
}
void EdenGame::paintFace4(XYZ *point) {
XYZ rpoint;
for (int y = -15; y < 15; y++) {
for (int x = -15; x < 15; x++) {
point->y = y;
point->z = x;
rotatePoint(point, &rpoint);
paintPixel(&rpoint, _face[4][tab1[x + 15] + tab2[y + 15]]);
}
}
}
void EdenGame::paintFace5(XYZ *point) {
XYZ rpoint;
for (int y = -15; y < 15; y++) {
for (int x = -15; x < 15; x++) {
point->x = x;
point->z = y;
rotatePoint(point, &rpoint);
paintPixel(&rpoint, _face[5][tab1[x + 15] + tab2[y + 15]]);
}
}
}
void EdenGame::paintFaces() {
XYZ point;
if (!(_faceSkip & 1)) {
point.z = -15;
paintFace0(&point);
}
if (!(_faceSkip & 2)) {
point.x = -15;
paintFace1(&point);
}
if (!(_faceSkip & 4)) {
point.y = -15;
paintFace2(&point);
}
if (!(_faceSkip & 8)) {
point.z = 15;
paintFace3(&point);
}
if (!(_faceSkip & 16)) {
point.x = 15;
paintFace4(&point);
}
if (!(_faceSkip & 32)) {
point.y = 15;
paintFace5(&point);
}
}
void EdenGame::renderCube() {
for (uint16 i = 0; i < sizeof(_cursor); i++)
_cursor[i] = 0;
_cursorCenter = &_cursor[40 * 20 + 20];
getSinCosTables(_angleX, &_cosX, &_sinX);
getSinCosTables(_angleY, &_cosY, &_sinY);
getSinCosTables(_angleZ, &_cosZ, &_sinZ);
for (int i = 0; i < 6; i++) {
int area = calcFaceArea(_cubePC[i]);
if (area <= 0) {
_face[i] = _newface[i]; // set new texture for invisible area,
_faceSkip |= 1 << i; // but don't draw it just yet
} else
_faceSkip &= ~(1 << i);
}
paintFaces();
const int xshift = -5; // TODO: temporary fix to decrease left margin
unsigned char *cur = _cursor;
unsigned char *scr = _graphics->getMainView()->_bufferPtr + _cursorPosX + _scrollPos + xshift + _cursorPosY * _graphics->getMainView()->_pitch;
for (int y = 0; y < 40; y++) {
for (int x = 0; x < 40; x++) {
if (x + _cursorPosX + _scrollPos + xshift < _graphics->getMainView()->_pitch && y + _cursorPosY < _graphics->getMainView()->_height)
if (*cur)
*scr = *cur;
scr++;
cur++;
}
scr += _graphics->getMainView()->_pitch - 40;
}
}
void EdenGame::incAngleX(int step) {
_angleX += step;
if (_angleX == 70 + 2)
_angleX = 0;
else if (_angleX == 0 - 2)
_angleX = 70;
}
void EdenGame::decAngleX() {
if (_angleX != 0)
_angleX -= (_angleX > 4) ? 4 : 2;
}
void EdenGame::incAngleY(int step) {
_angleY += step;
if (_angleY == 70 + 2)
_angleY = 0;
else if (_angleY == 0 - 2)
_angleY = 70;
}
void EdenGame::decAngleY() {
if (_angleY != 0)
_angleY -= (_angleY > 4) ? 4 : 2;
}
void EdenGame::incZoom() {
if (_zoomZ == 170)
_zoomZStep = 40;
else if (_zoomZ == 570)
_zoomZStep = -40;
_zoomZ += _zoomZStep;
}
void EdenGame::decZoom() {
if (_zoomZ == 170)
return;
if (_zoomZ < 170)
_zoomZ = 170;
else
_zoomZ -= 40;
}
void EdenGame::initCubePC() {
_zoomZ = 170;
_zoomZStep = 40;
_angleX = _angleY = _angleZ = 0;
_pcCursor = &_cursorsPC[0];
_cursCurPCMap = -1;
makeTables();
}
void EdenGame::selectPCMap(int16 num) {
if (num != _cursCurPCMap) {
_pcCursor = &_cursorsPC[num];
unsigned char *bank = _mainBankBuf + READ_LE_UINT16(_mainBankBuf);
for (int i = 0; i < 6; i++) {
_newface[i] = 4 + (unsigned char*)getElem(bank, _pcCursor->_sides[i]);
if (_cursCurPCMap == -1)
_face[i] = _newface[i];
}
_cursCurPCMap = num;
}
}
void EdenGame::enginePC() {
int16 curs = _currCursor;
if (_normalCursor && (_globals->_drawFlags & DrawFlags::drDrawFlag20))
curs = 9;
selectPCMap(curs);
_cursorNewTick = g_system->getMillis();
if (_cursorNewTick - _cursorOldTick < 1)
return;
_cursorOldTick = _cursorNewTick;
int step = _pcCursor->_speed;
switch (_pcCursor->_kind) {
case 0:
default:
break;
case 1: // rot up-down
decAngleY();
decZoom();
incAngleX(step);
break;
case 2: // rot left-right
decAngleX();
decZoom();
incAngleY(step);
break;
case 3: // rotate random
decZoom();
incAngleX(step);
incAngleY(step);
break;
case 4: // zoom in-out
_face[0] = _newface[0];
decAngleY();
decAngleX();
incZoom();
break;
}
renderCube();
}
void EdenGame::LostEdenMac_InitPrefs() {
// Keep track of the preferred language previously selected in the option menu
int pref = ConfMan.getInt("PrefLang");
if (pref < 1 || pref > 5) {
pref = 1;
ConfMan.setInt("PrefLang", 1);
ConfMan.flushToDisk();
}
_globals->_prefLanguage = pref;
_globals->_prefMusicVol[0] = 192;
_globals->_prefMusicVol[1] = 192;
_globals->_prefVoiceVol[0] = 255;
_globals->_prefVoiceVol[1] = 255;
_globals->_prefSoundVolume[0] = 32;
_globals->_prefSoundVolume[1] = 32;
}
} // namespace Cryo