diff options
author | Paul Gilbert | 2012-04-30 23:16:19 +1000 |
---|---|---|
committer | Paul Gilbert | 2012-04-30 23:16:19 +1000 |
commit | 68bcaa61b9eb1108028b3db072ade95431b9f14f (patch) | |
tree | 604032ba514b785f5a3216e7d47c9d4906e32d49 /engines/tony | |
parent | b0eef829728183b7ea170b30a33eca091bcc4574 (diff) | |
download | scummvm-rg350-68bcaa61b9eb1108028b3db072ade95431b9f14f.tar.gz scummvm-rg350-68bcaa61b9eb1108028b3db072ade95431b9f14f.tar.bz2 scummvm-rg350-68bcaa61b9eb1108028b3db072ade95431b9f14f.zip |
TONY: More header files and functionality added
Diffstat (limited to 'engines/tony')
-rw-r--r-- | engines/tony/adv.h | 35 | ||||
-rw-r--r-- | engines/tony/custom.cpp | 2511 | ||||
-rw-r--r-- | engines/tony/custom.h | 106 | ||||
-rw-r--r-- | engines/tony/detection.cpp | 4 | ||||
-rw-r--r-- | engines/tony/font.h | 12 | ||||
-rw-r--r-- | engines/tony/game.cpp | 1148 | ||||
-rw-r--r-- | engines/tony/gfxcore.h | 2 | ||||
-rw-r--r-- | engines/tony/gfxengine.h | 4 | ||||
-rw-r--r-- | engines/tony/input.h | 2 | ||||
-rw-r--r-- | engines/tony/loc.h | 6 | ||||
-rw-r--r-- | engines/tony/module.mk | 1 | ||||
-rw-r--r-- | engines/tony/mpal/lzo.cpp | 14 | ||||
-rw-r--r-- | engines/tony/mpal/lzo.h | 11 | ||||
-rw-r--r-- | engines/tony/mpal/stubs.cpp | 10 | ||||
-rw-r--r-- | engines/tony/mpal/stubs.h | 8 | ||||
-rw-r--r-- | engines/tony/sound.h | 365 | ||||
-rw-r--r-- | engines/tony/tony.cpp | 68 | ||||
-rw-r--r-- | engines/tony/tony.h | 94 | ||||
-rw-r--r-- | engines/tony/tonychar.h | 1 | ||||
-rw-r--r-- | engines/tony/utils.cpp | 2 | ||||
-rw-r--r-- | engines/tony/window.h | 134 |
21 files changed, 4512 insertions, 26 deletions
diff --git a/engines/tony/adv.h b/engines/tony/adv.h index b29e4eb0cd..aab7df24af 100644 --- a/engines/tony/adv.h +++ b/engines/tony/adv.h @@ -48,8 +48,24 @@ #ifndef TONY_ADV_H #define TONY_ADV_H +#include "tony/mpal/memory.h" +#include "tony/gfxcore.h" + + namespace Tony { +// X & Y dimensions of the adventure +#define RM_SX 640 +#define RM_SY 480 + +// Dimensioni X&Y del bigbuf +#define RM_BBX (RM_SX) +#define RM_BBY (RM_SY) + +// Skipping X&Y +#define RM_SKIPY ((RM_BBY - RM_SY) / 2) +#define RM_SKIPX 0 + // Tony's actions enum RMTonyAction { TA_GOTO = 0, @@ -65,6 +81,25 @@ enum RMTonyAction { TA_RECEIVECOMBINEGIVE }; +// Funzioni globali +HANDLE MainLoadLocation(int nLoc, RMPoint pt, RMPoint start); +HANDLE MainUnloadLocation(bool bDoOnExit); +void MainLinkGraphicTask(RMGfxTask *task); +void MainFreeze(void); +void MainUnfreeze(void); +void MainWaitFrame(void); +void MainShowMouse(void); +void MainHideMouse(void); +void MainEnableInput(void); +void MainDisableInput(void); +void MainPlayMusic(int nChannel, const char *fn, int nFX, bool bLoop, int nSync); +void MainInitWipe(int type); +void MainCloseWipe(void); +void MainWaitWipeEnd(void); +void MainEnableGUI(void); +void MainDisableGUI(void); +void MainSetPalesati(bool bPalesati); + } // End of namespace Tony #endif diff --git a/engines/tony/custom.cpp b/engines/tony/custom.cpp new file mode 100644 index 0000000000..55f6cbe77d --- /dev/null +++ b/engines/tony/custom.cpp @@ -0,0 +1,2511 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + */ +/************************************************************************** + * ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ * + * Nayma Software srl * + * e -= We create much MORE than ALL =- * + * u- z$$$c '. ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ * + * .d" d$$$$$b "b. * + * .z$* d$$$$$$$L ^*$c. * + * #$$$. $$$$$$$$$ .$$$" Project: Roasted Moths........ * + * ^*$b 4$$$$$$$$$F .d$*" * + * ^$$. 4$$$$$$$$$F .$P" Module: Custom.CPP........... * + * *$. '$$$$$$$$$ 4$P 4 * + * J *$ "$$$$$$$" $P r Author: Giovanni Bajo........ * + * z$ '$$$P*4c.*$$$*.z@*R$$$ $. * + * z$" "" #$F^ "" '$c Desc: Custom functions..... * + * z$$beu .ue=" $ "=e.. .zed$$c ..................... * + * "#$e z$*" . `. ^*Nc e$"" ..................... * + * "$$". .r" ^4. .^$$" ..................... * + * ^.@*"6L=\ebu^+C$"*b." * + * "**$. "c 4$$$ J" J$P*" OS: [ ] DOS [X] WIN95 [ ] PORT * + * ^"--.^ 9$" .--"" COMP: [ ] WATCOM [X] VISUAL C++ * + * " [ ] EIFFEL [ ] GCC/GXX/DJGPP * + * * + * This source code is Copyright (C) Nayma Software. ALL RIGHTS RESERVED * + * * + ************************************************************************** + */ + +#include "common/system.h" +#include "common/savefile.h" +#include "tony/mpal/mpal.h" +#include "tony/mpal/memory.h" +#include "tony/adv.h" +#include "tony/custom.h" +#include "tony/font.h" +#include "tony/game.h" +#include "tony/gfxcore.h" +#include "tony/tony.h" +#include "tony/tonychar.h" +#include "tony/utils.h" + +namespace Tony { + +extern bool bPatIrqFreeze; + +RMTony *Tony; +RMPointer *Pointer; +RMGameBoxes *Boxes; +RMLocation *Loc; +RMInventory *Inventory; +RMInput *Input; + +HANDLE (*LoadLocation)(int, RMPoint, RMPoint start); +HANDLE (*UnloadLocation)(bool bDoOnExit); +void (*LinkGraphicTask)(RMGfxTask *task); +void (*Freeze)(void); +void (*Unfreeze)(void); +void (*WaitFrame)(void); +void (*PlayMusic)(int nChannel, const char *fileName, int nFX, bool bLoop, int nSync); +void (*WaitWipeEnd)(void); +void (*CloseWipe)(void); +void (*InitWipe)(int type); +void (*EnableGUI)(void); +void (*DisableGUI)(void); +void (*SetPalesati)(bool bpal); + +uint32 dwTonyNumTexts = 0; +bool bTonyInTexts = false; +bool bStaticTalk = false; +RMTony::TALKTYPE nTonyNextTalkType; + +RMPoint StartLocPos[256]; +OSystem::MutexRef cs[10]; +OSystem::MutexRef vdb; +HANDLE mut[10]; + +bool bSkipIdle = false; +HANDLE hSkipIdle; + +int lastMusic = 0, lastTappeto = 0; + +int tappeti[200]; + +#define T_GRILLI 1 +#define T_GRILLIOV 2 +#define T_GRILLIVENTO 3 +#define T_GRILLIVENTO1 4 +#define T_VENTO 5 +#define T_MARE 6 +#define T_MAREMETA 7 + +char* tappetiFile[] = { + "None", + "1.ADP", // Grilli.WAV + "2.ADP", // Grilli-Ovattati.WAV + "3.ADP", // Grilli-Vento.WAV + "3.ADP", // Grilli-Vento1.WAV + "5.ADP", // Vento1.WAV + "4.ADP", // Mare1.WAV + "6.ADP" // Mare1.WAV metà volume +}; + +struct { + uint32 code; + RMItem *item; + byte r, g, b; + int talkpattern; + int standpattern; + int starttalkpattern, endtalkpattern; + int numtexts; + + void Save(Common::OutSaveFile *f) { + f->writeUint32LE(code); + f->writeUint32LE(0); + f->writeByte(r); + f->writeByte(g); + f->writeByte(b); + f->writeUint32LE(talkpattern); + f->writeUint32LE(standpattern); + f->writeUint32LE(starttalkpattern); + f->writeUint32LE(endtalkpattern); + f->writeUint32LE(numtexts); + } + void Load(Common::InSaveFile *f) { + code = f->readUint32LE(); + f->readUint32LE(); + item = NULL; + r = f->readByte(); + g = f->readByte(); + b = f->readByte(); + talkpattern = f->readUint32LE(); + standpattern = f->readUint32LE(); + starttalkpattern = f->readUint32LE(); + endtalkpattern = f->readUint32LE(); + numtexts = f->readUint32LE(); + } +} Character[16]; + +struct { + uint32 code; + RMItem *item; + byte r, g, b; + int x, y; + int numtalks[10]; + int curgroup; + int numtexts; + bool bInTexts; + int curTalk; + bool bAlwaysBack; + + void Save(Common::OutSaveFile *f) { + f->writeUint32LE(code); + f->writeUint32LE(0); + f->writeByte(r); + f->writeByte(g); + f->writeByte(b); + f->writeUint32LE(x); + f->writeUint32LE(y); + for (int i = 0; i < 10; ++i) + f->writeUint32LE(numtalks[i]); + f->writeUint32LE(curgroup); + f->writeUint32LE(numtexts); + f->writeByte(bInTexts); + f->writeUint32LE(curTalk); + f->writeByte(bAlwaysBack); + } + void Load(Common::InSaveFile *f) { + code = f->readUint32LE(); + f->readUint32LE(); + item = NULL; + r = f->readByte(); + g = f->readByte(); + b = f->readByte(); + x = f->readUint32LE(); + y = f->readUint32LE(); + for (int i = 0; i < 10; ++i) + numtalks[i] = f->readUint32LE(); + curgroup = f->readUint32LE(); + numtexts = f->readUint32LE(); + bInTexts = f->readByte(); + curTalk = f->readUint32LE(); + bAlwaysBack = f->readByte(); + } +} MCharacter[10]; + +bool IsMChar[16]; + +bool bAlwaysDisplay; + +RMPoint saveTonyPos; +int saveTonyLoc; + +RMTextDialog *curBackText = NULL; +bool bTonyIsSpeaking = false; + +int curChangedHotspot = 0; + +struct { + uint32 dwCode; + uint32 nX,nY; + + void Save(Common::OutSaveFile *f) { + f->writeUint32LE(dwCode); + f->writeUint32LE(nX); + f->writeUint32LE(nY); + } + void Load(Common::InSaveFile *f) { + dwCode = f->readUint32LE(); + nX = f->readUint32LE(); + nY = f->readUint32LE(); + } +} ChangedHotspot[256]; + +void ReapplyChangedHotspot(void) { + int i; + for (i = 0; i<curChangedHotspot; i++) + Loc->GetItemFromCode(ChangedHotspot[i].dwCode)->ChangeHotspot(RMPoint(ChangedHotspot[i].nX, ChangedHotspot[i].nY)); +} + +void SaveChangedHotspot(Common::OutSaveFile *f) { + f->writeByte(curChangedHotspot); + if (curChangedHotspot > 0) { + for (int i = 0; i < curChangedHotspot; ++i) + ChangedHotspot[i].Save(f); + } +} + +void LoadChangedHotspot(Common::InSaveFile *f) { + curChangedHotspot = f->readByte(); + + if (curChangedHotspot > 0) { + for (int i = 0; i < curChangedHotspot; ++i) + ChangedHotspot[i].Load(f); + } +} + + +/* + Classi richieste per le funzioni custom! + + Tony (per muoverlo) -> si puo' fare tramite MPAL l'animazione? Penso proprio di sì + + SendMessage -> Direi che basta theEngine.SendMessage() + ChangeLocation -> theEngine.ChangeLocation() + AddInventory -> theEngine.AddInventory() +*/ + +void MCharResetCodes(void) { + for (int i = 0; i < 10; i++) + MCharacter[i].item = Loc->GetItemFromCode(MCharacter[i].code); + for (int i = 0; i < 10; i++) + Character[i].item = Loc->GetItemFromCode(Character[i].code); +} + +void CharsSaveAll(Common::OutSaveFile *f) { + for (int i = 0; i < 10; i++) { + f->writeByte(IsMChar[i]); + if (IsMChar[i]) { + MCharacter[i].Save(f); + } else { + Character[i].Save(f); + } + } +} + +void CharsLoadAll(Common::InSaveFile *f) { + for (int i = 0; i < 10; i++) { + IsMChar[i] = f->readByte(); + if (IsMChar[i]) + MCharacter[i].Load(f); + else + Character[i].Load(f); + } +} + +DECLARE_CUSTOM_FUNCTION(FaceToMe)(uint32, uint32, uint32, uint32) { + Tony->SetPattern(Tony->PAT_STANDDOWN); +} + +DECLARE_CUSTOM_FUNCTION(BackToMe)(uint32, uint32, uint32, uint32) { + Tony->SetPattern(Tony->PAT_STANDUP); +} + +DECLARE_CUSTOM_FUNCTION(LeftToMe)(uint32, uint32, uint32, uint32) { + Tony->SetPattern(Tony->PAT_STANDLEFT); +} + +DECLARE_CUSTOM_FUNCTION(RightToMe)(uint32, uint32, uint32, uint32) { + Tony->SetPattern(Tony->PAT_STANDRIGHT); +} + + +DECLARE_CUSTOM_FUNCTION(TonySetPalesati)(uint32 bStatus, uint32, uint32, uint32) { + SetPalesati(bStatus); +} + +DECLARE_CUSTOM_FUNCTION(MySleep)(uint32 dwTime, uint32, uint32, uint32) { + if (bSkipIdle) return; + Sleep(dwTime); +} + +DECLARE_CUSTOM_FUNCTION(SetAlwaysDisplay)(uint32 val, uint32, uint32, uint32) { + bAlwaysDisplay = (val != 0); +} + + +DECLARE_CUSTOM_FUNCTION(SetPointer)(uint32 dwPointer, uint32, uint32, uint32) { + switch (dwPointer) { + case 1: + Pointer->SetSpecialPointer(Pointer->PTR_FRECCIASU); + break; + case 2: + Pointer->SetSpecialPointer(Pointer->PTR_FRECCIAGIU); + break; + case 3: + Pointer->SetSpecialPointer(Pointer->PTR_FRECCIASINISTRA); + break; + case 4: + Pointer->SetSpecialPointer(Pointer->PTR_FRECCIADESTRA); + break; + case 5: + Pointer->SetSpecialPointer(Pointer->PTR_FRECCIAMAPPA); + break; + + default: + Pointer->SetSpecialPointer(Pointer->PTR_NONE); + break; + } +} + +VoiceHeader *SearchVoiceHeader(uint32 codehi, uint32 codelo) { + uint i; + int code; + + code = (codehi << 16) | codelo; + + if (_vm->_voices.size() == 0) + return NULL; + + for (i = 0; i < _vm->_voices.size(); i++) + if (_vm->_voices[i].code == code) + return &_vm->_voices[i]; + + return NULL; +} + + +DECLARE_CUSTOM_FUNCTION(SendTonyMessage)(uint32 dwMessage, uint32 nX, uint32 nY, uint32) { + RMMessage msg(dwMessage); + int i; + int curOffset = 0; + + if (bSkipIdle) return; + + if (!msg.IsValid()) + return; + + VoiceHeader *curVoc = SearchVoiceHeader(0, dwMessage); + FPSFX *voice = NULL; + if (curVoc) { + // Si posiziona all'interno del database delle voci all'inizio della prima + curOffset = curVoc->offset; + + // PRIMA VOLTA PREALLOCA + g_system->lockMutex(vdb); + //fseek(_vm->m_vdbFP, curOffset, SEEK_SET); + _vm->_vdbFP.seek(curOffset); + _vm->_theSound.CreateSfx(&voice); + voice->LoadVoiceFromVDB(_vm->_vdbFP); +// curOffset = ftell(_vm->m_vdbFP); + curOffset = _vm->_vdbFP.pos(); + + voice->SetLoop(false); + g_system->unlockMutex(vdb); + } + + if (nTonyNextTalkType != Tony->TALK_NORMAL) { + Tony->StartTalk(nTonyNextTalkType); + if (!bStaticTalk) + nTonyNextTalkType = Tony->TALK_NORMAL; + } else { + if (msg.NumPeriods() > 1) + Tony->StartTalk(Tony->TALK_FIANCHI); + else + Tony->StartTalk(Tony->TALK_NORMAL); + } + + if (curBackText) + curBackText->Hide(); + bTonyIsSpeaking = true; + + for (i = 0; i < msg.NumPeriods() && !bSkipIdle; i++) { + RMTextDialog text; + + text.SetInput(Input); + + // Allineamento + text.SetAlignType(RMText::HCENTER,RMText::VBOTTOM); + + // Colore + text.SetColor(0,255,0); + + // Scrive il testo + text.WriteText(msg[i],0); + + // Setta la posizione + if (nX == 0 && nY == 0) + text.SetPosition(Tony->Position() - RMPoint(0, 130) - Loc->ScrollPosition()); + else + text.SetPosition(RMPoint(nX, nY) - Loc->ScrollPosition()); + + // Setta l'always display + if (bAlwaysDisplay) { text.SetAlwaysDisplay(); text.ForceTime(); } + + // Registra il testo + LinkGraphicTask(&text); + + if (curVoc) { + if (i == 0) { + voice->Play(); + text.SetCustomSkipHandle2(voice->hEndOfBuffer); + } else { + g_system->lockMutex(vdb); + // fseek(_vm->m_vdbFP, curOffset, SEEK_SET); + _vm->_vdbFP.seek(curOffset); + _vm->_theSound.CreateSfx(&voice); + voice->LoadVoiceFromVDB(_vm->_vdbFP); + // curOffset = ftell(_vm->m_vdbFP); + curOffset = _vm->_vdbFP.pos(); + voice->SetLoop(false); + voice->Play(); + text.SetCustomSkipHandle2(voice->hEndOfBuffer); + g_system->unlockMutex(vdb); + } + } + + // Aspetta la fine della visualizzazione + text.SetCustomSkipHandle(hSkipIdle); + text.WaitForEndDisplay(); + + if (curVoc) { + voice->Stop(); + voice->Release(); + voice=NULL; + } + } + + bTonyIsSpeaking = false; + if (curBackText) + curBackText->Show(); + + Tony->EndTalk(); +} + +DECLARE_CUSTOM_FUNCTION(ChangeBoxStatus)(uint32 nLoc, uint32 nBox, uint32 nStatus, uint32) { + Boxes->ChangeBoxStatus(nLoc,nBox,nStatus); +} + + +DECLARE_CUSTOM_FUNCTION(CustLoadLocation)(uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) { + HANDLE h; + + Freeze(); + + curChangedHotspot = 0; + if (bUseStartPos != 0) + LoadLocation(nLoc, RMPoint(tX, tY), StartLocPos[nLoc]); + else + LoadLocation(nLoc, RMPoint(tX, tY), RMPoint(-1, -1)); + + Unfreeze(); + h = mpalQueryDoAction(0, nLoc, 0); + + // On Enter? + if (h != INVALID_HANDLE_VALUE) + WaitForSingleObject(h, INFINITE); +} + + +RMPoint SFM_pt; +int SFM_nLoc; + +DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgStart)(uint32 nMsg, uint32 nFont, uint32, uint32) { + RMMessage msg(nMsg); + RMGfxClearTask clear; + int i; + + SFM_nLoc = Loc->TEMPGetNumLoc(); + SFM_pt = Tony->Position(); + + if (bSkipIdle) return; + + UnloadLocation(false); + Tony->Hide(); + Unfreeze(); + + for (i = 0; i < msg.NumPeriods() && !bSkipIdle; i++) { + RMTextDialog text; + + text.SetInput(Input); + + // Allineamento + text.SetAlignType(RMText::HCENTER,RMText::VCENTER); + + // Forza il testo a scomparire a tempo + text.ForceTime(); + + // Colore + text.SetColor(255,255,255); + + // Scrive il testo + if (nFont== 0) + text.WriteText(msg[i],1); + else if (nFont==1) + text.WriteText(msg[i],0); + + // Setta la posizione + text.SetPosition(RMPoint(320,240)); + + text.SetAlwaysDisplay(); + text.ForceTime(); + + // Registra il testo + LinkGraphicTask(&clear); + LinkGraphicTask(&text); + + // Aspetta la fine della visualizzazione + text.SetCustomSkipHandle(hSkipIdle); + text.WaitForEndDisplay(); + } +} + +DECLARE_CUSTOM_FUNCTION(ClearScreen)(uint32, uint32, uint32, uint32) { + RMGfxClearTask clear; + + LinkGraphicTask(&clear); + WaitFrame(); +} + +DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgEnd)(uint32 bNotEnableTony, uint32, uint32, uint32) { + Freeze(); + LoadLocation(SFM_nLoc,RMPoint(SFM_pt.x,SFM_pt.y),RMPoint(-1,-1)); + if (!bNotEnableTony) + Tony->Show(); + Unfreeze(); + + MCharResetCodes(); + ReapplyChangedHotspot(); +} + + +DECLARE_CUSTOM_FUNCTION(SendFullscreenMessage)(uint32 nMsg, uint32 nFont, uint32, uint32) { + SendFullscreenMsgStart(nMsg,nFont,0,0); + SendFullscreenMsgEnd(0, 0, 0, 0); +} + +bool bNoOcchioDiBue = false; + +DECLARE_CUSTOM_FUNCTION(NoOcchioDiBue)(uint32, uint32, uint32, uint32) { + bNoOcchioDiBue = true; +} + +DECLARE_CUSTOM_FUNCTION(CloseLocation)(uint32, uint32, uint32, uint32) { + if (!bNoOcchioDiBue) { + InitWipe(1); + WaitWipeEnd(); + } + + _vm->StopMusic(4); + + // On Exit e lascia freezzato + UnloadLocation(true); + Unfreeze(); +} + + +DECLARE_CUSTOM_FUNCTION(ChangeLocation)(uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) { + HANDLE h; + + if (!bNoOcchioDiBue) { + InitWipe(1); + WaitWipeEnd(); + } + + if (lastTappeto != tappeti[nLoc]) { + _vm->StopMusic(4); + } + + // On Exit e lascia freezzato + UnloadLocation(true); + + curChangedHotspot = 0; + if (bUseStartPos != 0) + LoadLocation(nLoc, RMPoint(tX, tY), StartLocPos[nLoc]); + else + LoadLocation(nLoc, RMPoint(tX, tY), RMPoint(-1, -1)); + + if (lastTappeto != tappeti[nLoc]) { + lastTappeto = tappeti[nLoc]; + if (lastTappeto != 0) + _vm->PlayMusic(4, tappetiFile[lastTappeto], 0, true, 2000); + } + + if (!bNoOcchioDiBue) { + InitWipe(2); + } + + Unfreeze(); + + + h = mpalQueryDoAction(0,nLoc,0); + + if (!bNoOcchioDiBue) { + WaitWipeEnd(); + CloseWipe(); + } + + bNoOcchioDiBue = false; + + // On Enter? + if (h != INVALID_HANDLE_VALUE) + WaitForSingleObject(h,INFINITE); + +} + +DECLARE_CUSTOM_FUNCTION(SetLocStartPosition)(uint32 nLoc, uint32 lX, uint32 lY, uint32) { + StartLocPos[nLoc].Set(lX,lY); +} + +DECLARE_CUSTOM_FUNCTION(SaveTonyPosition)(uint32, uint32, uint32, uint32) { + saveTonyPos = Tony->Position(); + saveTonyLoc = Loc->TEMPGetNumLoc(); +} + +DECLARE_CUSTOM_FUNCTION(RestoreTonyPosition)(uint32, uint32, uint32, uint32) { + ChangeLocation(saveTonyLoc, saveTonyPos.x, saveTonyPos.y, 0); + MCharResetCodes(); +} + + +DECLARE_CUSTOM_FUNCTION(DisableInput)(uint32, uint32, uint32, uint32) { + MainDisableInput(); +} + + +DECLARE_CUSTOM_FUNCTION(EnableInput)(uint32, uint32, uint32, uint32) { + MainEnableInput(); +} + +DECLARE_CUSTOM_FUNCTION(StopTony)(uint32, uint32, uint32, uint32) { + Tony->StopNoAction(); +} + + +DECLARE_CUSTOM_FUNCTION(CustEnableGUI)(uint32, uint32, uint32, uint32) { + EnableGUI(); +} + +DECLARE_CUSTOM_FUNCTION(CustDisableGUI)(uint32, uint32, uint32, uint32) +{ + DisableGUI(); +} + + +void TonyGenericTake1(uint32 nDirection) { + Freeze(); + Tony->Take(nDirection,0); + Unfreeze(); + + if (!bSkipIdle) + Tony->WaitForEndPattern(); +} + +void TonyGenericTake2(uint32 nDirection) { + Freeze(); + Tony->Take(nDirection,1); + Unfreeze(); + + if (!bSkipIdle) + Tony->WaitForEndPattern(); + + Freeze(); + Tony->Take(nDirection,2); + Unfreeze(); +} + +void TonyGenericPut1(uint32 nDirection) { + Freeze(); + Tony->Put(nDirection,0); + Unfreeze(); + + if (!bSkipIdle) + Tony->WaitForEndPattern(); +} + +void TonyGenericPut2(uint32 nDirection) { + Freeze(); + Tony->Put(nDirection,1); + Unfreeze(); + + if (!bSkipIdle) + Tony->WaitForEndPattern(); + + Freeze(); + Tony->Put(nDirection,2); + Unfreeze(); +} + + +DECLARE_CUSTOM_FUNCTION(TonyTakeUp1)(uint32, uint32, uint32, uint32) { + TonyGenericTake1(0); +} + + +DECLARE_CUSTOM_FUNCTION(TonyTakeMid1)(uint32, uint32, uint32, uint32) { + TonyGenericTake1(1); +} + +DECLARE_CUSTOM_FUNCTION(TonyTakeDown1)(uint32, uint32, uint32, uint32) { + TonyGenericTake1(2); +} + + + +DECLARE_CUSTOM_FUNCTION(TonyTakeUp2)(uint32, uint32, uint32, uint32) { + TonyGenericTake2(0); +} + + +DECLARE_CUSTOM_FUNCTION(TonyTakeMid2)(uint32, uint32, uint32, uint32) { + TonyGenericTake2(1); +} + +DECLARE_CUSTOM_FUNCTION(TonyTakeDown2)(uint32, uint32, uint32, uint32) { + TonyGenericTake2(2); +} + + + + + + + +DECLARE_CUSTOM_FUNCTION(TonyPutUp1)(uint32, uint32, uint32, uint32) { + TonyGenericPut1(0); +} + + +DECLARE_CUSTOM_FUNCTION(TonyPutMid1)(uint32, uint32, uint32, uint32) { + TonyGenericPut1(1); +} + +DECLARE_CUSTOM_FUNCTION(TonyPutDown1)(uint32, uint32, uint32, uint32) { + TonyGenericPut1(2); +} + +DECLARE_CUSTOM_FUNCTION(TonyPutUp2)(uint32, uint32, uint32, uint32) { + TonyGenericPut2(0); +} + + +DECLARE_CUSTOM_FUNCTION(TonyPutMid2)(uint32, uint32, uint32, uint32) { + TonyGenericPut2(1); +} + +DECLARE_CUSTOM_FUNCTION(TonyPutDown2)(uint32, uint32, uint32, uint32) { + TonyGenericPut2(2); +} + + + +DECLARE_CUSTOM_FUNCTION(TonyPerTerra)(uint32 dwParte, uint32, uint32, uint32) { + if (dwParte== 0) + Tony->SetPattern(Tony->PAT_PERTERRALEFT); + else + Tony->SetPattern(Tony->PAT_PERTERRARIGHT); +} + +DECLARE_CUSTOM_FUNCTION(TonySiRialza)(uint32 dwParte, uint32, uint32, uint32) { + if (dwParte== 0) + Tony->SetPattern(Tony->PAT_SIRIALZALEFT); + else + Tony->SetPattern(Tony->PAT_SIRIALZARIGHT); + + if (!bSkipIdle) + Tony->WaitForEndPattern(); +} + +DECLARE_CUSTOM_FUNCTION(TonyPastorella)(uint32 bIsPast, uint32, uint32, uint32) { + Tony->SetPastorella(bIsPast); +} + +DECLARE_CUSTOM_FUNCTION(TonyFischietto)(uint32, uint32, uint32, uint32) { + Tony->SetPattern(Tony->PAT_FISCHIETTORIGHT); + if (!bSkipIdle) + Tony->WaitForEndPattern(); + Tony->SetPattern(Tony->PAT_STANDRIGHT); +} + + +void TonySetNumTexts(uint32 dwText) { + dwTonyNumTexts=dwText; + bTonyInTexts = false; +} + +DECLARE_CUSTOM_FUNCTION(TonyRide)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_RIDE; +} + +DECLARE_CUSTOM_FUNCTION(TonyRidacchia)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_RIDE2; +} + +DECLARE_CUSTOM_FUNCTION(TonyFianchi)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_FIANCHI; +} + +DECLARE_CUSTOM_FUNCTION(TonyCanta)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_CANTA; +} + +DECLARE_CUSTOM_FUNCTION(TonySiIndica)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_SIINDICA; +} + +DECLARE_CUSTOM_FUNCTION(TonySpaventatoConMani)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_SPAVENTATO; +} + +DECLARE_CUSTOM_FUNCTION(TonySpaventatoSenzaMani)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_SPAVENTATO2; +} + +DECLARE_CUSTOM_FUNCTION(TonyConMartello)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_CONMARTELLO; + Tony->SetPattern(Tony->PAT_CONMARTELLO); +} + +DECLARE_CUSTOM_FUNCTION(TonyConBicchiere)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_CONBICCHIERE; + Tony->SetPattern(Tony->PAT_CONBICCHIERE); +} + +DECLARE_CUSTOM_FUNCTION(TonyConVerme)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_CONVERME; + Tony->SetPattern(Tony->PAT_CONVERME); +} + +DECLARE_CUSTOM_FUNCTION(TonyConCorda)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_CONCORDA; + Tony->SetPattern(Tony->PAT_CONCORDA); +} + +DECLARE_CUSTOM_FUNCTION(TonyConSegretaria)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_CONSEGRETARIA; + Tony->SetPattern(Tony->PAT_CONSEGRETARIA); +} + +DECLARE_CUSTOM_FUNCTION(TonyConConiglioANIM)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_CONCONIGLIO; +} + +DECLARE_CUSTOM_FUNCTION(TonyConRicettaANIM)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_CONRICETTA; +} + +DECLARE_CUSTOM_FUNCTION(TonyConCarteANIM)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_CONCARTE; +} + +DECLARE_CUSTOM_FUNCTION(TonyConPupazzoANIM)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_CONPUPAZZO; +} + +DECLARE_CUSTOM_FUNCTION(TonyConPupazzoStart)(uint32, uint32, uint32, uint32) { + nTonyNextTalkType = Tony->TALK_CONPUPAZZOSTATIC; + bStaticTalk = true; + Tony->StartStatic(Tony->TALK_CONPUPAZZOSTATIC); +} + +DECLARE_CUSTOM_FUNCTION(TonyConPupazzoEnd)(uint32, uint32, uint32, uint32) { + Tony->EndStatic(Tony->TALK_CONPUPAZZOSTATIC); + bStaticTalk = false; + nTonyNextTalkType = Tony->TALK_NORMAL; +} + +DECLARE_CUSTOM_FUNCTION(TonyConConiglioStart)(uint32, uint32, uint32, uint32) { + nTonyNextTalkType = Tony->TALK_CONCONIGLIOSTATIC; + bStaticTalk = true; + Tony->StartStatic(Tony->TALK_CONCONIGLIOSTATIC); +} + +DECLARE_CUSTOM_FUNCTION(TonyConConiglioEnd)(uint32, uint32, uint32, uint32) { + Tony->EndStatic(Tony->TALK_CONCONIGLIOSTATIC); + bStaticTalk = false; + nTonyNextTalkType = Tony->TALK_NORMAL; +} + +DECLARE_CUSTOM_FUNCTION(TonyConRicettaStart)(uint32, uint32, uint32, uint32) { + nTonyNextTalkType = Tony->TALK_CONRICETTASTATIC; + bStaticTalk = true; + Tony->StartStatic(Tony->TALK_CONRICETTASTATIC); +} + +DECLARE_CUSTOM_FUNCTION(TonyConRicettaEnd)(uint32, uint32, uint32, uint32) { + Tony->EndStatic(Tony->TALK_CONRICETTASTATIC); + bStaticTalk = false; + nTonyNextTalkType = Tony->TALK_NORMAL; +} + +DECLARE_CUSTOM_FUNCTION(TonyConCarteStart)(uint32, uint32, uint32, uint32) { + nTonyNextTalkType = Tony->TALK_CONCARTESTATIC; + bStaticTalk = true; + Tony->StartStatic(Tony->TALK_CONCARTESTATIC); +} + +DECLARE_CUSTOM_FUNCTION(TonyConCarteEnd)(uint32, uint32, uint32, uint32) { + Tony->EndStatic(Tony->TALK_CONCARTESTATIC); + bStaticTalk = false; + nTonyNextTalkType = Tony->TALK_NORMAL; +} + +DECLARE_CUSTOM_FUNCTION(TonyConTaccuinoStart)(uint32, uint32, uint32, uint32) { + nTonyNextTalkType = Tony->TALK_CONTACCUINOSTATIC; + bStaticTalk = true; + Tony->StartStatic(Tony->TALK_CONTACCUINOSTATIC); +} + +DECLARE_CUSTOM_FUNCTION(TonyConTaccuinoEnd)(uint32, uint32, uint32, uint32) { + Tony->EndStatic(Tony->TALK_CONTACCUINOSTATIC); + bStaticTalk = false; + nTonyNextTalkType = Tony->TALK_NORMAL; +} + +DECLARE_CUSTOM_FUNCTION(TonyConMegafonoStart)(uint32, uint32, uint32, uint32) { + nTonyNextTalkType = Tony->TALK_CONMEGAFONOSTATIC; + bStaticTalk = true; + Tony->StartStatic(Tony->TALK_CONMEGAFONOSTATIC); +} + +DECLARE_CUSTOM_FUNCTION(TonyConMegafonoEnd)(uint32, uint32, uint32, uint32) { + Tony->EndStatic(Tony->TALK_CONMEGAFONOSTATIC); + bStaticTalk = false; + nTonyNextTalkType = Tony->TALK_NORMAL; +} + +DECLARE_CUSTOM_FUNCTION(TonyConBarbaStart)(uint32, uint32, uint32, uint32) { + nTonyNextTalkType = Tony->TALK_CONBARBASTATIC; + bStaticTalk = true; + Tony->StartStatic(Tony->TALK_CONBARBASTATIC); +} + +DECLARE_CUSTOM_FUNCTION(TonyConBarbaEnd)(uint32, uint32, uint32, uint32) { + Tony->EndStatic(Tony->TALK_CONBARBASTATIC); + bStaticTalk = false; + nTonyNextTalkType = Tony->TALK_NORMAL; +} + +DECLARE_CUSTOM_FUNCTION(TonySpaventatoStart)(uint32, uint32, uint32, uint32) { + nTonyNextTalkType = Tony->TALK_SPAVENTATOSTATIC; + bStaticTalk = true; + Tony->StartStatic(Tony->TALK_SPAVENTATOSTATIC); +} + +DECLARE_CUSTOM_FUNCTION(TonySpaventatoEnd)(uint32, uint32, uint32, uint32) { + Tony->EndStatic(Tony->TALK_SPAVENTATOSTATIC); + bStaticTalk = false; + nTonyNextTalkType = Tony->TALK_NORMAL; +} + + + +DECLARE_CUSTOM_FUNCTION(TonySchifato)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_SCHIFATO; +} + +DECLARE_CUSTOM_FUNCTION(TonySniffaLeft)(uint32, uint32, uint32, uint32) { + Tony->SetPattern(Tony->PAT_SNIFFA_LEFT); + Tony->WaitForEndPattern(); + LeftToMe(0, 0, 0, 0); +} + +DECLARE_CUSTOM_FUNCTION(TonySniffaRight)(uint32, uint32, uint32, uint32) { + Tony->SetPattern(Tony->PAT_SNIFFA_RIGHT); + Tony->WaitForEndPattern(); + RightToMe(0, 0, 0, 0); +} + +DECLARE_CUSTOM_FUNCTION(TonyNaah)(uint32 dwText, uint32, uint32, uint32) { + TonySetNumTexts(dwText); + nTonyNextTalkType = Tony->TALK_NAAH; +} + +DECLARE_CUSTOM_FUNCTION(TonyMacbeth)(uint32 nPos, uint32, uint32, uint32) { + switch (nPos) { + case 1: + nTonyNextTalkType = Tony->TALK_MACBETH1; + break; + case 2: + nTonyNextTalkType = Tony->TALK_MACBETH2; + break; + case 3: + nTonyNextTalkType = Tony->TALK_MACBETH3; + break; + case 4: + nTonyNextTalkType = Tony->TALK_MACBETH4; + break; + case 5: + nTonyNextTalkType = Tony->TALK_MACBETH5; + break; + case 6: + nTonyNextTalkType = Tony->TALK_MACBETH6; + break; + case 7: + nTonyNextTalkType = Tony->TALK_MACBETH7; + break; + case 8: + nTonyNextTalkType = Tony->TALK_MACBETH8; + break; + case 9: + nTonyNextTalkType = Tony->TALK_MACBETH9; + break; + } +} + + +DECLARE_CUSTOM_FUNCTION(EnableTony)(uint32, uint32, uint32, uint32) { + Tony->Show(); +} + +DECLARE_CUSTOM_FUNCTION(DisableTony)(uint32 bShowOmbra, uint32, uint32, uint32) { + Tony->Hide(bShowOmbra); +} + +DECLARE_CUSTOM_FUNCTION(WaitForPatternEnd)(uint32 nItem, uint32, uint32, uint32) { + RMItem *item = Loc->GetItemFromCode(nItem); + + if (!bSkipIdle && item != NULL) + item->WaitForEndPattern(hSkipIdle); +} + + +DECLARE_CUSTOM_FUNCTION(SetTonyPosition)(uint32 nX, uint32 nY, uint32 nLoc, uint32) { + Tony->SetPosition(RMPoint(nX,nY),nLoc); +} + +DECLARE_CUSTOM_FUNCTION(MoveTonyAndWait)(uint32 nX, uint32 nY, uint32, uint32) { + Tony->Move(RMPoint(nX,nY)); + + if (!bSkipIdle) + Tony->WaitForEndMovement(); +} + +DECLARE_CUSTOM_FUNCTION(MoveTony)(uint32 nX, uint32 nY, uint32, uint32) { + Tony->Move(RMPoint(nX,nY)); +} + +DECLARE_CUSTOM_FUNCTION(ScrollLocation)(uint32 nX, uint32 nY, uint32 sX, uint32 sY) { + int lx, ly; + RMPoint pt; + + // Prende le coordinate di quanto scrollare + lx=*((int*)&nX); + ly=*((int*)&nY); + + pt=Loc->ScrollPosition(); + + while ((lx != 0 || ly != 0) && !bSkipIdle) { + if (lx>0) { + lx -= (int32)sX; if (lx<0) lx = 0; + pt.Offset((int32)sX, 0); + } else if (lx<0) { + lx += (int32)sX; if (lx>0) lx = 0; + pt.Offset(-(int32)sX, 0); + } + + if (ly > 0) { + ly-=sY; if (ly<0) ly = 0; + pt.Offset(0,sY); + } + else if (ly<0) + { + ly+=sY; if (ly>0) ly = 0; + pt.Offset(0, -(int32)sY); + } + + WaitFrame(); + + Freeze(); + Loc->SetScrollPosition(pt); + Tony->SetScrollPosition(pt); + Unfreeze(); + + } +} + +DECLARE_CUSTOM_FUNCTION(SyncScrollLocation)(uint32 nX, uint32 nY, uint32 sX, uint32 sY) { + int lx, ly; + RMPoint pt,startpt; + uint32 dwStartTime,dwCurTime,dwTotalTime; + uint32 stepX, stepY; + int dimx,dimy; + + // Prende le coordinate di quanto scrollare + lx=*((int*)&nX); + ly=*((int*)&nY); + dimx=lx; + dimy=ly; + if (lx<0) dimx = -lx; + if (ly<0) dimy = -ly; + + stepX = sX; + stepY = sY; + + startpt = Loc->ScrollPosition(); + + dwStartTime = timeGetTime(); + + if (sX) + dwTotalTime = dimx*(1000/35)/sX; + else + dwTotalTime = dimy*(1000/35)/sY; + + while ((lx != 0 || ly != 0) && !bSkipIdle) + { + dwCurTime=timeGetTime()-dwStartTime; + if (dwCurTime>dwTotalTime) + break; + + pt = startpt; + + if (sX) { + if (lx > 0) + pt.x += (dimx * dwCurTime) / dwTotalTime; + else + pt.x -= (dimx * dwCurTime) / dwTotalTime; + } else { + if (ly > 0) + pt.y += (dimy*dwCurTime) / dwTotalTime; + else + pt.y -= (dimy*dwCurTime) / dwTotalTime; + + } + +/* + sX = stepX * (dwCurTime-dwLastTime) / (1000/35); + sY = stepY * (dwCurTime-dwLastTime) / (1000/35); + + if (lx>0) + { + lx-=sX; if (lx<0) lx = 0; + pt.Offset(sX,0); + } + else if (lx<0) + { + lx+=sX; if (lx>0) lx = 0; + pt.Offset(-sX,0); + } + + if (ly>0) + { + ly-=sY; if (ly<0) ly = 0; + pt.Offset(0,sY); + } + else if (ly<0) + { + ly+=sY; if (ly>0) ly = 0; + pt.Offset(0,-sY); + } +*/ + WaitFrame(); + + Freeze(); + Loc->SetScrollPosition(pt); + Tony->SetScrollPosition(pt); + Unfreeze(); + + } + + + // Setta la posizione finale + if (sX) { + if (lx>0) + pt.x = startpt.x + dimx; + else + pt.x = startpt.x - dimx; + } else { + if (ly>0) + pt.y = startpt.y + dimy; + else + pt.y = startpt.y - dimy; + + } + + Freeze(); + Loc->SetScrollPosition(pt); + Tony->SetScrollPosition(pt); + Unfreeze(); +} + + +DECLARE_CUSTOM_FUNCTION(ChangeHotspot)(uint32 dwCode, uint32 nX, uint32 nY, uint32) { + int i; + + for (i = 0; i < curChangedHotspot; i++) + if (ChangedHotspot[i].dwCode == dwCode) { + ChangedHotspot[i].nX=nX; + ChangedHotspot[i].nY=nY; + break; + } + + if (i == curChangedHotspot) { + ChangedHotspot[i].dwCode=dwCode; + ChangedHotspot[i].nX=nX; + ChangedHotspot[i].nY=nY; + curChangedHotspot++; + } + + Loc->GetItemFromCode(dwCode)->ChangeHotspot(RMPoint(nX,nY)); +} + + +DECLARE_CUSTOM_FUNCTION(AutoSave)(uint32, uint32, uint32, uint32) { + _vm->AutoSave(); +} + +DECLARE_CUSTOM_FUNCTION(Abort)(uint32, uint32, uint32, uint32) { + _vm->Abort(); +} + +DECLARE_CUSTOM_FUNCTION(TremaSchermo)(uint32 nScosse, uint32, uint32, uint32) { + uint32 i; + uint32 curTime = _vm->GetTime(); + int dirx,diry; + + dirx = 1; + diry = 1; + + while (_vm->GetTime() < curTime + nScosse) { + WaitFrame(); + + Freeze(); + Loc->SetFixedScroll(RMPoint(1 * dirx, 1 * diry)); + Tony->SetFixedScroll(RMPoint(1 * dirx, 1 * diry)); + Unfreeze(); + + i = _vm->_randomSource.getRandomNumber(2); + + if (i == 0 || i == 2) + dirx = -dirx; + else if (i == 1 || i == 2) + diry = -diry; + } + + Freeze(); + Loc->SetFixedScroll(RMPoint(0, 0)); + Tony->SetFixedScroll(RMPoint(0, 0)); + Unfreeze(); +} + + + +/* + * Personaggi + */ + +DECLARE_CUSTOM_FUNCTION(CharSetCode)(uint32 nChar, uint32 nCode, uint32, uint32) { + assert(nChar < 16); + Character[nChar].code = nCode; + Character[nChar].item = Loc->GetItemFromCode(nCode); + Character[nChar].r = 255; + Character[nChar].g = 255; + Character[nChar].b = 255; + Character[nChar].talkpattern = 0; + Character[nChar].starttalkpattern = 0; + Character[nChar].endtalkpattern = 0; + Character[nChar].standpattern = 0; + + IsMChar[nChar] = false; +} + +DECLARE_CUSTOM_FUNCTION(CharSetColor)(uint32 nChar, uint32 r, uint32 g, uint32 b) { + assert(nChar<16); + Character[nChar].r = r; + Character[nChar].g = g; + Character[nChar].b = b; +} + +DECLARE_CUSTOM_FUNCTION(CharSetTalkPattern)(uint32 nChar, uint32 tp, uint32 sp, uint32) { + assert(nChar<16); + Character[nChar].talkpattern = tp; + Character[nChar].standpattern = sp; +} + +DECLARE_CUSTOM_FUNCTION(CharSetStartEndTalkPattern)(uint32 nChar, uint32 sp, uint32 ep, uint32) { + assert(nChar<16); + Character[nChar].starttalkpattern=sp; + Character[nChar].endtalkpattern=ep; +} + +DECLARE_CUSTOM_FUNCTION(CharSendMessage)(uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32) { + RMMessage msg(dwMessage); + int i; + RMPoint pt; + RMTextDialog *text; + int curOffset = 0; + + assert(nChar<16); + pt=Character[nChar].item->CalculatePos()-RMPoint(-60,20)-Loc->ScrollPosition(); + + if (Character[nChar].starttalkpattern != 0) { + Freeze(); + Character[nChar].item->SetPattern(Character[nChar].starttalkpattern); + Unfreeze(); + Character[nChar].item->WaitForEndPattern(); + } + + Freeze(); + Character[nChar].item->SetPattern(Character[nChar].talkpattern); + Unfreeze(); + + VoiceHeader *curVoc = SearchVoiceHeader(0, dwMessage); + FPSFX *voice = NULL; + if (curVoc) { + // Si posiziona all'interno del database delle voci all'inizio della prima +// fseek(_vm->m_vdbFP, curVoc->offset, SEEK_SET); + g_system->lockMutex(vdb); + _vm->_vdbFP.seek(curVoc->offset); + curOffset = curVoc->offset; + g_system->unlockMutex(vdb); + } + + for (i = 0; i<msg.NumPeriods() && !bSkipIdle; i++) { + if (bIsBack) { + curBackText = text = new RMTextDialogScrolling(Loc); + if (bTonyIsSpeaking) + curBackText->Hide(); + } else + text = new RMTextDialog; + + text->SetInput(Input); + + // Skipping + text->SetSkipStatus(!bIsBack); + + // Allineamento + text->SetAlignType(RMText::HCENTER,RMText::VBOTTOM); + + // Colore + text->SetColor(Character[nChar].r,Character[nChar].g,Character[nChar].b); + + // Scrive il testo + text->WriteText(msg[i],0); + + // Setta la posizione + text->SetPosition(pt); + + // Setta l'always display + if (bAlwaysDisplay) { text->SetAlwaysDisplay(); text->ForceTime(); } + + // Registra il testo + LinkGraphicTask(text); + + if (curVoc) { + g_system->lockMutex(vdb); + _vm->_theSound.CreateSfx(&voice); + _vm->_vdbFP.seek(curOffset); + voice->LoadVoiceFromVDB(_vm->_vdbFP); + voice->SetLoop(false); + if (bIsBack) voice->SetVolume(55); + voice->Play(); + text->SetCustomSkipHandle2(voice->hEndOfBuffer); + curOffset = _vm->_vdbFP.pos(); + g_system->unlockMutex(vdb); + } + + // Aspetta la fine della visualizzazione + text->SetCustomSkipHandle(hSkipIdle); + text->WaitForEndDisplay(); + + if (curVoc) { + voice->Stop(); + voice->Release(); + voice=NULL; + } + + + curBackText=NULL; + delete text; + } + + if (Character[nChar].endtalkpattern != 0) { + Freeze(); + Character[nChar].item->SetPattern(Character[nChar].endtalkpattern); + Unfreeze(); + Character[nChar].item->WaitForEndPattern(); + } + + Freeze(); + Character[nChar].item->SetPattern(Character[nChar].standpattern); + Unfreeze(); +} + +DECLARE_CUSTOM_FUNCTION(AddInventory)(uint32 dwCode, uint32, uint32, uint32) { + Inventory->AddItem(dwCode); +} + +DECLARE_CUSTOM_FUNCTION(RemoveInventory)(uint32 dwCode, uint32, uint32, uint32) { + Inventory->RemoveItem(dwCode); +} + +DECLARE_CUSTOM_FUNCTION(ChangeInventoryStatus)(uint32 dwCode, uint32 dwStatus, uint32, uint32) { + Inventory->ChangeItemStatus(dwCode,dwStatus); +} + + + + +/* + * Mastri Personaggi + */ + +DECLARE_CUSTOM_FUNCTION(MCharSetCode)(uint32 nChar, uint32 nCode, uint32, uint32) { + assert(nChar < 10); + MCharacter[nChar].code=nCode; + if (nCode== 0) + MCharacter[nChar].item=NULL; + else + MCharacter[nChar].item=Loc->GetItemFromCode(nCode); + MCharacter[nChar].r=255; + MCharacter[nChar].g=255; + MCharacter[nChar].b=255; + MCharacter[nChar].x=-1; + MCharacter[nChar].y=-1; + MCharacter[nChar].bAlwaysBack = 0; + + for (int i = 0; i < 10; i++) + MCharacter[nChar].numtalks[i] = 1; + + MCharacter[nChar].curgroup = 0; + + IsMChar[nChar] = true; +} + +DECLARE_CUSTOM_FUNCTION(MCharResetCode)(uint32 nChar, uint32, uint32, uint32) { + MCharacter[nChar].item=Loc->GetItemFromCode(MCharacter[nChar].code); +} + + +DECLARE_CUSTOM_FUNCTION(MCharSetPosition)(uint32 nChar, uint32 nX, uint32 nY, uint32) { + assert(nChar < 10); + MCharacter[nChar].x=nX; + MCharacter[nChar].y=nY; +} + + +DECLARE_CUSTOM_FUNCTION(MCharSetColor)(uint32 nChar, uint32 r, uint32 g, uint32 b) { + assert(nChar < 10); + MCharacter[nChar].r=r; + MCharacter[nChar].g=g; + MCharacter[nChar].b=b; +} + + +DECLARE_CUSTOM_FUNCTION(MCharSetNumTalksInGroup)(uint32 nChar, uint32 nGroup, uint32 nTalks, uint32) { + assert(nChar < 10); + assert(nGroup < 10); + + MCharacter[nChar].numtalks[nGroup]=nTalks; +} + + +DECLARE_CUSTOM_FUNCTION(MCharSetCurrentGroup)(uint32 nChar, uint32 nGroup, uint32, uint32) +{ + assert(nChar < 10); + assert(nGroup < 10); + + MCharacter[nChar].curgroup = nGroup; +} + +DECLARE_CUSTOM_FUNCTION(MCharSetNumTexts)(uint32 nChar, uint32 nTexts, uint32, uint32) { + assert(nChar < 10); + + MCharacter[nChar].numtexts=nTexts-1; + MCharacter[nChar].bInTexts = false; +} + +DECLARE_CUSTOM_FUNCTION(MCharSetAlwaysBack)(uint32 nChar, uint32 bAlwaysBack, uint32, uint32) { + assert(nChar < 10); + + MCharacter[nChar].bAlwaysBack=bAlwaysBack; +} + + +DECLARE_CUSTOM_FUNCTION(MCharSendMessage)(uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32 nFont) { + RMMessage msg(dwMessage); + int i; + int parm; + RMPoint pt; + HANDLE h; + RMTextDialog *text; + int curOffset = 0; + + assert(nChar < 10); + + bIsBack |= MCharacter[nChar].bAlwaysBack ? 1 : 0; + + // Calcola la posizione del testo in base al frame corrente + if (MCharacter[nChar].x==-1) + pt=MCharacter[nChar].item->CalculatePos()-RMPoint(-60,20)-Loc->ScrollPosition(); + else + pt=RMPoint(MCharacter[nChar].x,MCharacter[nChar].y); + + // Parametro per le azioni speciali: random tra le parlate + parm = (MCharacter[nChar].curgroup * 10) + _vm->_randomSource.getRandomNumber( + MCharacter[nChar].numtalks[MCharacter[nChar].curgroup] - 1) + 1; + + // Cerca di eseguire la funzione custom per inizializzare la parlata + if (MCharacter[nChar].item) { + h = mpalQueryDoAction(30,MCharacter[nChar].item->MpalCode(), parm); + if (h != INVALID_HANDLE_VALUE) + WaitForSingleObject(h,INFINITE); + } + + VoiceHeader *curVoc = SearchVoiceHeader(0, dwMessage); + FPSFX *voice = NULL; + if (curVoc) { + // Si posiziona all'interno del database delle voci all'inizio della prima + g_system->lockMutex(vdb); + // fseek(_vm->m_vdbFP, curVoc->offset, SEEK_SET); + _vm->_vdbFP.seek(curVoc->offset); + curOffset = curVoc->offset; + g_system->unlockMutex(vdb); + } + + for (i = 0; i < msg.NumPeriods() && !bSkipIdle; i++) { + // Crea l'oggetto diverso se è back o no + if (bIsBack) { + curBackText=text = new RMTextDialogScrolling(Loc); + if (bTonyIsSpeaking) + curBackText->Hide(); + } + else + text = new RMTextDialog; + + text->SetInput(Input); + + // Skipping + text->SetSkipStatus(!bIsBack); + + // Allineamento + text->SetAlignType(RMText::HCENTER,RMText::VBOTTOM); + + // Colore + text->SetColor(MCharacter[nChar].r,MCharacter[nChar].g,MCharacter[nChar].b); + + // Scrive il testo + text->WriteText(msg[i],nFont); + + // Setta la posizione + text->SetPosition(pt); + + // Setta l'always display + if (bAlwaysDisplay) { text->SetAlwaysDisplay(); text->ForceTime(); } + + // Registra il testo + LinkGraphicTask(text); + + if (curVoc) { + g_system->lockMutex(vdb); + _vm->_theSound.CreateSfx(&voice); + _vm->_vdbFP.seek(curOffset); + voice->LoadVoiceFromVDB(_vm->_vdbFP); + voice->SetLoop(false); + if (bIsBack) voice->SetVolume(55); + voice->Play(); + text->SetCustomSkipHandle2(voice->hEndOfBuffer); + curOffset = _vm->_vdbFP.pos(); + g_system->unlockMutex(vdb); + } + + // Aspetta la fine della visualizzazione + text->SetCustomSkipHandle(hSkipIdle); + text->WaitForEndDisplay(); + + if (curVoc) { + voice->Stop(); + voice->Release(); + voice=NULL; + } + + curBackText=NULL; + delete text; + } + + + // Cerca di eseguire la funzione custom per chiudere la parlata + if (MCharacter[nChar].item) { + h=mpalQueryDoAction(31,MCharacter[nChar].item->MpalCode(),parm); + if (h!=INVALID_HANDLE_VALUE) + WaitForSingleObject(h,INFINITE); + } +} + + + + + + +/* + * Dialoghi + */ + +int curDialog; + +DECLARE_CUSTOM_FUNCTION(SendDialogMessage)(uint32 nPers, uint32 nMsg, uint32, uint32) { + LPSTR string; + RMTextDialog* text; + int parm; + HANDLE h; + bool bIsBack = false; + + // La SendDialogMessage può andare in background se è un personaggio in MCHAR settato + // con la SetAlwaysBack + if (nPers != 0 && IsMChar[nPers] && MCharacter[nPers].bAlwaysBack) + bIsBack = true; + + VoiceHeader *curVoc = SearchVoiceHeader(curDialog, nMsg); + FPSFX *voice = NULL; + + if (curVoc) { + // Si posiziona all'interno del database delle voci all'inizio della prima + g_system->lockMutex(vdb); +// fseek(_vm->m_vdbFP, curVoc->offset, SEEK_SET); + _vm->_vdbFP.seek(curVoc->offset); + _vm->_theSound.CreateSfx(&voice); + voice->LoadVoiceFromVDB(_vm->_vdbFP); + voice->SetLoop(false); + if (bIsBack) voice->SetVolume(55); + g_system->unlockMutex(vdb); + } + + string=mpalQueryDialogPeriod(nMsg); + + if (nPers == 0) { + text = new RMTextDialog; + text->SetColor(0,255,0); + text->SetPosition(Tony->Position()-RMPoint(0,130)-Loc->ScrollPosition()); + text->WriteText(string,0); + + if (dwTonyNumTexts > 0) { + if (!bTonyInTexts) { + if (nTonyNextTalkType != Tony->TALK_NORMAL) { + Tony->StartTalk(nTonyNextTalkType); + if (!bStaticTalk) + nTonyNextTalkType = Tony->TALK_NORMAL; + } else + Tony->StartTalk(Tony->TALK_NORMAL); + + bTonyInTexts = true; + } + dwTonyNumTexts--; + } else { + Tony->StartTalk(nTonyNextTalkType); + if (!bStaticTalk) + nTonyNextTalkType = Tony->TALK_NORMAL; + } + } else if (!IsMChar[nPers]) { + RMPoint pt; + + text = new RMTextDialog; + + pt=Character[nPers].item->CalculatePos()-RMPoint(-60,20)-Loc->ScrollPosition(); + + if (Character[nPers].starttalkpattern != 0) { + Freeze(); + Character[nPers].item->SetPattern(Character[nPers].starttalkpattern); + Unfreeze(); + Character[nPers].item->WaitForEndPattern(); + } + + Character[nPers].item->SetPattern(Character[nPers].talkpattern); + + text->SetColor(Character[nPers].r,Character[nPers].g,Character[nPers].b); + text->WriteText(string,0); + text->SetPosition(pt); + } else { + RMPoint pt; + + if (MCharacter[nPers].x==-1) + pt=MCharacter[nPers].item->CalculatePos()-RMPoint(-60,20)-Loc->ScrollPosition(); + else + pt=RMPoint(MCharacter[nPers].x,MCharacter[nPers].y); + + // Parametro per le azioni speciali: random tra le parlate + parm = (MCharacter[nPers].curgroup * 10) + _vm->_randomSource.getRandomNumber( + MCharacter[nPers].numtalks[MCharacter[nPers].curgroup] - 1) + 1; + + if (MCharacter[nPers].numtexts != 0 && MCharacter[nPers].bInTexts) { + MCharacter[nPers].numtexts--; + } else { + // Cerca di eseguire la funzione custom per inizializzare la parlata + h = mpalQueryDoAction(30, MCharacter[nPers].item->MpalCode(), parm); + if (h != INVALID_HANDLE_VALUE) + WaitForSingleObject(h,INFINITE); + + MCharacter[nPers].curTalk = parm; + + if (MCharacter[nPers].numtexts != 0) { + MCharacter[nPers].bInTexts = true; + MCharacter[nPers].numtexts--; + } + } + + if (MCharacter[nPers].bAlwaysBack) { + text = curBackText = new RMTextDialogScrolling(Loc); + if (bTonyIsSpeaking) + curBackText->Hide(); + bIsBack = true; + } else + text = new RMTextDialog; + + text->SetSkipStatus(!MCharacter[nPers].bAlwaysBack); + text->SetColor(MCharacter[nPers].r,MCharacter[nPers].g,MCharacter[nPers].b); + text->WriteText(string,0); + text->SetPosition(pt); + } + + if (!bSkipIdle) { + text->SetInput(Input); + if (bAlwaysDisplay) { text->SetAlwaysDisplay(); text->ForceTime(); } + text->SetAlignType(RMText::HCENTER,RMText::VBOTTOM); + LinkGraphicTask(text); + + if (curVoc) { + voice->Play(); + text->SetCustomSkipHandle2(voice->hEndOfBuffer); + } + + // Aspetta la fine della visualizzazione + text->SetCustomSkipHandle(hSkipIdle); + text->WaitForEndDisplay(); + } + + if (curVoc) { + voice->Stop(); + voice->Release(); + voice=NULL; + } + + if (nPers != 0) { + if (!IsMChar[nPers]) { + if (Character[nPers].endtalkpattern != 0) { + Freeze(); + Character[nPers].item->SetPattern(Character[nPers].endtalkpattern); + Unfreeze(); + Character[nPers].item->WaitForEndPattern(); + } + + Character[nPers].item->SetPattern(Character[nPers].standpattern); + delete text; + } else { + if ((MCharacter[nPers].bInTexts && MCharacter[nPers].numtexts== 0) || !MCharacter[nPers].bInTexts) { + // Cerca di eseguire la funzione custom per chiudere la parlata + MCharacter[nPers].curTalk = (MCharacter[nPers].curTalk%10) + MCharacter[nPers].curgroup*10; + h=mpalQueryDoAction(31,MCharacter[nPers].item->MpalCode(),MCharacter[nPers].curTalk); + if (h!=INVALID_HANDLE_VALUE) + WaitForSingleObject(h,INFINITE); + + MCharacter[nPers].bInTexts = false; + MCharacter[nPers].numtexts = 0; + } + + curBackText = NULL; + delete text; + } + } else { + if ((dwTonyNumTexts== 0 && bTonyInTexts) || !bTonyInTexts) { + Tony->EndTalk(); + dwTonyNumTexts = 0; + bTonyInTexts = false; + } + + delete text; + } + + GlobalFree(string); +} + + +// @@@@ QUESTA NON SI PUO' SKIPPARE!!!!!!!!!!!!!!!!!!! + +DECLARE_CUSTOM_FUNCTION(StartDialog)(uint32 nDialog, uint32 nStartGroup, uint32, uint32) { + int nChoice; + uint32 *sl; + int i,num; + char* string; + RMDialogChoice dc; + int sel; + + curDialog = nDialog; + + // Chiama l'MPAL per iniziare il dialogo + mpalQueryDoDialog(nDialog,nStartGroup); + + // Aspetta che una scelta si presenti + while ((nChoice=mpalQueryDialogWaitForChoice()) != -1) { + // Si fa dare la lista di opzioni e le conta + sl=mpalQueryDialogSelectList(nChoice); + for (num = 0; sl[num] != 0; num++) + ; + + // Se c'e' una sola opzione, la fa automaticamente, e aspetta la prossima scelta + if (num==1) + { + mpalQueryDialogSelection(nChoice,sl[0]); + GlobalFree(sl); + continue; + } + + // Crea una scelta per il dialogo + dc.Init(); + dc.SetNumChoices(num); + + // Scrive tutte le possibili opzioni + for (i = 0;i < num; i++) { + string = mpalQueryDialogPeriod(sl[i]); + assert(string != NULL); + dc.AddChoice(string); + GlobalFree(string); + } + + // Attiva l'oggetto + LinkGraphicTask(&dc); + dc.Show(); + + // Disegna il puntatore + Pointer->SetSpecialPointer(Pointer->PTR_NONE); + MainShowMouse(); + + while (!(Input->MouseLeftClicked() && ((sel = dc.GetSelection()) != -1))) { + WaitFrame(); + Freeze(); + dc.DoFrame(Input->MousePos()); + Unfreeze(); + } + + // Nascondi il puntatore + MainHideMouse(); + + dc.Hide(); + mpalQueryDialogSelection(nChoice, sl[sel]); + + // Chiude la scelta + dc.Close(); + + GlobalFree(sl); + } +} + + + + + +/* + * Sync tra idle e mpal + */ + +DECLARE_CUSTOM_FUNCTION(TakeOwnership)(uint32 num, uint32, uint32, uint32) { +// EnterCriticalSection(&cs[num]); + WaitForSingleObject(mut[num],INFINITE); +} + +DECLARE_CUSTOM_FUNCTION(ReleaseOwnership)(uint32 num, uint32, uint32, uint32) { +// LeaveCriticalSection(&cs[num]); +// g_system->unlockMutex(mut[num]); + warning("TODO: ReleaseOwnership"); +} + + + + + + + + + + + +/* + * Musica + * ------ + * + * Effetti di fade supportati: + * + * nFX = 0 - La nuova musica si sostituisce a quella vecchia + * nFX=1 - La nuova musica si interfade con quella vecchia + * nFX=2 - La nuova musica subentra a tempo con quella vecchia + * + */ + +int curSonoriz = 0; + +bool bFadeOutStop; + +void ThreadFadeInMusic(void *nMusic) { + int i; + int nChannel = (int)nMusic; + + debug("Start FadeIn Music\n"); + + for (i = 0; i < 16; i++) { + _vm->SetMusicVolume(nChannel, i * 4); + Sleep(100); + } + _vm->SetMusicVolume(nChannel, 64); + + debug("End FadeIn Music\n"); + _endthread(); +} + +void ThreadFadeOutMusic(void *nMusic) { + int i; + int nChannel = (int)nMusic; + int startVolume = _vm->GetMusicVolume(nChannel); + + debug("Start FadeOut Music\n"); + + for (i = 16; i > 0 && !bFadeOutStop; i--) { + if (i * 4 < startVolume) + _vm->SetMusicVolume(nChannel, i * 4); + Sleep(100); + } + + if (!bFadeOutStop) + _vm->SetMusicVolume(nChannel, 0); + + // Se è uno stacchetto ferma tutto + if (nChannel == 2) + _vm->StopMusic(2); + + debug("End FadeOut Music\n"); + + _endthread(); +} + +DECLARE_CUSTOM_FUNCTION(FadeInSonoriz)(uint32, uint32, uint32, uint32) { + _beginthread(ThreadFadeInMusic, 10240, (void*)curSonoriz); +} + +DECLARE_CUSTOM_FUNCTION(FadeOutSonoriz)(uint32, uint32, uint32, uint32) { + bFadeOutStop = false; + _beginthread(ThreadFadeOutMusic, 10240, (void *)curSonoriz); +} + +DECLARE_CUSTOM_FUNCTION(FadeOutStacchetto)(uint32, uint32, uint32, uint32) { + bFadeOutStop = false; + _beginthread(ThreadFadeOutMusic, 10240, (void*)2); +} + +DECLARE_CUSTOM_FUNCTION(FadeInStacchetto)(uint32, uint32, uint32, uint32) { + _beginthread(ThreadFadeInMusic, 10240, (void*)2); +} + +DECLARE_CUSTOM_FUNCTION(StopSonoriz)(uint32, uint32, uint32, uint32) { + _vm->StopMusic(curSonoriz); +} + +DECLARE_CUSTOM_FUNCTION(StopStacchetto)(uint32, uint32, uint32, uint32) { + _vm->StopMusic(2); +} + +DECLARE_CUSTOM_FUNCTION(MuteSonoriz)(uint32, uint32, uint32, uint32) { + _vm->SetMusicVolume(curSonoriz, 0); +} + +DECLARE_CUSTOM_FUNCTION(DemuteSonoriz)(uint32, uint32, uint32, uint32) { + bFadeOutStop = true; + _vm->SetMusicVolume(curSonoriz, 64); +} + +DECLARE_CUSTOM_FUNCTION(MuteStacchetto)(uint32, uint32, uint32, uint32) { + _vm->SetMusicVolume(2, 0); +} + +DECLARE_CUSTOM_FUNCTION(DemuteStacchetto)(uint32, uint32, uint32, uint32) { + _vm->SetMusicVolume(2, 64); +} + +struct { + const char *name; + int sync; +} musicFiles[] = +{ +/* + { "PREGAME1.ADP", 0 }, { "SONO1.ADP", 0 }, + { "SONO2.ADP", 0 }, { "SONO3.ADP", 0 }, + { "CADUTA.ADP",0 }, { "RISVEGLIO.ADP", 0 }, + { "BACKGROUND.ADP", 0 }, { "PREGAME3.ADP", 0 }, + { "BARBUTA1.ADP", 2450 }, { "BARBUTA2.ADP", 0 }, +*/ + { "00.ADP", 0 }, { "01.ADP", 0 }, + { "02.ADP", 0 }, { "03.ADP", 0 }, + { "04.ADP",0 }, { "05.ADP", 0 }, + { "06.ADP", 0 }, { "07.ADP", 0 }, + { "08.ADP", 2450 }, { "09.ADP", 0 }, + +/* + { "BARBUTA3.ADP", 0 }, { "15-RUFUS.ADP", 0 }, + { "20-MAMMA.ADP", 0 }, { "32-MAMMARADIO.ADP", 0 }, + { "24-TUNNELOV-MIDI.ADP", 0 }, { "34-RAZZO.ADP", 0 }, + { "27-ZUCC1.ADP", 0 }, { "BEAST.ADP", 0 }, + { "22-MORTIMER.ADP", 0 }, { "25-PUB-OVATTATO.ADP", 0 }, +*/ + { "10.ADP", 0 }, { "11.ADP", 0 }, + { "12.ADP", 0 }, { "13.ADP", 0 }, + { "14.ADP", 0 }, { "15.ADP", 0 }, + { "16.ADP", 0 }, { "17.ADP", 0 }, + { "18.ADP", 0 }, { "19.ADP", 0 }, +/* + { "25-PUB.ADP", 0 }, { "ALBERGO.ADP", 0 }, + { "37.ADP", 0 }, { "26-PIRAT.ADP", 0 }, + { "LORENZBACK.ADP", 0 }, { "LORENZ3.ADP", 0 }, + { "CASTLE.ADP", 0 }, { "53-BACKR.ADP", 0 }, + { "16-SMIL1.ADP", 1670 }, { "16-SMIL2.ADP", 0 }, +*/ + { "20.ADP", 0 }, { "21.ADP", 0 }, + { "22.ADP", 0 }, { "23.ADP", 0 }, + { "24.ADP", 0 }, { "25.ADP", 0 }, + { "26.ADP", 0 }, { "27.ADP", 0 }, + { "28.ADP", 1670 }, { "29.ADP", 0 }, +/* + { "16-SMILE.ADP", 0 }, { "16-DIALOG2.ADP", 0 }, + { "07-SHAKE1.ADP", 2900 }, { "07-SHAKE2.ADP", 0 }, + { "07-SHAKE3.ADP", 0 }, { "46-BEEE.ADP", 0 }, + { "434748.ADP", 0 }, { "TORRE.ADP", 0 }, + { "50-DRAGO.ADP", 0 }, { "56-OPERA.ADP", 0 }, +*/ + { "30.ADP", 0 }, { "31.ADP", 0 }, + { "32.ADP", 2900 }, { "33.ADP", 0 }, + { "34.ADP", 0 }, { "35.ADP", 0 }, + { "36.ADP", 0 }, { "37.ADP", 0 }, + { "38.ADP", 0 }, { "39.ADP", 0 }, +/* + { "FLAUTARP.ADP", 0 }, { "01-2001.ADP", 1920 }, + { "02-INTROPANORAMICA.ADP", 1560 }, { "03-PANORAMICA.ADP", 1920 }, + { "04-INTERNI.ADP", 1920 }, { "05-CADEPIUMA.ADP", 1920 }, + { "06-SCENDESCALE.ADP", 1920 }, { "07-THRILL.ADP", 1920 }, + { "08-CADUTAZUCCA.ADP", 1920 }, { "09-PIUMAALEGGIA.ADP", 1920 }, +*/ + { "40.ADP", 0 }, { "41.ADP", 1920 }, + { "42.ADP", 1560 }, { "43.ADP", 1920 }, + { "44.ADP", 1920 }, { "45.ADP", 1920 }, + { "46.ADP", 1920 }, { "47.ADP", 1920 }, + { "48.ADP", 1920 }, { "49.ADP", 1920 }, + +/* + { "10-JACKZUCCONA.ADP", 1920 }, { "11-JACKIMPRECAALLAGRANDELUNA.ADP", 1920 }, + { "12-GRANDELUNALOGO.ADP", 1920 }, { "60-BACKGROUND.ADP", 0 }, + { "TONYSTAR.ADP", 0 }, { "FUNNY.ADP", 0 }, + { "60-INIZIODIALOGO.ADP", 0 }, { "60-DIALOGO.ADP", 0 }, + { "60-JACKFELICE.ADP", 0 }, { "24-TONYVIOLENTATO.ADP", 0 } +*/ + + { "50.ADP", 1920 }, { "51.ADP", 1920 }, + { "52.ADP", 1920 }, { "53.ADP", 0 }, + { "54.ADP", 0 }, { "55.ADP", 0 }, + { "56.ADP", 0 }, { "57.ADP", 0 }, + { "58.ADP", 0 }, { "59.ADP", 0 } + +}; + + +const char *staccFileNames[] = { +/* + "05-MUCCA.ADP", "06-HALOW.ADP", + "LETTERAINIZIO.ADP", "LETTERAPAURA.ADP", + "LETTERAFINE.ADP", "PREGAME2.ADP", + "07-TIMOT.ADP", "15-SHOTRUFUS.ADP", + "15-SHOTTONY.ADP", "27-ZUCC2.ADP", +*/ + "S00.ADP", "S01.ADP", + "S02.ADP", "S03.ADP", + "S04.ADP", "S05.ADP", + "S06.ADP", "S07.ADP", + "S08.ADP", "S09.ADP", + +/* + "53-DLOGO.ADP", "16-DIALOG1.ADP", + "TORRE1.ADP", "GARG1.ADP", + "LORENZ1.ADP", "24-FIGHT.ADP", + "08-MACBETH-PREPARA.ADP", "08-MACBETH-RECITA.ADP", + "GATTO1.ADP" +*/ + "S10.ADP", "S11.ADP", + "S12.ADP", "S13.ADP", + "S14.ADP", "S15.ADP", + "S16.ADP", "S17.ADP", + "S18.ADP" +}; + + +void CustPlayMusic(uint32 nChannel, const char *mFN, uint32 nFX, bool bLoop, int nSync = 0) { + if (nSync == 0) + nSync = 2000; + debug("Start CustPlayMusic\n"); + PlayMusic(nChannel, mFN, nFX, bLoop, nSync); + debug("End CustPlayMusic\n"); +} + +DECLARE_CUSTOM_FUNCTION(PlaySonoriz)(uint32 nMusic, uint32 nFX, uint32 bNoLoop, uint32) { + if (nFX == 0 || nFX == 1 || nFX==2) { + debug("PlaySonoriz stop fadeout\n"); + bFadeOutStop = true; + } + + lastMusic = nMusic; + CustPlayMusic(curSonoriz, musicFiles[nMusic].name, nFX, bNoLoop ? false : true, musicFiles[nMusic].sync); +} + +DECLARE_CUSTOM_FUNCTION(PlayStacchetto)(uint32 nMusic, uint32 nFX, uint32 bLoop, uint32) { + CustPlayMusic(2,staccFileNames[nMusic],nFX,bLoop); +} + +DECLARE_CUSTOM_FUNCTION(PlayItemSfx)(uint32 nItem, uint32 nSFX, uint32, uint32) { + if (nItem== 0) { + Tony->PlaySfx(nSFX); + } else { + RMItem *item = Loc->GetItemFromCode(nItem); + if (item) + item->PlaySfx(nSFX); + } +} + + +void RestoreMusic(void) { + PlaySonoriz(lastMusic, 0, 0, 0); + if (lastTappeto != 0) + CustPlayMusic(4, tappetiFile[lastTappeto], 0, true); +} + +void SaveMusic(Common::OutSaveFile *f) { + f->writeByte(lastMusic); + f->writeByte(lastTappeto); +} + +void LoadMusic(Common::InSaveFile *f) { + lastMusic = f->readByte(); + lastTappeto = f->readByte(); +} + + +DECLARE_CUSTOM_FUNCTION(StacchettoFadeStart)(uint32 nStacc, uint32 bLoop, uint32, uint32) { + FadeOutSonoriz(0, 0, 0, 0); + MuteStacchetto(0, 0, 0, 0); + PlayStacchetto(nStacc, 0, bLoop, 0); + FadeInStacchetto(0, 0, 0, 0); +} + +DECLARE_CUSTOM_FUNCTION(StacchettoFadeEnd)(uint32 nStacc, uint32 bLoop, uint32, uint32) { + FadeOutStacchetto(0, 0, 0, 0); + FadeInSonoriz(0, 0, 0, 0); +} + + + + +DECLARE_CUSTOM_FUNCTION(MustSkipIdleStart)(uint32, uint32, uint32, uint32) { + bSkipIdle = true; + SetEvent(hSkipIdle); +} + +DECLARE_CUSTOM_FUNCTION(MustSkipIdleEnd)(uint32, uint32, uint32, uint32) { + bSkipIdle = false; + ResetEvent(hSkipIdle); +} + +DECLARE_CUSTOM_FUNCTION(PatIrqFreeze)(uint32 bStatus, uint32, uint32, uint32) { + bPatIrqFreeze = bStatus; +} + +DECLARE_CUSTOM_FUNCTION(OpenInitLoadMenu)(uint32 , uint32, uint32, uint32) { + Freeze(); + _vm->OpenInitLoadMenu(); + Unfreeze(); +} + +DECLARE_CUSTOM_FUNCTION(OpenInitOptions)(uint32 , uint32, uint32, uint32) { + Freeze(); + _vm->OpenInitOptions(); + Unfreeze(); +} + + +DECLARE_CUSTOM_FUNCTION(DoCredits)(uint32 nMsg, uint32 dwTime, uint32, uint32) { + RMMessage msg(nMsg); + RMTextDialog *text; + HANDLE hDisable = CreateEvent(NULL, true, false, NULL); + int i; + uint32 startTime; + + text = new RMTextDialog[msg.NumPeriods()]; + + for (i = 0; i < msg.NumPeriods(); i++) { + text[i].SetInput(Input); + + // Allineamento + if (msg[i][0] == '@') { + text[i].SetAlignType(RMText::HCENTER, RMText::VTOP); + text[i].WriteText(&msg[i][1], 3); + text[i].SetPosition(RMPoint(414, 70 + i * 26)); // 70 + } else { + text[i].SetAlignType(RMText::HLEFT,RMText::VTOP); + text[i].WriteText(msg[i], 3); + text[i].SetPosition(RMPoint(260, 70 + i * 26)); + } + + + // Setta la posizione + text[i].SetAlwaysDisplay(); + text[i].SetForcedTime(dwTime * 1000); + text[i].SetNoTab(); + + // Aspetta la fine della visualizzazione + text[i].SetCustomSkipHandle(hDisable); + + // Registra il testo + LinkGraphicTask(&text[i]); + } + + startTime = _vm->GetTime(); + + while (startTime + dwTime * 1000 > _vm->GetTime()) { + WaitFrame(); + if (Input->MouseLeftClicked() || Input->MouseRightClicked()) + break; + if ((GetAsyncKeyState(Common::KEYCODE_TAB) & 0x8001) == 0x8001) + break; + } + + SetEvent(hDisable); + + WaitFrame(); + WaitFrame(); + + delete[] text; +} + + + +BEGIN_CUSTOM_FUNCTION_MAP() + + ASSIGN( 1, CustLoadLocation) + ASSIGN( 2, MySleep) + ASSIGN( 3, SetPointer) + ASSIGN( 5, MoveTony) + ASSIGN( 6, FaceToMe) + ASSIGN( 7, BackToMe) + ASSIGN( 8, LeftToMe) + ASSIGN( 9, RightToMe) + ASSIGN( 10, SendTonyMessage) + ASSIGN( 11, ChangeBoxStatus) + ASSIGN( 12, ChangeLocation) + ASSIGN( 13, DisableTony) + ASSIGN( 14, EnableTony) + ASSIGN( 15, WaitForPatternEnd) + ASSIGN( 16, SetLocStartPosition) + ASSIGN( 17, ScrollLocation) + ASSIGN( 18, MoveTonyAndWait) + ASSIGN( 19, ChangeHotspot) + ASSIGN( 20, AddInventory) + ASSIGN( 21, RemoveInventory) + ASSIGN( 22, ChangeInventoryStatus) + ASSIGN( 23, SetTonyPosition) + ASSIGN( 24, SendFullscreenMessage) + ASSIGN( 25, SaveTonyPosition) + ASSIGN( 26, RestoreTonyPosition) + ASSIGN( 27, DisableInput) + ASSIGN( 28, EnableInput) + ASSIGN( 29, StopTony) + + ASSIGN( 30, TonyTakeUp1) + ASSIGN( 31, TonyTakeMid1) + ASSIGN( 32, TonyTakeDown1) + ASSIGN( 33, TonyTakeUp2) + ASSIGN( 34, TonyTakeMid2) + ASSIGN( 35, TonyTakeDown2) + + ASSIGN( 72, TonyPutUp1) + ASSIGN( 73, TonyPutMid1) + ASSIGN( 74, TonyPutDown1) + ASSIGN( 75, TonyPutUp2) + ASSIGN( 76, TonyPutMid2) + ASSIGN( 77, TonyPutDown2) + + ASSIGN( 36, TonyPerTerra) + ASSIGN( 37, TonySiRialza) + ASSIGN( 38, TonyPastorella) + ASSIGN( 39, TonyFischietto) + + ASSIGN( 40, TonyRide) + ASSIGN( 41, TonyFianchi) + ASSIGN( 42, TonyCanta) + ASSIGN( 43, TonySiIndica) + ASSIGN( 44, TonySpaventatoConMani) + ASSIGN( 49, TonySpaventatoSenzaMani) + ASSIGN( 45, TonyConBicchiere) + ASSIGN( 46, TonyConVerme) + ASSIGN( 47, TonyConMartello) + ASSIGN( 48, TonyConCorda) + ASSIGN( 90, TonyConConiglioANIM) + ASSIGN( 91, TonyConRicettaANIM) + ASSIGN( 92, TonyConCarteANIM) + ASSIGN( 93, TonyConPupazzoANIM) + ASSIGN( 94, TonyConPupazzoStart) + ASSIGN( 95, TonyConPupazzoEnd) + ASSIGN( 96, TonyConConiglioStart) + ASSIGN( 97, TonyConConiglioEnd) + ASSIGN( 98, TonyConRicettaStart) + ASSIGN( 99, TonyConRicettaEnd) + ASSIGN(100, TonyConCarteStart) + ASSIGN(101, TonyConCarteEnd) + ASSIGN(102, TonyConTaccuinoStart) + ASSIGN(103, TonyConTaccuinoEnd) + ASSIGN(104, TonyConMegafonoStart) + ASSIGN(105, TonyConMegafonoEnd) + ASSIGN(106, TonyConBarbaStart) + ASSIGN(107, TonyConBarbaEnd) + ASSIGN(108, TonyRidacchia) + ASSIGN(109, TonySchifato) + ASSIGN(110, TonyNaah) + ASSIGN(111, TonyMacbeth) + ASSIGN(112, TonySniffaLeft) + ASSIGN(113, TonySniffaRight) + ASSIGN(114, TonySpaventatoStart) + ASSIGN(115, TonySpaventatoEnd) + ASSIGN(116, TonyConSegretaria) + + ASSIGN( 50, CharSetCode) + ASSIGN( 51, CharSetColor) + ASSIGN( 52, CharSetTalkPattern) + ASSIGN( 53, CharSendMessage) + ASSIGN( 54, CharSetStartEndTalkPattern) + + ASSIGN( 60, MCharSetCode) + ASSIGN( 61, MCharSetColor) + ASSIGN( 62, MCharSetCurrentGroup) + ASSIGN( 63, MCharSetNumTalksInGroup) + ASSIGN( 64, MCharSetNumTexts) + ASSIGN( 65, MCharSendMessage) + ASSIGN( 66, MCharSetPosition) + ASSIGN( 67, MCharSetAlwaysBack) + ASSIGN( 68, MCharResetCode) + + ASSIGN( 70, StartDialog) + ASSIGN( 71, SendDialogMessage) + + ASSIGN( 80, TakeOwnership) + ASSIGN( 81, ReleaseOwnership) + + ASSIGN( 86, PlaySonoriz) + ASSIGN( 87, PlayStacchetto) + ASSIGN( 88, FadeInSonoriz) + ASSIGN( 89, FadeOutSonoriz) + ASSIGN(123, FadeInStacchetto) + ASSIGN(124, FadeOutStacchetto) + ASSIGN(125, MuteSonoriz) + ASSIGN(126, DemuteSonoriz) + ASSIGN(127, MuteStacchetto) + ASSIGN(128, DemuteStacchetto) + ASSIGN( 84, StopSonoriz) + ASSIGN( 85, StopStacchetto) + ASSIGN( 83, PlayItemSfx) + ASSIGN(129, StacchettoFadeStart) + ASSIGN(130, StacchettoFadeEnd) + + ASSIGN(120, TremaSchermo) + ASSIGN(121, AutoSave) + ASSIGN(122, Abort) + ASSIGN(131, NoOcchioDiBue) + ASSIGN(132, SendFullscreenMsgStart) + ASSIGN(133, SendFullscreenMsgEnd) + ASSIGN(134, CustEnableGUI) + ASSIGN(135, CustDisableGUI) + ASSIGN(136, ClearScreen) + ASSIGN(137, PatIrqFreeze) + ASSIGN(138, TonySetPalesati) + ASSIGN(139, OpenInitLoadMenu) + ASSIGN(140, OpenInitOptions) + ASSIGN(141, SyncScrollLocation) + ASSIGN(142, CloseLocation) + ASSIGN(143, SetAlwaysDisplay) + ASSIGN(144, DoCredits) + + ASSIGN( 200, MustSkipIdleStart); + ASSIGN( 201, MustSkipIdleEnd); + +END_CUSTOM_FUNCTION_MAP() + +void SetupGlobalVars(RMTony *tony, RMPointer *ptr, RMGameBoxes *box, RMLocation *loc, RMInventory *inv, RMInput *input) { + Tony = tony; + Pointer = ptr; + Boxes = box; + Loc = loc; + Inventory = inv; + Input = input; + + LoadLocation = MainLoadLocation; + UnloadLocation = MainUnloadLocation; + LinkGraphicTask = MainLinkGraphicTask; + Freeze = MainFreeze; + Unfreeze = MainUnfreeze; + WaitFrame = MainWaitFrame; + PlayMusic = MainPlayMusic; + InitWipe = MainInitWipe; + CloseWipe = MainCloseWipe; + WaitWipeEnd = MainWaitWipeEnd; + DisableGUI = MainDisableGUI; + EnableGUI = MainEnableGUI; + SetPalesati = MainSetPalesati; + + g_system->lockMutex(vdb); + + bAlwaysDisplay = false; + int i; +/* + for (i = 0;i < 10; i++) + InitializeCriticalSection(&cs[i]); + for (i = 0;i < 10; i++) + mut[i] = CreateMutex(NULL, false, NULL); +*/ + for (i = 0; i < 200; i++) + tappeti[i] = 0; + + tappeti[6] = T_GRILLI; + tappeti[7] = T_GRILLI; + tappeti[8] = T_GRILLIOV; + tappeti[10] = T_GRILLI; + tappeti[12] = T_GRILLI; + tappeti[13] = T_GRILLIOV; + tappeti[15] = T_GRILLI; + tappeti[16] = T_GRILLIVENTO; + tappeti[18] = T_GRILLI; + tappeti[19] = T_GRILLIVENTO; + tappeti[20] = T_GRILLI; + tappeti[23] = T_GRILLI; + tappeti[26] = T_MAREMETA; + tappeti[27] = T_GRILLI; + tappeti[28] = T_GRILLIVENTO; + tappeti[31] = T_GRILLI; + tappeti[33] = T_MARE; + tappeti[35] = T_MARE; + tappeti[36] = T_GRILLI; + tappeti[37] = T_GRILLI; + tappeti[40] = T_GRILLI; + tappeti[41] = T_GRILLI; + tappeti[42] = T_GRILLI; + tappeti[45] = T_GRILLI; + tappeti[51] = T_GRILLI; + tappeti[52] = T_GRILLIVENTO1; + tappeti[53] = T_GRILLI; + tappeti[54] = T_GRILLI; + tappeti[57] = T_VENTO; + tappeti[58] = T_VENTO; + tappeti[60] = T_VENTO; + + + + // Crea l'evento per skippare le idle + hSkipIdle = CreateEvent(NULL, true, false, NULL); +} + +} // end of namespace Tony diff --git a/engines/tony/custom.h b/engines/tony/custom.h new file mode 100644 index 0000000000..ee85c8dd41 --- /dev/null +++ b/engines/tony/custom.h @@ -0,0 +1,106 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + */ +/************************************************************************** + * ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ * + * Nayma Software srl * + * e -= We create much MORE than ALL =- * + * u- z$$$c '. ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ * + * .d" d$$$$$b "b. * + * .z$* d$$$$$$$L ^*$c. * + * #$$$. $$$$$$$$$ .$$$" Project: Roasted Moths........ * + * ^*$b 4$$$$$$$$$F .d$*" * + * ^$$. 4$$$$$$$$$F .$P" Module: Custom.CPP........... * + * *$. '$$$$$$$$$ 4$P 4 * + * J *$ "$$$$$$$" $P r Author: Giovanni Bajo........ * + * z$ '$$$P*4c.*$$$*.z@*R$$$ $. * + * z$" "" #$F^ "" '$c Desc: Custom functions..... * + * z$$beu .ue=" $ "=e.. .zed$$c ..................... * + * "#$e z$*" . `. ^*Nc e$"" ..................... * + * "$$". .r" ^4. .^$$" ..................... * + * ^.@*"6L=\ebu^+C$"*b." * + * "**$. "c 4$$$ J" J$P*" OS: [ ] DOS [X] WIN95 [ ] PORT * + * ^"--.^ 9$" .--"" COMP: [ ] WATCOM [X] VISUAL C++ * + * " [ ] EIFFEL [ ] GCC/GXX/DJGPP * + * * + * This source code is Copyright (C) Nayma Software. ALL RIGHTS RESERVED * + * * + ************************************************************************** + +/** RCS + * + * $Id: $ + * + **/ + +#ifndef TONY_CUSTOM_H +#define TONY_CUSTOM_H + +#include "tony/mpal/mpal.h" + +namespace Tony { + +using namespace MPAL; + +/* + * Defines + */ + +typedef uint32 HWND; + +typedef void __declspec(dllexport) (*INIT_CUSTOM_FUNCTION_TYPE)(HWND, LPCUSTOMFUNCTION *); + +#define INIT_CUSTOM_FUNCTION MapCustomFunctions +#define INIT_CUSTOM_FUNCTION_STRING "MapCustomFunctions" + +#define DECLARE_CUSTOM_FUNCTION(x) void x + +#define BEGIN_CUSTOM_FUNCTION_MAP() \ + static void AssignError(HWND hWnd, int num) { \ + error("Custom function %u has been already assigned!", num); \ + } \ + void INIT_CUSTOM_FUNCTION(HWND hWnd, LPCUSTOMFUNCTION *lpMap) \ + { + + +#define END_CUSTOM_FUNCTION_MAP() \ + } + + +#define ASSIGN(num,func) \ + if (lpMap[num]!=NULL) \ + AssignError(hWnd,num); \ + lpMap[num]=func; + +class RMTony; +class RMPointer; +class RMGameBoxes; +class RMLocation; +class RMInventory; +class RMInput; + +void INIT_CUSTOM_FUNCTION(HWND hWnd, LPCUSTOMFUNCTION *lpMap); +void SetupGlobalVars(RMTony *tony, RMPointer *ptr, RMGameBoxes *box, RMLocation *loc, RMInventory *inv, RMInput *input); + +#endif + +} // end of namespace Tony diff --git a/engines/tony/detection.cpp b/engines/tony/detection.cpp index 58d16842d4..6be0ca302c 100644 --- a/engines/tony/detection.cpp +++ b/engines/tony/detection.cpp @@ -43,6 +43,10 @@ Common::Language TonyEngine::getLanguage() const { return _gameDescription->desc.language; } +bool TonyEngine::getIsDemo() const { + return _gameDescription->desc.flags & ADGF_DEMO; +} + } static const PlainGameDescriptor tonyGames[] = { diff --git a/engines/tony/font.h b/engines/tony/font.h index 348e7618ea..57a8b1c4fb 100644 --- a/engines/tony/font.h +++ b/engines/tony/font.h @@ -55,6 +55,8 @@ namespace Tony { class RMInventory; +class RMLoc; +class RMItem; /** * Gestisce un font, in cui ha varie surface per ogni lettera @@ -318,7 +320,7 @@ class RMTextItemName : protected RMText { protected: RMPoint m_mpos; RMPoint m_curscroll; - RMItem* m_item; + RMItem *m_item; RMString m_itemName; public: @@ -330,10 +332,10 @@ public: void DoFrame(RMGfxTargetBuffer &bigBuf, RMLocation &loc, RMPointer &ptr, RMInventory &inv); virtual void Draw(RMGfxTargetBuffer& bigBuf, RMGfxPrimitive* prim); - RMPoint GetHotspot() { if (m_item==NULL) return m_mpos+m_curscroll; else return m_item->Hotspot(); } - RMItem* GetSelectedItem() { return m_item; } - bool IsItemSelected() { return m_item!=NULL; } - bool IsNormalItemSelected() { return m_item!=NULL && m_itemName.Length()>0; } + RMPoint GetHotspot(); + RMItem *GetSelectedItem(); + bool IsItemSelected(); + bool IsNormalItemSelected(); virtual bool RemoveThis() { return true; } }; diff --git a/engines/tony/game.cpp b/engines/tony/game.cpp index 48827cbc2a..d759ef510a 100644 --- a/engines/tony/game.cpp +++ b/engines/tony/game.cpp @@ -45,10 +45,1158 @@ * * **************************************************************************/ +#include "common/file.h" +#include "common/savefile.h" +#include "tony/mpal/lzo.h" +#include "tony/mpal/memory.h" +#include "tony/mpal/mpal.h" +#include "tony/mpal/mpalutils.h" +#include "tony/mpal/stubs.h" +#include "tony/custom.h" #include "tony/game.h" +#include "tony/gfxengine.h" +#include "tony/tony.h" namespace Tony { +using namespace MPAL; +/****************************************/ +/* Variabili globali di configurazione */ +/****************************************/ + +// FIXME: Move into a class instance +bool bCfgInvLocked; +bool bCfgInvNoScroll; +bool bCfgTimerizedText; +bool bCfgInvUp; +bool bCfgAnni30; +bool bCfgAntiAlias; +bool bCfgSottotitoli; +bool bCfgTransparence; +bool bCfgInterTips; +bool bCfgDubbing; +bool bCfgMusic; +bool bCfgSFX; +int nCfgTonySpeed; +int nCfgTextSpeed; +int nCfgDubbingVolume; +int nCfgMusicVolume; +int nCfgSFXVolume; +bool bSkipSfxNoLoop; + +bool bPatIrqFreeze; + +/****************************************/ +/* Funzioni globali per la DLL Custom */ +/****************************************/ + +static char path_buffer[_MAX_PATH]; +static char drive[_MAX_DRIVE]; +static char dir[_MAX_DIR]; +static char fname[_MAX_FNAME]; +static char ext[_MAX_EXT]; + +HANDLE MainLoadLocation(int nLoc, RMPoint pt, RMPoint start) { + return _vm->GetEngine()->LoadLocation(nLoc,pt,start); +} + +HANDLE MainUnloadLocation(bool bDoOnExit) { + return _vm->GetEngine()->UnloadLocation(bDoOnExit); +} + +void MainLinkGraphicTask(RMGfxTask *task) { + _vm->GetEngine()->LinkGraphicTask(task); +} + +void MainFreeze(void) { + _vm->GetEngine()->Freeze(); +} + +void MainUnfreeze(void) { + _vm->GetEngine()->Unfreeze(); +} + +void MainWaitFrame(void) { + WaitForSingleObject(_vm->m_hEndOfFrame, INFINITE); +} + +void MainShowMouse(void) { + _vm->GetEngine()->EnableMouse(); +} + +void MainHideMouse(void) { + _vm->GetEngine()->DisableMouse(); +} + +void MainPlayMusic(int nChannel, char* filename, int nFX, bool bLoop, int nSync) { + _vm->PlayMusic(nChannel, filename, nFX, bLoop, nSync); +} + +void MainDisableInput(void) { + _vm->GetEngine()->DisableInput(); +} + +void MainEnableInput(void) { + _vm->GetEngine()->EnableInput(); +} + +void MainInitWipe(int type) { + _vm->GetEngine()->InitWipe(type); +} + +void MainCloseWipe(void) { + _vm->GetEngine()->CloseWipe(); +} + +void MainWaitWipeEnd(void) { + _vm->GetEngine()->WaitWipeEnd(); +} + +void MainEnableGUI(void) { + _vm->GetEngine()->m_bGUIInterface = true; + _vm->GetEngine()->m_bGUIInventory = true; + _vm->GetEngine()->m_bGUIOption = true; +} + +void MainDisableGUI(void) { + _vm->GetEngine()->m_bGUIInterface = false; + _vm->GetEngine()->m_bGUIInventory = false; + _vm->GetEngine()->m_bGUIOption = false; +} + +void MainSetPalesati(bool bPalesati) { + _vm->GetEngine()->SetPalesati(bPalesati); +} + +/****************************************************************************\ +* Metodi di RMOptionButton +\****************************************************************************/ + +RMOptionButton::RMOptionButton(uint32 dwRes, RMPoint pt, bool bDoubleState) { + RMResRaw raw(dwRes); + assert(raw.IsValid()); + m_buf = new RMGfxSourceBuffer16(false); + m_buf->Init(raw, raw.Width(), raw.Height()); + + m_rect.SetRect(pt.x, pt.y, pt.x + raw.Width() - 1, pt.y + raw.Height() - 1); + m_bActive = false; + m_bHasGfx = true; + m_bDoubleState = bDoubleState; +} + +RMOptionButton::RMOptionButton(RMRect pt) { + m_rect = pt; + m_bActive = false; + m_bHasGfx = false; + m_bDoubleState = false; +} + +RMOptionButton::~RMOptionButton() { + if (m_bHasGfx) + delete m_buf; +} + +bool RMOptionButton::DoFrame(RMPoint mousePos, bool bLeftClick, bool bRightClick) { + if (!m_bDoubleState) { + if (m_rect.PtInRect(mousePos)) { + if (!m_bActive) { + m_bActive=true; + return true; + } + } else { + if (m_bActive) { + m_bActive=false; + return true; + } + } + } else { + if (bLeftClick && m_rect.PtInRect(mousePos)) { + m_bActive = !m_bActive; + return true; + } + } + + return false; +} + + + +void RMOptionButton::Draw(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) { + if (!m_bActive) + return; + + if (m_bHasGfx) + m_buf->Draw(bigBuf,prim); +} + +void RMOptionButton::AddToList(RMGfxTargetBuffer &bigBuf) { + if (m_bHasGfx) + bigBuf.AddPrim(new RMGfxPrimitive(this, m_rect)); +} + + +/****************************************************************************\ +* RMOptionSlide methods +\****************************************************************************/ + +#define INIT_GFX16_FROMRAW(dwRes, buf16) \ + raw = new RMResRaw(dwRes); \ + assert(raw->IsValid()); \ + assert((buf16) == NULL); \ + (buf16) = new RMGfxSourceBuffer16(false); \ + (buf16)->Init(*raw,raw->Width(),raw->Height()); \ + delete raw; + +#define INIT_GFX8_FROMRAW(dwRes, buf8) \ + raw = new RMResRaw(dwRes); \ + assert(raw->IsValid()); \ + assert((buf8) == NULL); \ + (buf8) = new RMGfxSourceBuffer8RLEByte(); \ + (buf8)->Init(*raw, raw->Width(), raw->Height(), true); \ + delete raw; + +/****************************************************************************\ +* Metodi di RMGfxEngine +\****************************************************************************/ + +bool bIdleExited; + +void ExitAllIdles(int nCurLoc) { + // Chiude le idle + bSkipSfxNoLoop = true; + mpalEndIdlePoll(nCurLoc); + bIdleExited = true; + bSkipSfxNoLoop = false; + ExitThread(0); +} + + +RMGfxEngine::RMGfxEngine() { + // Crea il big buffer dove verranno disegnati i frame + m_bigBuf.Create(RM_BBX, RM_BBY, 16); + m_bigBuf.OffsetY(RM_SKIPY); +} + +RMGfxEngine::~RMGfxEngine() { + // Chiude il buffer + m_bigBuf.Destroy(); +} + +void RMGfxEngine::OpenOptionScreen(int type) { + bool bRes; + + switch (type) { + case 0: + bRes=m_opt.Init(m_bigBuf); + break; + case 1: + bRes=m_opt.InitLoadMenuOnly(m_bigBuf, true); + break; + case 2: + bRes=m_opt.InitNoLoadSave(m_bigBuf); + break; + case 3: + bRes=m_opt.InitLoadMenuOnly(m_bigBuf, false); + break; + case 4: + bRes=m_opt.InitSaveMenuOnly(m_bigBuf, false); + break; + } + + if (bRes) { + _vm->PauseSound(true); + + DisableInput(); + m_inv.EndCombine(); + m_curActionObj=0; + m_curAction=TA_GOTO; + m_point.SetAction(m_curAction); + m_point.SetSpecialPointer(RMPointer::PTR_NONE); + m_point.SetCustomPointer(NULL); + EnableMouse(); + _vm->GrabThumbnail(); + + // Esce la IDLE onde evitare la morte prematura in caricamento + m_bMustEnterMenu = true; + if (type == 1 || type == 2) { + bIdleExited = true; + } else { + m_tony.StopNoAction(); + + uint32 id; + bIdleExited = false; + CreateThread(NULL, 10240, (LPTHREAD_START_ROUTINE)ExitAllIdles, (void *)m_nCurLoc, 0, &id); + } + } +} + +void RMGfxEngine::DoFrame(bool bDrawLocation) { + g_system->lockMutex(csMainLoop); + + // Poll dei dispositivi di input + m_input.Poll(); + + if (m_bMustEnterMenu && bIdleExited) { + m_bOption = true; + m_bMustEnterMenu = false; + bIdleExited = false; + } + + if (m_bOption) { + m_opt.DoFrame(&m_input); + m_bOption = !m_opt.IsClosing(); + if (!m_bOption) { + DisableMouse(); + EnableInput(); + mpalStartIdlePoll(m_nCurLoc); + _vm->PauseSound(false); + } + } + + if (bDrawLocation && m_bLocationLoaded) { + // Locazione e oggetti + m_loc.DoFrame(&m_bigBuf); + + // Controlla gli input del mouse + if (m_bInput && !m_tony.InAction()) { + // Se siamo sull'inventario, è lui che controlla tutti gli input + if (m_inv.HaveFocus(m_input.MousePos()) && !m_inter.Active()) { + // CLICK SINISTRO + // ************** + if (m_input.MouseLeftClicked()/* && m_itemName.IsItemSelected()*/) { + // Left click attiva il combine, se siamo su un oggetto + if (m_inv.LeftClick(m_input.MousePos(),m_curActionObj)) { + m_curAction=TA_COMBINE; + m_point.SetAction(m_curAction); + } + } + else + + // CLICK DESTRO + // ************ + if (m_input.MouseRightClicked()) { + if(m_itemName.IsItemSelected()) { + m_curActionObj=0; + m_inv.RightClick(m_input.MousePos()); + } else + m_inv.RightClick(m_input.MousePos()); + } else + + // RILASCIO DESTRO + // *************** + if (m_input.MouseRightReleased()) { + if (m_inv.RightRelease(m_input.MousePos(), m_curAction)) { + m_tony.MoveAndDoAction(m_itemName.GetHotspot(), m_itemName.GetSelectedItem(), m_curAction); + + m_curAction=TA_GOTO; + m_point.SetAction(m_curAction); + } + } + } else { + // Menu Opzioni + // ************ + if (m_bGUIOption) { + if (!m_tony.InAction() && m_bInput) { + if ((m_input.MouseLeftClicked() && m_input.MousePos().x < 3 && m_input.MousePos().y < 3)) { + OpenOptionScreen(0); + goto SKIPCLICKSINISTRO; + } else if ((GetAsyncKeyState(Common::KEYCODE_ESCAPE) & 0x8001) == 0x8001) + OpenOptionScreen(0); + else if (!_vm->getIsDemo()) { + if ((GetAsyncKeyState(Common::KEYCODE_F3) & 0x8001)==0x8001) + OpenOptionScreen(3); + else if ((GetAsyncKeyState(Common::KEYCODE_F2) & 0x8001)==0x8001) + OpenOptionScreen(4); + } + } + } + + // CLICK SINISTRO + // ************** + if (m_input.MouseLeftClicked() && !m_inter.Active()) { + // Se clicko dentro un oggetto, esegui l'azione + //if (m_itemName.IsItemSelected()) + { + if (m_curAction!=TA_COMBINE) + m_tony.MoveAndDoAction(m_itemName.GetHotspot(), m_itemName.GetSelectedItem(), m_point.CurAction()); + else if (m_itemName.GetSelectedItem() != NULL) + m_tony.MoveAndDoAction(m_itemName.GetHotspot(), m_itemName.GetSelectedItem(), TA_COMBINE, m_curActionObj); + } + + if (m_curAction==TA_COMBINE) { + m_inv.EndCombine(); + m_point.SetSpecialPointer(RMPointer::PTR_NONE); + } + + m_curAction=TA_GOTO; + m_point.SetAction(m_curAction); + } + +SKIPCLICKSINISTRO: + // CLICK DESTRO + // ************ + if (m_curAction == TA_COMBINE) { + // Durante il combine, lo annulla. + if (m_input.MouseRightClicked()) { + m_inv.EndCombine(); + m_curActionObj = 0; + m_curAction = TA_GOTO; + m_point.SetAction(m_curAction); + m_point.SetSpecialPointer(RMPointer::PTR_NONE); + } + } else if (m_input.MouseRightClicked() && m_itemName.IsItemSelected() && m_point.GetSpecialPointer() == RMPointer::PTR_NONE) { + if (m_bGUIInterface) { + // Prima di aprire l'interfaccia, rimette GOTO + m_curAction = TA_GOTO; + m_curActionObj = 0; + m_point.SetAction(m_curAction); + m_inter.Clicked(m_input.MousePos()); + } + } + + + // RILASCIO DESTRO + // *************** + if (m_input.MouseRightReleased()) { + if (m_bGUIInterface) { + if (m_inter.Released(m_input.MousePos(), m_curAction)) { + m_point.SetAction(m_curAction); + m_tony.MoveAndDoAction(m_itemName.GetHotspot(), m_itemName.GetSelectedItem(), m_curAction); + + m_curAction=TA_GOTO; + m_point.SetAction(m_curAction); + } + } + } + } + + // Aggiorna il nome sotto il puntatore del mouse + m_itemName.SetMouseCoord(m_input.MousePos()); + if (!m_inter.Active() && !m_inv.MiniActive()) + m_itemName.DoFrame(m_bigBuf, m_loc, m_point, m_inv); + } + + // Inventario & interfaccia + m_inter.DoFrame(m_bigBuf, m_input.MousePos()); + m_inv.DoFrame(m_bigBuf, m_point, m_input.MousePos(), (!m_tony.InAction() && !m_inter.Active() && m_bGUIInventory)); + } + + // Anima Tony + m_tony.DoFrame(&m_bigBuf, m_nCurLoc); + + // Aggiorna lo scrolling per tenere Tony dentro lo schermo + if (m_tony.MustUpdateScrolling() && m_bLocationLoaded) { + RMPoint showThis=m_tony.Position(); + showThis.y -= 60; + m_loc.UpdateScrolling(showThis); + } + + if (m_bLocationLoaded) + m_tony.SetScrollPosition(m_loc.ScrollPosition()); + + if ((!m_tony.InAction() && m_bInput) || m_bAlwaysDrawMouse) { + m_point.SetCoord(m_input.MousePos()); + m_point.DoFrame(&m_bigBuf); + } + + // ********************** + // Disegna la lista di OT + // ********************** + m_bigBuf.DrawOT(); + +#define FSTEP (480/32) + + // Wipe + if (m_bWiping) + { + switch (m_nWipeType) { + case 1: + if (!(m_rcWipeEllipse.bottom-m_rcWipeEllipse.top>=FSTEP*2)) { + SetEvent(m_hWipeEvent); + m_nWipeType=3; + break; + } + + m_rcWipeEllipse.top+=FSTEP; + m_rcWipeEllipse.left+=FSTEP; + m_rcWipeEllipse.right-=FSTEP; + m_rcWipeEllipse.bottom-=FSTEP; + break; + + case 2: + if (!(m_rcWipeEllipse.bottom-m_rcWipeEllipse.top<480-FSTEP)) { + SetEvent(m_hWipeEvent); + m_nWipeType=3; + break; + } + + m_rcWipeEllipse.top-=FSTEP; + m_rcWipeEllipse.left-=FSTEP; + m_rcWipeEllipse.right+=FSTEP; + m_rcWipeEllipse.bottom+=FSTEP; + break; + } + } + + g_system->unlockMutex(csMainLoop); +} + + +void RMGfxEngine::InitCustomDll(void) { + SetupGlobalVars(&m_tony, &m_point, &_vm->_theBoxes, &m_loc, &m_inv, &m_input); +} + +void RMGfxEngine::ItemIrq(uint32 dwItem, int nPattern, int nStatus) { + static RMGfxEngine *This = NULL; + RMItem *item; + + // Inizializzazione! + if ((int)dwItem == -1) + { + This=(RMGfxEngine*)nPattern; + return; + } + + if (This->m_bLocationLoaded) { + item = This->m_loc.GetItemFromCode(dwItem); + if (item != NULL) { + if (nPattern != -1) { + if (bPatIrqFreeze) + MainFreeze(); + item->SetPattern(nPattern, true); + if (bPatIrqFreeze) + MainUnfreeze(); + } + if (nStatus!=-1) + item->SetStatus(nStatus); + } + } +} + +/* + // WINBUG: This is a special case for the file open/save dialog, + // which sometimes pumps while it is coming up but before it has + // disabled the main window. + HWND hWndFocus = ::GetFocus(); + bool bEnableParent = false; + m_ofn.hwndOwner = PreModal(); + AfxUnhookWindowCreate(); + if (m_ofn.hwndOwner != NULL && ::IsWindowEnabled(m_ofn.hwndOwner)) + { + bEnableParent = true; + ::EnableWindow(m_ofn.hwndOwner, false); + } + + _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); + assert(pThreadState->m_pAlternateWndInit == NULL); + + if (m_ofn.Flags & OFN_EXPLORER) + pThreadState->m_pAlternateWndInit = this; + else + AfxHookWindowCreate(this); + + int nResult; + if (m_bOpenFileDialog) + nResult = ::GetOpenFileName(&m_ofn); + else + nResult = ::GetSaveFileName(&m_ofn); + + if (nResult) + assert(pThreadState->m_pAlternateWndInit == NULL); + pThreadState->m_pAlternateWndInit = NULL; + + // WINBUG: Second part of special case for file open/save dialog. + if (bEnableParent) + ::EnableWindow(m_ofn.hwndOwner, true); + if (::IsWindow(hWndFocus)) + ::SetFocus(hWndFocus); +*/ + + +void RMGfxEngine::SelectLocation(RMPoint ptTonyStart, RMPoint start) { +#if 0 + OPENFILENAME ofn; + char lpszFileName[512]; + + // @@@ Con TonyStart=-1,-1 allora usa la posizione scritta nella locazione + + // Sceglie la locazione + ZeroMemory(lpszFileName,512); + ZeroMemory(&ofn,sizeof(ofn)); + ofn.lStructSize=sizeof(ofn); + ofn.hwndOwner=NULL; + ofn.lpstrFilter="Locazione (*.LOC)\0*.LOC\0Locazione ottimizzata (*.LOX)\0*.LOX\0Tutti i files (*.*)\0*.*\0"; + ofn.lpstrCustomFilter=NULL; + ofn.nFilterIndex=1; + ofn.lpstrFile=lpszFileName; + ofn.nMaxFile=512; + ofn.lpstrInitialDir=NULL; + ofn.lpstrTitle="Load Location"; + ofn.Flags=OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_PATHMUSTEXIST; + + if (!GetOpenFileName(&ofn)) + assert(0); + + // Carica la locazione + m_loc.Load(lpszFileName); + m_bLocationLoaded = true; + m_nCurLoc=m_loc.TEMPGetNumLoc(); + + if (ptTonyStart.x==-1 && ptTonyStart.y==-1) + InitForNewLocation(m_loc.TEMPGetNumLoc(),m_loc.TEMPGetTonyStart(),RMPoint(-1,-1)); + else + InitForNewLocation(m_loc.TEMPGetNumLoc(),ptTonyStart,start); +#endif +} + +void RMGfxEngine::InitForNewLocation(int nLoc, RMPoint ptTonyStart, RMPoint start) { + if (start.x == -1 || start.y == -1) { + start.x = ptTonyStart.x-RM_SX/2; + start.y = ptTonyStart.y-RM_SY/2; + } + + m_loc.SetScrollPosition(start); + + if (ptTonyStart.x==0 && ptTonyStart.y==0) { + } else { + m_tony.SetPosition(ptTonyStart, nLoc); + m_tony.SetScrollPosition(start); + } + + m_curAction=TA_GOTO; + m_point.SetCustomPointer(NULL); + m_point.SetSpecialPointer(RMPointer::PTR_NONE); + m_point.SetAction(m_curAction); + m_inter.Reset(); + m_inv.Reset(); + + mpalStartIdlePoll(m_nCurLoc); +} + +HANDLE RMGfxEngine::LoadLocation(int nLoc, RMPoint ptTonyStart, RMPoint start) { + bool bLoaded; + int i; + + m_nCurLoc=nLoc; + + bLoaded = false; + for (i = 0; i < 5; i++) { + // Retry sul loading della locazione + RMRes res(m_nCurLoc); + if (!res.IsValid()) + continue; +#if 0 + // codice per dumpare una locazione in caso serva una modifica + if (nLoc == 106) + { + FILE *f = fopen("loc106.lox", "wb"); + fwrite(res.DataPointer(), res.Size(), 1, f); + fclose(f); + } +#endif + m_loc.Load(res); + InitForNewLocation(nLoc, ptTonyStart, start); + bLoaded = true; + break; + } + + if (!bLoaded) + SelectLocation(ptTonyStart, start); + + if (m_bOption) + m_opt.ReInit(m_bigBuf); + + m_bLocationLoaded = true; + + // On Enter per la locazion + return INVALID_HANDLE_VALUE; //mpalQueryDoAction(0, m_nCurLoc, 0); +} + +HANDLE RMGfxEngine::UnloadLocation(bool bDoOnExit) { + HANDLE h; + + // Scarica tutta la memoria della locazione + mpalEndIdlePoll(m_nCurLoc); + + // On Exit? + if (bDoOnExit) { + h = mpalQueryDoAction(1, m_nCurLoc, 0); + if (h != INVALID_HANDLE_VALUE) + WaitForSingleObject(h, INFINITE); + } + + MainFreeze(); + + m_bLocationLoaded = false; + + m_bigBuf.ClearOT(); + m_loc.Unload(); + + return INVALID_HANDLE_VALUE; +} + +void RMGfxEngine::Init() { + // Screen loading + RMResRaw *raw; + RMGfxSourceBuffer16 *load = NULL; + INIT_GFX16_FROMRAW(20038, load); + m_bigBuf.AddPrim(new RMGfxPrimitive(load)); + m_bigBuf.DrawOT(); + m_bigBuf.ClearOT(); + delete load; + _vm->m_wnd.GetNewFrame(*this, NULL); + + + + bPatIrqFreeze = true; + + // GUI attivabile + m_bGUIOption = true; + m_bGUIInterface = true; + m_bGUIInventory = true; + + bSkipSfxNoLoop = false; + m_bMustEnterMenu = false; + bIdleExited = false; + m_bOption = false; + m_bWiping = false; + m_hWipeEvent=CreateEvent(NULL, false, false, NULL); + + // Crea l'evento di freeze + g_system->lockMutex(csMainLoop); + + // Inizializza la funzione di IRQ di Item per l'MPAL + ItemIrq((uint32)-1, (uint32)this, 0); + mpalInstallItemIrq(ItemIrq); + + // Inizializza DirectInput + m_input.Init(/*hInst*/); + + // Inizializza il puntatore del mouse + m_point.Init(); + + // Inizializza Tony + m_tony.Init(); + m_tony.LinkToBoxes(&_vm->_theBoxes); + + // Inizializza l'inventario e l'interfaccia + m_inv.Init(); + m_inter.Init(); + + // Carica la locazione e setta le priorità @@@@@ + m_bLocationLoaded = false; +/* + m_nCurLoc=1; + RMRes res(m_nCurLoc); + m_loc.Load(res); + m_loc.SetPriority(1); + m_tony.SetPosition(RMPoint(201,316),1); + //m_tony.SetPosition(RMPoint(522,305),2); + //m_tony.SetPosition(RMPoint(158,398),4); + m_tony.SetPattern(m_tony.PAT_STANDDOWN); + m_curAction=TA_GOTO; +*/ + EnableInput(); + + // Inizio del gioco + //m_tony.ExecuteAction(4,1,0); //PREGAME + + m_tony.ExecuteAction(20,1,0); + +// theLog << "Seleziona la locazione\n"; + //LoadLocation(1,RMPoint(201,316),RMPoint(-1,-1)); + //SelectLocation(); + //LoadLocation(5,RMPoint(685,338),RMPoint(-1,-1)); + //LoadLocation(7,RMPoint(153,424),RMPoint(-1,-1)); + //LoadLocation(70,RMPoint(10,10),RMPoint(-1,-1)); + //LoadLocation(20,RMPoint(112,348),RMPoint(-1,-1)); + //LoadLocation(26,RMPoint(95,456),RMPoint(-1,-1)); + //LoadLocation(12,RMPoint(221,415),RMPoint(-1,-1)); + //LoadLocation(25,RMPoint(221,415),RMPoint(-1,-1)); + //LoadLocation(16,RMPoint(111,438),RMPoint(-1,-1)); + //LoadLocation(60,RMPoint(18,302),RMPoint(-1,-1)); + + // CASTELLO + + //LoadLocation(40,RMPoint(233,441),RMPoint(-1,-1)); +} + +void RMGfxEngine::Close(void) { + m_bigBuf.ClearOT(); + + m_inter.Close(); + m_inv.Close(); + m_tony.Close(); + m_point.Close(); + m_input.Close(); +} + +void RMGfxEngine::SwitchFullscreen(bool bFull) { + m_input.SwitchFullscreen(bFull); +} + +void RMGfxEngine::GDIControl(bool bCon) +{ + m_input.GDIControl(bCon); +} + +/* +void RMGfxEngine::OptionScreen(void) +{ + if (!m_bOption) + { + if (m_opt.Init(m_bigBuf)) + { + m_bOption = true; + DisableInput(); + EnableMouse(); + } + } + else + { + if (m_opt.Close()) + { + m_bOption = false; + DisableMouse(); + EnableInput(); + } + } +} +*/ + +void RMGfxEngine::EnableInput(void) { + m_bInput = true; +} + +void RMGfxEngine::DisableInput(void) { + m_bInput = false; + m_inter.Reset(); +} + +void RMGfxEngine::EnableMouse(void) { + m_bAlwaysDrawMouse = true; +} + +void RMGfxEngine::DisableMouse(void) { + m_bAlwaysDrawMouse = false; +} + +void RMGfxEngine::Freeze(void) { + g_system->lockMutex(csMainLoop); +} + +void RMGfxEngine::Unfreeze(void) { + g_system->unlockMutex(csMainLoop); +} + +void CharsSaveAll(Common::OutSaveFile *fp); +void CharsLoadAll(Common::InSaveFile *fp); +void MCharResetCodes(void); +void SaveChangedHotspot(Common::OutSaveFile *f); +void LoadChangedHotspot(Common::InSaveFile *f); +void ReapplyChangedHotspot(void); + +void RestoreMusic(void); +void SaveMusic(Common::OutSaveFile *f); +void LoadMusic(Common::InSaveFile *f); + +unsigned char wrkmem[LZO1X_999_MEM_COMPRESS]; + +void RMGfxEngine::SaveState(const char *fn, byte *curThumb, const char *name, bool bFastCompress) { + Common::OutSaveFile *f; + byte *state, *statecmp; + byte *thumbcmp; + uint32 thumbsizecmp, thumbsize; + uint32 size, sizecmp; + int i; + char buf[4]; + RMPoint tp = m_tony.Position(); + + // Salvataggio: variabili mpal + locazione corrente + posizione di tony + inventario + + // Per ora salviamo solo lo stato MPAL + size = mpalGetSaveStateSize(); + state = new byte[size]; + statecmp = new byte[size*2]; + mpalSaveState(state); + + thumbcmp = new byte[160*120*4]; + thumbsize = 160*120*2; + + if (bFastCompress) { + lzo1x_1_compress(state, size, statecmp, &sizecmp, wrkmem); + lzo1x_1_compress(curThumb, thumbsize, thumbcmp, &thumbsizecmp, wrkmem); + } else { + lzo1x_999_compress(state, size, statecmp, &sizecmp, wrkmem); + lzo1x_999_compress(curThumb, thumbsize, thumbcmp, &thumbsizecmp, wrkmem); + } + + buf[0] = 'R'; + buf[1] = 'M'; + buf[2] = 'S'; + buf[3] = 0x7; + + f = g_system->getSavefileManager()->openForSaving(fn); + if (f == NULL) + return; + + f->write(buf, 4); + f->writeUint32LE(thumbsizecmp); + f->write(thumbcmp, thumbsizecmp); + + // Livello di difficoltà + i = mpalQueryGlobalVar("VERSIONEFACILE"); + f->writeByte(i); + + i = strlen(name); + f->writeByte(i); + f->write(name, i); + + f->writeUint32LE(m_nCurLoc); + f->writeUint32LE(tp.x); + f->writeUint32LE(tp.y); + f->writeUint32LE(size); + f->writeUint32LE(sizecmp); + + f->write(statecmp, sizecmp); + + delete [] state; + delete [] statecmp; + delete [] thumbcmp; + + // inventario + size = m_inv.GetSaveStateSize(); + state = new byte[size]; + m_inv.SaveState(state); + + f->writeUint32LE(size); + f->write(state, size); + delete[] state; + + // boxes + size = _vm->_theBoxes.GetSaveStateSize(); + state = new byte[size]; + _vm->_theBoxes.SaveState(state); + f->writeUint32LE(size); + f->write(state, size); + delete[] state; + + // New Ver5 + bool bStat; + + // Salva lo stato della pastorella e del palesati + bStat = m_tony.GetPastorella(); + f->writeByte(bStat); + bStat = m_inter.GetPalesati(); + f->writeByte(bStat); + + // Salva gli mchar + CharsSaveAll(f); + + // Salva le opzioni + f->writeByte(bCfgInvLocked); + f->writeByte(bCfgInvNoScroll); + f->writeByte(bCfgTimerizedText); + f->writeByte(bCfgInvUp); + f->writeByte(bCfgAnni30); + f->writeByte(bCfgAntiAlias); + f->writeByte(bCfgSottotitoli); + f->writeByte(bCfgTransparence); + f->writeByte(bCfgInterTips); + f->writeByte(bCfgDubbing); + f->writeByte(bCfgMusic); + f->writeByte(bCfgSFX); + f->writeByte(nCfgTonySpeed); + f->writeByte(nCfgTextSpeed); + f->writeByte(nCfgDubbingVolume); + f->writeByte(nCfgMusicVolume); + f->writeByte(nCfgSFXVolume); + + // Salva gli hotspot + SaveChangedHotspot(f); + + // Salva la musica + SaveMusic(f); + + f->finalize(); + delete f; +} + +void RMGfxEngine::LoadState(const char *fn) { + // PROBLEMA: Bisognerebbe caricare la locazione in un thread a parte per fare la OnEnter ... + Common::InSaveFile *f; + byte *state, *statecmp; + uint32 size, sizecmp; + char buf[4]; + RMPoint tp; + int loc; + int ver; + int i; + + f = g_system->getSavefileManager()->openForLoading(fn); + if (f == NULL) + return; + + f->read(buf, 4); + if (buf[0] != 'R' || buf[1] != 'M' || buf[2] != 'S') { + delete f; + return; + } + + ver = buf[3]; + + if (ver != 0x1 && ver != 0x2 && ver != 0x3 && ver != 0x4 && ver != 0x5 && ver != 0x6 && ver != 0x7) { + delete f; + return; + } + + if (ver >= 0x3) { + // C'è il thumbnail. Se ver >= 5, è compresso + if (ver >= 0x5) { + i = 0; + i = f->readUint32LE(); + f->seek(i, SEEK_CUR); + } else + f->seek(160 * 120 * 2, SEEK_CUR); + } + + if (ver >= 0x5) { + // Skip del livello di difficoltà + f->seek(1, SEEK_CUR); + } + + if (ver >= 0x4) { // Skippa il nome, che non serve a nessuno + i = f->readByte(); + f->seek(i, SEEK_CUR); + } + + loc = f->readUint32LE(); + tp.x = f->readUint32LE(); + tp.y = f->readUint32LE(); + size = f->readUint32LE(); + + if (ver >= 0x5) { + // Stato MPAL compresso! + sizecmp = f->readUint32LE(); + state = new byte[size]; + statecmp = new byte[sizecmp]; + f->read(statecmp, sizecmp); + lzo1x_decompress(statecmp, sizecmp, state, &size); + + delete[] statecmp; + } else { + state = new byte[size]; + f->read(state, size); + } + + mpalLoadState(state); + delete[] state; + + + // inventario + size = f->readUint32LE(); + state = new byte[size]; + f->read(state, size); + + m_inv.LoadState(state); + delete[] state; + + if (ver >= 0x2) { // Versione 2: box please + size = f->readUint32LE(); + state = new byte[size]; + f->read(state, size); + _vm->_theBoxes.LoadState(state); + delete[] state; + } + + if (ver >= 5) { + // Versione 5: + bool bStat = false; + + bStat = f->readByte(); + m_tony.SetPastorella(bStat); + bStat = f->readByte(); + m_inter.SetPalesati(bStat); + + CharsLoadAll(f); + } + + if (ver >= 6) { + // Carica le opzioni + bCfgInvLocked = f->readByte(); + bCfgInvNoScroll = f->readByte(); + bCfgTimerizedText = f->readByte(); + bCfgInvUp = f->readByte(); + bCfgAnni30 = f->readByte(); + bCfgAntiAlias = f->readByte(); + bCfgSottotitoli = f->readByte(); + bCfgTransparence = f->readByte(); + bCfgInterTips = f->readByte(); + bCfgDubbing = f->readByte(); + bCfgMusic = f->readByte(); + bCfgSFX = f->readByte(); + nCfgTonySpeed = f->readByte(); + nCfgTextSpeed = f->readByte(); + nCfgDubbingVolume = f->readByte(); + nCfgMusicVolume = f->readByte(); + nCfgSFXVolume = f->readByte(); + + // Carica gli hotspot + LoadChangedHotspot(f); + } + + if (ver >= 7) { + LoadMusic(f); + } + + delete f; + + UnloadLocation(false); + LoadLocation(loc, tp, RMPoint(-1, -1)); + m_tony.SetPattern(RMTony::PAT_STANDRIGHT); + MainUnfreeze(); + + // Le versioni vecchie necessitano di On enter + if (ver < 5) + mpalQueryDoAction(0, loc, 0); + else { + // In quelle nuove, ci basta resettare gli mcode + MCharResetCodes(); + } + + if (ver >= 6) + ReapplyChangedHotspot(); + + RestoreMusic(); + + m_bGUIInterface = true; + m_bGUIInventory = true; + m_bGUIOption = true; +} + +void RMGfxEngine::PauseSound(bool bPause) { + if (m_bLocationLoaded) + m_loc.PauseSound(bPause); +} + +void RMGfxEngine::InitWipe(int type) { + m_bWiping = true; + m_nWipeType=type; + m_nWipeStep=0; + + if (m_nWipeType==1) + m_rcWipeEllipse = Common::Rect(80, 0, 640 - 80, 480); + else if (m_nWipeType == 2) + m_rcWipeEllipse = Common::Rect(320 - FSTEP, 240 - FSTEP, 320 + FSTEP, 240 + FSTEP); +} + +void RMGfxEngine::CloseWipe(void) { + m_bWiping = false; +} + +void RMGfxEngine::WaitWipeEnd(void) { + WaitForSingleObject(m_hWipeEvent, INFINITE); +} } // End of namespace Tony diff --git a/engines/tony/gfxcore.h b/engines/tony/gfxcore.h index 313e471cdf..f5553d21c6 100644 --- a/engines/tony/gfxcore.h +++ b/engines/tony/gfxcore.h @@ -237,7 +237,7 @@ class RMGfxSourceBuffer : public virtual RMGfxBuffer, public RMGfxTaskSetPrior { public: // Carica i dati della surface a basso livello virtual int Init(uint32 resID, int dimx, int dimy, bool bLoadPalette = false); - virtual int Init(byte *buf, int dimx, int dimy, bool bLoadPalette = false); + virtual int Init(const byte *buf, int dimx, int dimy, bool bLoadPalette = false); virtual void Init(RMDataStream &ds, int dimx, int dimy, bool bLoadPalette = false); virtual ~RMGfxSourceBuffer(); diff --git a/engines/tony/gfxengine.h b/engines/tony/gfxengine.h index 317056315e..2019cf01c9 100644 --- a/engines/tony/gfxengine.h +++ b/engines/tony/gfxengine.h @@ -145,8 +145,8 @@ public: void Unfreeze(void); // State management - void SaveState(char *fn, byte *curThumb, char *name, bool bFastCompress = false); - void LoadState(char *fn); + void SaveState(const char *fn, byte *curThumb, const char *name, bool bFastCompress = false); + void LoadState(const char *fn); // Selects a location void SelectLocation(RMPoint ptTonyStart=RMPoint(-1,-1), RMPoint start=RMPoint(-1,-1)); diff --git a/engines/tony/input.h b/engines/tony/input.h index 6ea56024a9..554b10628b 100644 --- a/engines/tony/input.h +++ b/engines/tony/input.h @@ -75,7 +75,7 @@ public: ~RMInput(); // Class initialisation - void Init(uint32 hInst); + void Init(/*uint32 hInst*/); // Closes the class void Close(void); diff --git a/engines/tony/loc.h b/engines/tony/loc.h index 1cae9edb1e..73effc85c1 100644 --- a/engines/tony/loc.h +++ b/engines/tony/loc.h @@ -541,7 +541,7 @@ public: // Caricamento da disco bool Load(char *lpszFileName); bool Load(HANDLE hFile); - bool Load(byte *buf); + bool Load(const byte *buf); bool Load(RMDataStream &ds); bool LoadLOX(RMDataStream &ds); @@ -561,10 +561,10 @@ public: RMItem* GetItemFromCode(uint32 dwCode); // Setta la posizione corrente di scrolling - void SetScrollPosition(RMPoint &scroll); + void SetScrollPosition(const RMPoint &scroll); // Setta un offset aggiuntivo di scrolling da aggiungere sempre - void SetFixedScroll(RMPoint &scroll); + void SetFixedScroll(const RMPoint &scroll); // Aggiorna le coordinate di scrolling in modo da visualizzare sempre il punto fornito void UpdateScrolling(RMPoint ptShowThis); diff --git a/engines/tony/module.mk b/engines/tony/module.mk index cbc07d27b7..7c2c7928a8 100644 --- a/engines/tony/module.mk +++ b/engines/tony/module.mk @@ -1,6 +1,7 @@ MODULE := engines/tony MODULE_OBJS := \ + custom.o \ detection.o \ game.o \ gfxcore.o \ diff --git a/engines/tony/mpal/lzo.cpp b/engines/tony/mpal/lzo.cpp index 6cd755fc93..17b059455c 100644 --- a/engines/tony/mpal/lzo.cpp +++ b/engines/tony/mpal/lzo.cpp @@ -63,6 +63,7 @@ */ #include "lzo.h" +#include "common/textconsole.h" namespace Tony { @@ -505,6 +506,19 @@ lookbehind_overrun: #endif } +int lzo1x_1_compress(const byte *src, uint32 src_len, byte *dst, uint32 *dst_len, void *wrkmem) { + warning("TODO: lzo1x_1_compress"); + return 0; +} + +/** + * better compression ratio at the cost of more memory and time + */ +int lzo1x_999_compress(const byte *src, uint32 src_len, byte *dst, uint32 *dst_len, void *wrkmem) { + warning("TODO: lzo1x_999_compress"); + return 0; +} + } // end of namespace MPAL } // end of namespace Tony diff --git a/engines/tony/mpal/lzo.h b/engines/tony/mpal/lzo.h index 1d20c8e96e..ebb1c4b516 100644 --- a/engines/tony/mpal/lzo.h +++ b/engines/tony/mpal/lzo.h @@ -87,12 +87,23 @@ namespace MPAL { #define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ #define LZO_E_INVALID_ARGUMENT (-10) +#define LZO1X_999_MEM_COMPRESS ((uint32) (14 * 16384L * sizeof(uint16))) /** * Decompresses an LZO compressed resource */ int lzo1x_decompress(const byte *src, uint32 src_len, byte *dst, uint32 *dst_len); +/** + * Comrpess a data block into an LZO stream + */ +int lzo1x_1_compress(const byte *src, uint32 src_len, byte *dst, uint32 *dst_len, void *wrkmem); + +/** + * better compression ratio at the cost of more memory and time + */ +int lzo1x_999_compress(const byte *src, uint32 src_len, byte *dst, uint32 *dst_len, void *wrkmem); + } // end of namespace MPAL } // end of namespace Tony diff --git a/engines/tony/mpal/stubs.cpp b/engines/tony/mpal/stubs.cpp index 054ed55c68..ea93265ec9 100644 --- a/engines/tony/mpal/stubs.cpp +++ b/engines/tony/mpal/stubs.cpp @@ -59,9 +59,15 @@ HANDLE CreateThread(void *lpThreadAttributes, size_t dwStackSize, return 0; } +void _beginthread(LPTHREAD_ROUTINE lpStartAddress, size_t dwStackSize, void *lpParameter) { +} + void ExitThread(int ThreadId) { } +void _endthread() { +} + void TerminateThread(HANDLE ThreadId, uint32 dwExitCode) { } @@ -91,6 +97,10 @@ void SetEvent(HANDLE hEvent) { void ResetEvent(HANDLE hEvent) { } +uint16 GetAsyncKeyState(Common::KeyCode kc) { + return 0; +} + } // end of namespace MPAL } // end of namespace Tony diff --git a/engines/tony/mpal/stubs.h b/engines/tony/mpal/stubs.h index a8d3253ddb..9a22b65b7a 100644 --- a/engines/tony/mpal/stubs.h +++ b/engines/tony/mpal/stubs.h @@ -31,6 +31,7 @@ #include "common/scummsys.h" #include "common/algorithm.h" +#include "common/keyboard.h" #include "tony/mpal/memory.h" namespace Tony { @@ -42,6 +43,7 @@ namespace MPAL { \****************************************************************************/ typedef uint32 (*LPTHREAD_START_ROUTINE)(void *lpThreadParameter); +typedef void (*LPTHREAD_ROUTINE)(void *lpThreadParameter); /****************************************************************************\ * Defines @@ -82,8 +84,12 @@ extern HANDLE CreateThread(void *lpThreadAttributes, size_t dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, void *lpParameter, uint32 dwCreationFlags, uint32 *lpThreadId); +extern void _beginthread(LPTHREAD_ROUTINE lpStartAddress, size_t dwStackSize, void *lpParameter); + extern void ExitThread(int ThreadId); +extern void _endthread(); + extern void TerminateThread(HANDLE ThreadId, uint32 dwExitCode); extern void CloseHandle(HANDLE ThreadId); @@ -100,6 +106,8 @@ extern void SetEvent(HANDLE hEvent); extern void ResetEvent(HANDLE hEvent); +extern uint16 GetAsyncKeyState(Common::KeyCode kc); + } // end of namespace MPAL } // end of namespace Tony diff --git a/engines/tony/sound.h b/engines/tony/sound.h index 75a70553ef..c966c93888 100644 --- a/engines/tony/sound.h +++ b/engines/tony/sound.h @@ -54,7 +54,9 @@ namespace Tony { +class FPSTREAM; class FPSFX; +class CODEC; enum CODECS { FPCODEC_RAW, @@ -62,6 +64,144 @@ enum CODECS { FPCODEC_WAV }; + +/****************************************************************************\ +***************************************************************************** +* class FPSound +* ------------- +* Description: Sound driver per Falling Pumpkins +***************************************************************************** +\****************************************************************************/ + +class FPSOUND { + +private: + + bool bSoundSupported; +/* + LPDIRECTSOUND lpDS; + LPDIRECTSOUNDBUFFER lpDSBPrimary; + DSCAPS dscaps; + HWND hwnd; +*/ + +/****************************************************************************\ +* Metodi +\****************************************************************************/ + +public: + +/****************************************************************************\ +* +* Function: FPSOUND::FPSOUND(); +* +* Description: Costruttore di default. Inizializza gli attributi. +* +\****************************************************************************/ + + FPSOUND(); + + +/****************************************************************************\ +* +* Function: FPSOUND::~FPSOUND(); +* +* Description: Deinizializza l'oggetto, disallocando la memoria. +* +\****************************************************************************/ + + ~FPSOUND(); + + +/****************************************************************************\ +* +* Function: bool FPSOUND::Init(HWND hWnd); +* +* Description: Inizializza l'oggetto, e prepara tutto il necessario per +* creare stream e effetti sonori. +* +* Input: HWND hWnd Handle della finestra principale +* +* Return: True se tutto OK, FALSE in caso di errore. +* +\****************************************************************************/ + + + bool Init(/*HWND hWnd*/); + + +/****************************************************************************\ +* +* Function: bool CreateStream(FPSTREAM** lplpStream); +* +* Description: Alloca un oggetti di tipo FPSTREAM, e ritorna il suo +* puntatore dopo averlo inizializzato. +* +* Input: FPSTREAM** lplpStream Conterra' il pointer all'oggetto +* appena creato. +* +* Return: TRUE se tutto OK, FALSE in caso di errore +* +* Note: L'utilizzo di funzioni del tipo CreateStream(), CreateSfx(), +* sono dovute al fatto che i costruttori delle classi FPSTREAM +* e FPSFX richiedono che DirectSound sia gia' stato +* inzializzato. In questo modo quindi si evitano dei bugs +* che si verrebbero a creare se venisse dichiarata un oggetto +* di tipo FPSTREAM o FPSFX globale (o cmq prima della +* inizializzazione di DirectSound). +* +\****************************************************************************/ + + bool CreateStream(FPSTREAM **lplpStream); + + + +/****************************************************************************\ +* +* Function: bool CreateSfx(FPSFX** lplpSfx); +* +* Description: Alloca un oggetti di tipo FPSFX e ritorna il suo +* puntatore dopo averlo inizializzato. +* +* Input: FPSFX** lplpSfx Conterra' il pointer all'oggetto +* appena creato. +* +* Return: TRUE se tutto OK, FALSE in caso di errore +* +* Note: Vedi le note di CreateStream() +* +\****************************************************************************/ + + bool CreateSfx(FPSFX **lplpSfx); + + + +/****************************************************************************\ +* +* Function: void SetMasterVolume(int dwVolume); +* +* Description: Setta il volume generale +* +* Input: int dwVolume Volume da settare (0-63) +* +\****************************************************************************/ + + void SetMasterVolume(int dwVolume); + + +/****************************************************************************\ +* +* Function: void GetMasterVolume(LPINT lpdwVolume); +* +* Description: Richiede il volume generale +* +* Input: LPINT lpdwVolume Variabile che conterra' il volume (0-63) +* +\****************************************************************************/ + + void GetMasterVolume(int *lpdwVolume); +}; + class FPSFX { /****************************************************************************\ @@ -93,7 +233,7 @@ private: // DSBPOSITIONNOTIFY dspnHot[2]; public: -// HANDLE hEndOfBuffer; + HANDLE hEndOfBuffer; private: @@ -159,9 +299,9 @@ public: * \****************************************************************************/ - bool LoadFile(char *lpszFileName, uint32 dwCodec = FPCODEC_RAW); - bool LoadFile(byte *lpBuf, uint32 dwCodec); - bool LoadVoiceFromVDB(HANDLE hvdb); + bool LoadFile(char *lpszFileName, uint32 dwCodec = FPCODEC_RAW); + bool LoadFile(byte *lpBuf, uint32 dwCodec); + bool LoadVoiceFromVDB(Common::File &hvdb); /****************************************************************************\ @@ -249,6 +389,223 @@ public: void GetVolume(int * lpdwVolume); }; +class FPSTREAM { + +/****************************************************************************\ +* Attributi +\****************************************************************************/ + +private: + +/* + HWND hwnd; + LPDIRECTSOUND lpDS; + LPDIRECTSOUNDBUFFER lpDSBuffer; // Buffer DirectSound circolare + LPDIRECTSOUNDNOTIFY lpDSNotify; // Notify degli hotspot nel buffer +*/ + byte *lpTempBuffer; // Buffer temporaneo per decompressione + + uint32 dwBufferSize; // Dimensione del buffer in bytes + uint32 dwSize; // Dimensione dello stream in bytes + uint32 dwCodec; // CODEC utilizzato + + HANDLE hThreadEnd; // Evento per chiudere il thread + HANDLE hFile; // Handle del file di stream + HANDLE hPlayThread; // Handle del thread di play + HANDLE hHot1, hHot2, hHot3; // Eventi settati da DirectSoundNotify + HANDLE hPlayThread_PlayFast; + HANDLE hPlayThread_PlayNormal; + + bool bSoundSupported; // TRUE se il suono e' attivo + bool bFileLoaded; // TRUE se e' stato aperto un file + bool bLoop; // TRUE se bisogna loopare lo stream + bool bDoFadeOut; // TRUE se bisogna fare un fade out + bool bSyncExit; + bool bPaused; + int lastVolume; + FPSTREAM *SyncToPlay; +// DSBPOSITIONNOTIFY dspnHot[3]; + + CODEC *lpCodec; // CODEC da utilizzare. + bool CreateBuffer(int nBufSize); + +public: + bool bIsPlaying; // TRUE se si sta playando lo stream + +private: + + static void PlayThread(FPSTREAM *This); + +/****************************************************************************\ +* Metodi +\****************************************************************************/ + +public: + +/****************************************************************************\ +* +* Function: FPSTREAM(LPDIRECTSOUND lpDS, bool bSoundOn); +* +* Description: Costruttore di default. *NON* bisogna dichiarare direttamente +* un oggetto, ma crearlo piuttosto tramite FPSOUND::CreateStream() +* +\****************************************************************************/ + + FPSTREAM(void * /*LPDIRECTSOUND*/ lpDS, uint32 /*HWND hWnd */, bool bSoundOn); + + +/****************************************************************************\ +* +* Function: ~FPSTREAM(); +* +* Description: Distruttore di default. Si preoccupa anche di fermare stream +* eventualmente in esecuzione, e disallocare la memoria da +* essi occupata. +* +\****************************************************************************/ + + ~FPSTREAM(); + + +/****************************************************************************\ +* +* Function: Release(); +* +* Description: Rilascia la memoria dell'oggetto. Deve essere richiamata quando +* l'oggetto non serve piu' e **SOLO SE** l'oggetto e' stato +* creato con la FPSOUND::CreateStream(). +* +* Note: Eventuali puntatori all'oggetto non sono piu' validi dopo +* questa chiamata. +* +\****************************************************************************/ + + void Release(); + + +/****************************************************************************\ +* +* Function: bool LoadFile(char *lpszFileName, uint32 dwCodec=FPCODEC_RAW); +* +* Description: Apre un file di stream. +* +* Input: char *lpszFile Nome del file di stream da aprire +* uint32 dwCodec CODEC da utilizzare per decomprimere +* i campioni sonori +* +* Return: TRUE se tutto OK, FALSE in caso di errore +* +\****************************************************************************/ + + bool LoadFile(char *lpszFileName, uint32 dwCodec = FPCODEC_RAW, int nSync = 2000); + + + +/****************************************************************************\ +* +* Function: UnloadFile(); +* +* Description: Chiude un file di stream eventualmente aperto. E' necessario +* richiamare questa funzione per disallocare la memoria +* occupata dallo stream. +* +* Return: Il distruttore della classe per sicurezza richiama la +* UnloadFile() se non e' stata richiamata esplicitamente. +* +\****************************************************************************/ + + bool UnloadFile(); + + +/****************************************************************************\ +* +* Function: bool Play(); +* +* Description: Suona lo stream caricato. +* +* Return: TRUE se tutto OK, FALSE in caso di errore. +* +\****************************************************************************/ + + bool Play(); + void PlayFast(void); + void Prefetch(void); + + +/****************************************************************************\ +* +* Function: bool Stop(); +* +* Description: Ferma il play dello stream. +* +* Return: TRUE se tutto OK, FALSE in caso di errore. +* +\****************************************************************************/ + + bool Stop(bool bSync = false); + void WaitForSync(FPSTREAM* toplay); + + +/****************************************************************************\ +* +* Function: void Pause(bool bPause); +* +* Description: Pause dell'effetto sonoro +* +\****************************************************************************/ + + void Pause(bool bPause); + + +/****************************************************************************\ +* +* Function: bool SetLoop(bool bLoop); +* +* Description: Attiva o disattiva il loop dello stream. +* +* Input: bool bLoop TRUE per attivare il loop, FALSE per +* disattivarlo +* +* Note: Il loop deve essere attivato PRIMA di eseguire il play +* dello stream. Qualsiasi modifica effettuata durante il play +* non avra' effetto fino a che lo stream non viene fermato, +* e poi rimesso in play. +* +\****************************************************************************/ + + void SetLoop(bool bLoop); + + + +/****************************************************************************\ +* +* Function: void SetVolume(int dwVolume); +* +* Description: Cambia il volume dello stream +* +* Input: int dwVolume Volume da settare (0-63) +* +\****************************************************************************/ + + void SetVolume(int dwVolume); + + + +/****************************************************************************\ +* +* Function: void GetVolume(LPINT lpdwVolume); +* +* Description: Chiede il volume dello stream +* +* Input: LPINT lpdwVolume Variabile in cui verra' inserito +* il volume corrente +* +\****************************************************************************/ + + void GetVolume(int *lpdwVolume); +}; + + } // End of namespace Tony #endif diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp index a370c8efaf..e27cb6d9d3 100644 --- a/engines/tony/tony.cpp +++ b/engines/tony/tony.cpp @@ -49,10 +49,9 @@ Common::Error TonyEngine::run() { if (result != Common::kNoError) return result; - /* Play(); Close(); -*/ + return Common::kNoError; } @@ -60,6 +59,12 @@ Common::Error TonyEngine::run() { * Initialise the game */ Common::ErrorCode TonyEngine::Init() { + m_hEndOfFrame = CreateEvent(NULL, false, false, NULL); + + m_bPaused = false; + m_bDrawLocation = true; + m_startTime = g_system->getMillis(); + // Initialise the function list Common::fill(FuncList, FuncList + 300, (LPCUSTOMFUNCTION)NULL); @@ -98,6 +103,60 @@ void TonyEngine::GUIError(const Common::String &msg) { GUIErrorMessage(msg); } +char nextMusic[_MAX_PATH]; +bool nextLoop; +int nextChannel; +int nextSync; +int curChannel; +int flipflop=0; +OSystem::MutexRef csMusic; + + +void TonyEngine::PlayMusic(int nChannel, char* fn, int nFX, bool bLoop, int nSync) { + warning("TonyEngine::PlayMusic"); +} + +void TonyEngine::PlaySFX(int nChannel, int nFX) { + warning("TonyEngine::PlaySFX"); +} + +void TonyEngine::StopMusic(int nChannel) { + warning("TonyEngine::StopMusic"); +} + +void TonyEngine::StopSFX(int nChannel) { + warning("TonyEngine::StopSFX"); +} + +void TonyEngine::PlayUtilSFX(int nChannel, int nFX) { + warning("TonyEngine::PlayUtilSFX"); +} + +void TonyEngine::StopUtilSFX(int nChannel) { + warning("TonyEngine::StopUtilSFX"); +} + +void TonyEngine::PreloadSFX(int nChannel, char* fn) { + warning("TonyEngine::PreloadSFX"); +} + +FPSFX *TonyEngine::CreateSFX(byte *buf) { + warning("TonyEngine::CreateSFX"); + return NULL; +} + +void TonyEngine::PreloadUtilSFX(int nChannel, char *fn) { + warning("TonyEngine::PreloadUtilSFX"); +} + +void TonyEngine::UnloadAllSFX(void) { + warning("TonyEngine::UnloadAllSFX"); +} + +void TonyEngine::UnloadAllUtilSFX(void) { + warning("TonyEngine::UnloadAllUtilSFX"); +} + void TonyEngine::InitMusic() { warning("TODO: TonyEngine::InitMusic"); } @@ -160,4 +219,9 @@ void TonyEngine::CloseVoiceDatabase() { _voices.clear(); } +void TonyEngine::GrabThumbnail(void) { + //m_wnd.GrabThumbnail(m_curThumbnail); + warning("TODO: TonyEngine::GrabThumbnail"); +} + } // End of namespace Tony diff --git a/engines/tony/tony.h b/engines/tony/tony.h index a372260c34..f3b840faf5 100644 --- a/engines/tony/tony.h +++ b/engines/tony/tony.h @@ -36,6 +36,7 @@ #include "tony/gfxEngine.h" #include "tony/loc.h" #include "tony/utils.h" +#include "tony/window.h" /** * This is the namespace of the Tony engine. @@ -72,11 +73,9 @@ struct VoiceHeader { class TonyEngine : public Engine { private: Common::ErrorCode Init(); + void InitMusic(); void CloseMusic(); - void PauseSound(bool bPause); - void SetMusicVolume(int nChannel, int volume); - int GetMusicVolume(int nChannel); bool OpenVoiceDatabase(); void CloseVoiceDatabase(); protected: @@ -88,24 +87,105 @@ public: Common::RandomSource _randomSource; MPAL::MemoryManager _memoryManager; RMResUpdate _resUpdate; + HANDLE m_hEndOfFrame; Common::File _vdbFP; Common::Array<VoiceHeader> _voices; + FPSOUND _theSound; // Bounding box list manager RMGameBoxes _theBoxes; RMGfxEngine _theEngine; + RMWindow m_wnd; + bool m_bPaused; + bool m_bDrawLocation; + int m_startTime; + uint16 *m_curThumbnail; + + bool m_bQuitNow; + bool m_bTimeFreezed; + int m_nTimeFreezed; + + enum DATADIR { + DD_BASE = 1, + DD_SAVE, + DD_SHOTS, + DD_MUSIC, + DD_LAYER, + DD_UTILSFX, + DD_VOICES, + DD_BASE2 + }; public: TonyEngine(OSystem *syst, const TonyGameDescription *gameDesc); virtual ~TonyEngine(); const TonyGameDescription *_gameDescription; - uint32 getGameID() const; uint32 getFeatures() const; Common::Language getLanguage() const; uint16 getVersion() const; - uint32 getFlags() const; - Common::Platform getPlatform() const; - + bool getIsDemo() const; + RMGfxEngine *GetEngine() { return &_theEngine; } void GUIError(const Common::String &msg); + + void Play(); + void Close(); + void Abort(); + + void GetDataDirectory(DATADIR dir, char *path); + + void SwitchFullscreen(bool bFull); + void OptionScreen(void); + + void ShowLocation(void) { m_bDrawLocation = true; } + void HideLocation(void) { m_bDrawLocation = false; } + + // Mette o leva la pausa + void Pause(bool bPause); + bool IsPaused() { return m_bPaused; } + + // Reads the time + uint32 GetTime(void); + void FreezeTime(void); + void UnfreezeTime(void); + + // Music + // ****** + void PlayMusic(int nChannel, char *fn, int nFX, bool bLoop, int nSync); + void StopMusic(int nChannel); + + void PlaySFX(int nSfx, int nFX = 0); + void StopSFX(int nSfx); + + void PlayUtilSFX(int nSfx, int nFX = 0); + void StopUtilSFX(int nSfx); + + FPSFX *CreateSFX(byte *buf); + + void PreloadSFX(int nSfx, char *fn); + void UnloadAllSFX(void); + + void PreloadUtilSFX(int nSfx, char *fn); + void UnloadAllUtilSFX(void); + + // Ferma tutta la parte audio + void PauseSound(bool bPause); + + void SetMusicVolume(int nChannel, int volume); + int GetMusicVolume(int nChannel); + + // Salvataggio + void AutoSave(void); + void SaveState(int n, char *name); + void LoadState(int n); + void GetSaveStateFileName(int n, char* buf); + + // Prende il thumbnail + void GrabThumbnail(void); + uint16 *GetThumbnail(void) { return m_curThumbnail; } + + void Quit(void) { m_bQuitNow = true; } + + void OpenInitLoadMenu(void); + void OpenInitOptions(void); }; // Global reference to the TonyEngine object diff --git a/engines/tony/tonychar.h b/engines/tony/tonychar.h index 9d3c0202d0..9806fd5e58 100644 --- a/engines/tony/tonychar.h +++ b/engines/tony/tonychar.h @@ -49,6 +49,7 @@ #define TONY_TONYCHAR_H #include "tony/mpal/stubs.h" +#include "tony/loc.h" namespace Tony { diff --git a/engines/tony/utils.cpp b/engines/tony/utils.cpp index 48dcb9392a..360b7a6f32 100644 --- a/engines/tony/utils.cpp +++ b/engines/tony/utils.cpp @@ -980,7 +980,7 @@ HGLOBAL RMResUpdate::QueryResource(uint32 dwRes) { uint32 dwSize; // Decompress the data - MPAL::lzo1x_decompress(cmpBuf, info.cmpSize, lpDestBuf, &dwSize); + lzo1x_decompress(cmpBuf, info.cmpSize, lpDestBuf, &dwSize); // Delete buffer for compressed data delete [] cmpBuf; diff --git a/engines/tony/window.h b/engines/tony/window.h new file mode 100644 index 0000000000..d248ffb871 --- /dev/null +++ b/engines/tony/window.h @@ -0,0 +1,134 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +/************************************************************************** + * ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ * + * Nayma Software srl * + * e -= We create much MORE than ALL =- * + * u- z$$$c '. ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ * + * .d" d$$$$$b "b. * + * .z$* d$$$$$$$L ^*$c. * + * #$$$. $$$$$$$$$ .$$$" Project: Roasted Moths........ * + * ^*$b 4$$$$$$$$$F .d$*" * + * ^$$. 4$$$$$$$$$F .$P" Module: Window.HPP........... * + * *$. '$$$$$$$$$ 4$P 4 * + * J *$ "$$$$$$$" $P r Author: Giovanni Bajo........ * + * z$ '$$$P*4c.*$$$*.z@*R$$$ $. * + * z$" "" #$F^ "" '$c Desc: Classi per la gestione * + * z$$beu .ue=" $ "=e.. .zed$$c di una finestra Direct + * "#$e z$*" . `. ^*Nc e$"" Draw................. * + * "$$". .r" ^4. .^$$" ..................... * + * ^.@*"6L=\ebu^+C$"*b." * + * "**$. "c 4$$$ J" J$P*" OS: [ ] DOS [X] WIN95 [ ] PORT * + * ^"--.^ 9$" .--"" COMP: [ ] WATCOM [X] VISUAL C++ * + * " [ ] EIFFEL [ ] GCC/GXX/DJGPP * + * * + * This source code is Copyright (C) Nayma Software. ALL RIGHTS RESERVED * + * * + **************************************************************************/ + +#ifndef TONY_WINDOW_H +#define TONY_WINDOW_H + +#include "common/scummsys.h" +#include "common/rect.h" + +namespace Tony { + +typedef uint32 HWND; + +class RMWindow { +private: + bool Lock(/*DDSURFACEDESC& ddsd */); + void Unlock(/*DDSURFACEDESC& ddsd */); + + // Inizializza DirectDraw + void DDInit(void); + + // Chiude DirectDraw + void DDClose(void); + + // Repaint grafico tramite DirectDraw + void Repaint(void); + + // Window Proc principale che richiama la WindowProc dentro la classe +// friend LRESULT CALLBACK GlobalWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + + // Procedura di gestione messaggi +// LRESULT WindowProc(UINT msg, WPARAM wParam, LPARAM lParam); + +protected: + HWND m_hWnd; + bool m_bFullscreen; + + void * /*LPDIRECTDRAW*/ m_DD; + void * /*LPDIRECTDRAWSURFACE*/ m_Primary; + void * /*LPDIRECTDRAWSURFACE*/ m_Back; + void * /*LPDIRECTDRAWCLIPPER*/ m_MainClipper; + void * /*LPDIRECTDRAWCLIPPER*/ m_BackClipper; + + int fps, fcount; + int lastsecond, lastfcount; + + int mskRed, mskGreen, mskBlue; + + bool m_bGrabScreenshot; + bool m_bGrabThumbnail; + bool m_bGrabMovie; + uint16 *m_wThumbBuf; + + void CreateBWPrecalcTable(void); + void UpdatePixelFormat(void); + void WipeEffect(Common::Rect &rcBoundEllipse); + + public: + RMWindow() { m_Primary = NULL; m_Back = NULL; }; + ~RMWindow() { Close(); } + + // Inizializzazione + void Init(/*HINSTANCE hInst*/); + void InitDirectDraw(void); + void Close(void); + + // Switch tra windowed e fullscreen + void SwitchFullscreen(bool bFull); + + // Legge il prossimo frame + void GetNewFrame(byte *lpBuf, Common::Rect *rcBoundEllipse); + + // Avverte di grabbare un thumbnail per il salvataggio +// void GrabThumbnail(uint16 *buf); + + operator HWND() { return m_hWnd; } + + // Modi pixel format + // MODE1: 1555 + // MODE2: 5515 + // MODE3: 5551 + bool ISMODE1() { return (mskRed == 0x7C00 && mskGreen == 0x3E0 && mskBlue== 0x1F); } + bool ISMODE2() { return (mskRed == 0xF800 && mskGreen == 0x7E0 && mskBlue== 0x1F); } + bool ISMODE3() { return (mskRed == 0xF800 && mskGreen == 0x7C0 && mskBlue== 0x3E); } + bool ISMODE4() { return (mskBlue == 0xF800 && mskGreen == 0x7E0 && mskRed== 0x1F); } +}; + +} // End of namespace Tony + +#endif /* TONY_WINDOW_H */ |