diff options
Diffstat (limited to 'engines/tony/game.cpp')
-rw-r--r-- | engines/tony/game.cpp | 1148 |
1 files changed, 1148 insertions, 0 deletions
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 |