diff options
author | Paul Gilbert | 2012-05-12 21:54:37 +1000 |
---|---|---|
committer | Paul Gilbert | 2012-05-12 21:54:37 +1000 |
commit | 073e46503cd09130c3d7e2372ae50e47402569d2 (patch) | |
tree | 22ec65b1c51c3b02bb8368082c1655c8fe155f17 | |
parent | 109e5f8226c1db18926e307d4ecb9c3c83fdd7bc (diff) | |
download | scummvm-rg350-073e46503cd09130c3d7e2372ae50e47402569d2.tar.gz scummvm-rg350-073e46503cd09130c3d7e2372ae50e47402569d2.tar.bz2 scummvm-rg350-073e46503cd09130c3d7e2372ae50e47402569d2.zip |
TONY: Properly implement game saving and loading.
Saving isn't enabled in the demo, so for testing purposes I'm currently dissbling the ADGF_DEMO flag in the detection tables so saving is enabled.
-rw-r--r-- | engines/tony/game.cpp | 62 | ||||
-rw-r--r-- | engines/tony/gfxengine.cpp | 95 | ||||
-rw-r--r-- | engines/tony/input.cpp | 10 | ||||
-rw-r--r-- | engines/tony/input.h | 2 | ||||
-rw-r--r-- | engines/tony/tony.cpp | 32 | ||||
-rw-r--r-- | engines/tony/tony.h | 2 | ||||
-rw-r--r-- | engines/tony/window.cpp | 65 |
7 files changed, 120 insertions, 148 deletions
diff --git a/engines/tony/game.cpp b/engines/tony/game.cpp index e5e08f57e7..7378826a71 100644 --- a/engines/tony/game.cpp +++ b/engines/tony/game.cpp @@ -371,6 +371,7 @@ RMOptionScreen::RMOptionScreen(void) { m_menu = NULL; m_HideLoadSave = NULL; m_QuitConfirm = NULL; + m_bQuitConfirm = false; Create(RM_SX, RM_SY); @@ -1401,10 +1402,11 @@ void RMOptionScreen::RemoveThis(CORO_PARAM, bool &result) { } -bool RMOptionScreen::LoadThumbnailFromSaveState(int nState, byte *lpDestBuf, RMString& name, byte &diff) { - char buf[256]; - char namebuf[256]; int i; - Common::File f; +bool RMOptionScreen::LoadThumbnailFromSaveState(int nState, byte *lpDestBuf, RMString &name, byte &diff) { + Common::String buf; + char namebuf[256]; + int i; + Common::InSaveFile *f; char id[4]; // Pulisce la destinazione @@ -1412,60 +1414,68 @@ bool RMOptionScreen::LoadThumbnailFromSaveState(int nState, byte *lpDestBuf, RMS name = "No name"; diff = 10; - // Si fa dare il nome del salvataggio - _vm->GetSaveStateFileName(nState, buf); + // Get the savegame filename for the given slot + buf = _vm->GetSaveStateFileName(nState); - // Guarda se esiste - if (f.open(buf)) + // Try and open the savegame + f = g_system->getSavefileManager()->openForLoading(buf); + if (f == NULL) return false; - // Controlla se è giusto l'header - f.read(id, 4); + // Check to see if the file has a valid header + f->read(id, 4); if (id[0] != 'R' || id[1] != 'M' || id[2] != 'S') { - f.close(); + delete f; return false; } if (id[3] < 0x3) { - // Versione vecchia, niente screenshot - f.close(); + // Very old version that doesn't have screenshots + delete f; return true; } - // legge lo screenshot - if (id[3] >= 0x5) { + // Load the screenshot + if ((id[3] >= 0x5) && (id[3] < 0x8)) { + // Read it as an LZO compressed data block byte *cmpbuf; uint32 cmpsize, size; cmpbuf = new byte[160 * 120 * 4]; // Se la versione >= 5, è compresso! - cmpsize = f.readUint32LE(); - f.read(cmpbuf, cmpsize); + cmpsize = f->readUint32LE(); + f->read(cmpbuf, cmpsize); lzo1x_decompress(cmpbuf,cmpsize,lpDestBuf,&size); delete[] cmpbuf; - } else - f.read(lpDestBuf, 160 * 120 * 2); + } else { + // Read in the screenshot as an uncompressed data block + if (id[3] >= 8) + // Recent versions use hardcoded 160x120 uncomrpessed data, so size can be skipped + f->skip(4); + + f->read(lpDestBuf, 160 * 120 * 2); + } if (id[3] >= 0x5) { - // Legge il livello di difficoltà - diff = f.readByte(); + // Read in the difficulty level + diff = f->readByte(); } if (id[3] < 0x4) { - // Versione vecchia, niente nome - f.close(); + // Savegame version doesn't have a stored name + delete f; return true; } - i = f.readByte(); - f.read(namebuf, i); + i = f->readByte(); + f->read(namebuf, i); namebuf[i] = '\0'; name = namebuf; - f.close(); + delete f; return true; } diff --git a/engines/tony/gfxengine.cpp b/engines/tony/gfxengine.cpp index b5278b3b05..579983ad75 100644 --- a/engines/tony/gfxengine.cpp +++ b/engines/tony/gfxengine.cpp @@ -713,66 +713,55 @@ void RestoreMusic(CORO_PARAM); void SaveMusic(Common::OutSaveFile *f); void LoadMusic(Common::InSaveFile *f); -unsigned char wrkmem[LZO1X_999_MEM_COMPRESS]; +#define TONY_SAVEGAME_VERSION 8 void RMGfxEngine::SaveState(const char *fn, byte *curThumb, const char *name, bool bFastCompress) { Common::OutSaveFile *f; - byte *state, *statecmp; - byte *thumbcmp; - uint thumbsizecmp, thumbsize; - uint size, sizecmp; + byte *state; + uint thumbsize; + uint size; int i; char buf[4]; RMPoint tp = m_tony.Position(); - // Salvataggio: variabili mpal + locazione corrente + posizione di tony + inventario + // Saving: mpal variables, current location, + tony inventory position - // Per ora salviamo solo lo stato MPAL - size=mpalGetSaveStateSize(); + // For now, we only save the MPAL state + 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; + buf[3] = TONY_SAVEGAME_VERSION; f = g_system->getSavefileManager()->openForSaving(fn); - if (f==NULL) return; + if (f == NULL) + return; + f->write(buf, 4); - f->writeUint32LE(thumbsizecmp); - f->write(thumbcmp, thumbsizecmp); + f->writeUint32LE(thumbsize); + f->write(curThumb, thumbsize); - // Livello di difficoltà + // Difficulty level i = mpalQueryGlobalVar("VERSIONEFACILE"); f->writeByte(i); - i=strlen(name); + 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); + f->write(state, size); delete[] state; - delete[] statecmp; - delete[] thumbcmp; - // inventario + // Inventory size = m_inv.GetSaveStateSize(); state = new byte[size]; m_inv.SaveState(state); @@ -791,16 +780,16 @@ void RMGfxEngine::SaveState(const char *fn, byte *curThumb, const char *name, bo // New Ver5 bool bStat; - // Salva lo stato della pastorella e del palesati + // Saves the state of the shepherdess and show yourself bStat = m_tony.GetPastorella(); f->writeByte(bStat); bStat = m_inter.GetPalesati(); f->writeByte(bStat); - // Salva gli mchar + // Save the chars CharsSaveAll(f); - // Salva le opzioni + // Save the options f->writeByte(bCfgInvLocked); f->writeByte(bCfgInvNoScroll); f->writeByte(bCfgTimerizedText); @@ -819,10 +808,10 @@ void RMGfxEngine::SaveState(const char *fn, byte *curThumb, const char *name, bo f->writeByte(nCfgMusicVolume); f->writeByte(nCfgSFXVolume); - // Salva gli hotspot + // Save the hotspots SaveChangedHotspot(f); - // Salva la musica + // Save the music SaveMusic(f); f->finalize(); @@ -845,8 +834,10 @@ void RMGfxEngine::LoadState(CORO_PARAM, const char *fn) { CORO_BEGIN_CODE(_ctx); _ctx->f = g_system->getSavefileManager()->openForLoading(fn); - if (_ctx->f == NULL) return; + if (_ctx->f == NULL) + return; _ctx->f->read(_ctx->buf, 4); + if (_ctx->buf[0] != 'R' || _ctx->buf[1] != 'M' || _ctx->buf[2] != 'S') { delete _ctx->f; return; @@ -854,39 +845,43 @@ void RMGfxEngine::LoadState(CORO_PARAM, const char *fn) { _ctx->ver = _ctx->buf[3]; - if (_ctx->ver != 0x1 && _ctx->ver != 0x2 && _ctx->ver != 0x3 && _ctx->ver != 0x4 && _ctx->ver != 0x5 && _ctx->ver != 0x6 && _ctx->ver != 0x7) { + if (_ctx->ver == 0 || _ctx->ver > TONY_SAVEGAME_VERSION) { delete _ctx->f; return; } if (_ctx->ver >= 0x3) { - // C'è il thumbnail. Se _ctx->ver >= 5, è compresso - if (_ctx->ver >= 0x5) { + // There is a thumbnail. If the version is between 5 and 7, it's compressed + if ((_ctx->ver >= 0x5) && (_ctx->ver <= 0x7)) { _ctx->i = 0; _ctx->i = _ctx->f->readUint32LE(); _ctx->f->seek(_ctx->i); - } else + } else { + if (_ctx->ver >= 8) + // Skip thumbnail size + _ctx->f->skip(4); + _ctx->f->seek(160 * 120 * 2, SEEK_CUR); + } } if (_ctx->ver >= 0x5) { - // Skip del livello di difficoltà + // Skip the difficulty level _ctx->f->seek(1, SEEK_CUR); } - if (_ctx->ver >= 0x4) { // Skippa il nome, che non serve a nessuno + if (_ctx->ver >= 0x4) { // Skip the savegame name, which serves no purpose _ctx->i = _ctx->f->readByte(); _ctx->f->seek(_ctx->i, SEEK_CUR); } _ctx->loc = _ctx->f->readUint32LE(); - _ctx->loc = _ctx->f->readUint32LE(); _ctx->tp.x = _ctx->f->readUint32LE(); _ctx->tp.y = _ctx->f->readUint32LE(); _ctx->size = _ctx->f->readUint32LE(); - if (_ctx->ver >= 0x5) { - // Stato MPAL compresso! + if ((_ctx->ver >= 0x5) && (_ctx->ver <= 7)) { + // MPAL was packed! _ctx->sizecmp = _ctx->f->readUint32LE(); _ctx->state = new byte[_ctx->size]; _ctx->statecmp = new byte[_ctx->sizecmp]; @@ -894,6 +889,7 @@ void RMGfxEngine::LoadState(CORO_PARAM, const char *fn) { lzo1x_decompress(_ctx->statecmp,_ctx->sizecmp,_ctx->state,&_ctx->size); delete[] _ctx->statecmp; } else { + // Read uncompressed MPAL data _ctx->state = new byte[_ctx->size]; _ctx->f->read(_ctx->state, _ctx->size); } @@ -901,8 +897,7 @@ void RMGfxEngine::LoadState(CORO_PARAM, const char *fn) { mpalLoadState(_ctx->state); delete[] _ctx->state; - - // inventario + // Inventory _ctx->size = _ctx->f->readUint32LE(); _ctx->state = new byte[_ctx->size]; _ctx->f->read(_ctx->state, _ctx->size); @@ -930,7 +925,7 @@ void RMGfxEngine::LoadState(CORO_PARAM, const char *fn) { } if (_ctx->ver >= 6) { - // Carica le opzioni + // Load options bCfgInvLocked = _ctx->f->readByte(); bCfgInvNoScroll = _ctx->f->readByte(); bCfgTimerizedText = _ctx->f->readByte(); @@ -949,7 +944,7 @@ void RMGfxEngine::LoadState(CORO_PARAM, const char *fn) { nCfgMusicVolume = _ctx->f->readByte(); nCfgSFXVolume = _ctx->f->readByte(); - // Carica gli hotspot + // Load hotspots LoadChangedHotspot(_ctx->f); } @@ -964,11 +959,11 @@ void RMGfxEngine::LoadState(CORO_PARAM, const char *fn) { m_tony.SetPattern(RMTony::PAT_STANDRIGHT); MainUnfreeze(); - // Le versioni vecchie necessitano di On enter + // On older versions, need to an enter action if (_ctx->ver < 5) mpalQueryDoAction(0, _ctx->loc, 0); else { - // In quelle nuove, ci basta resettare gli mcode + // In the new ones, we just reset the mcode MCharResetCodes(); } diff --git a/engines/tony/input.cpp b/engines/tony/input.cpp index bd90ec641d..fcd56b5989 100644 --- a/engines/tony/input.cpp +++ b/engines/tony/input.cpp @@ -127,4 +127,14 @@ bool RMInput::MouseRight() { return _rightButton; } +/** + * Return true if a key has been pressed */ +bool RMInput::GetAsyncKeyState(Common::KeyCode kc) { + // The act of testing for a particular key automatically clears the state, to prevent + // the same key being registered in multiple different frames + bool result = _keyDown[(int)kc]; + _keyDown[(int)kc] = false; + return result; +} + } // End of namespace Tony diff --git a/engines/tony/input.h b/engines/tony/input.h index acb7fbd677..79a11db678 100644 --- a/engines/tony/input.h +++ b/engines/tony/input.h @@ -98,7 +98,7 @@ public: bool MouseBothReleased() { return _leftReleaseMouse && _rightReleaseMouse; } // Returns true if the given key is pressed - bool GetAsyncKeyState(Common::KeyCode kc) { return _keyDown[(int)kc]; } + bool GetAsyncKeyState(Common::KeyCode kc); }; } // End of namespace Tony diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp index f86576d5c2..56b68419fd 100644 --- a/engines/tony/tony.cpp +++ b/engines/tony/tony.cpp @@ -389,20 +389,13 @@ int TonyEngine::GetMusicVolume(int nChannel) { } -void TonyEngine::GetSaveStateFileName(int n, char *buf) { - RMString name; - - if (n > 0) - name.Format("%02d", n); - else - name.Format("autosave"); - - name += ".sav"; +Common::String TonyEngine::GetSaveStateFileName(int n) { + return Common::String::format("tony.%03d", n); } void TonyEngine::AutoSave(CORO_PARAM) { CORO_BEGIN_CONTEXT; - char buf[256]; + Common::String buf; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); @@ -411,8 +404,8 @@ void TonyEngine::AutoSave(CORO_PARAM) { CORO_INVOKE_0(MainWaitFrame); CORO_INVOKE_0(MainWaitFrame); MainFreeze(); - GetSaveStateFileName(0, _ctx->buf); - _theEngine.SaveState(_ctx->buf, (byte *)m_curThumbnail, "Autosave", true); + _ctx->buf = GetSaveStateFileName(0); + _theEngine.SaveState(_ctx->buf.c_str(), (byte *)m_curThumbnail, "Autosave", true); MainUnfreeze(); CORO_END_CODE; @@ -420,22 +413,20 @@ void TonyEngine::AutoSave(CORO_PARAM) { void TonyEngine::SaveState(int n, const char *name) { - char buf[256]; - - GetSaveStateFileName(n, buf); - _theEngine.SaveState(buf,(byte *)m_curThumbnail, name); + Common::String buf = GetSaveStateFileName(n); + _theEngine.SaveState(buf.c_str(), (byte *)m_curThumbnail, name); } void TonyEngine::LoadState(CORO_PARAM, int n) { CORO_BEGIN_CONTEXT; - char buf[256]; + Common::String buf; CORO_END_CONTEXT(_ctx); CORO_BEGIN_CODE(_ctx); - GetSaveStateFileName(n, _ctx->buf); - CORO_INVOKE_1(_theEngine.LoadState, _ctx->buf); + _ctx->buf = GetSaveStateFileName(n); + CORO_INVOKE_1(_theEngine.LoadState, _ctx->buf.c_str()); CORO_END_CODE; } @@ -485,8 +476,7 @@ void TonyEngine::CloseVoiceDatabase() { } void TonyEngine::GrabThumbnail(void) { - //_window.GrabThumbnail(m_curThumbnail); - warning("TODO: TonyEngine::GrabThumbnail"); + _window.GrabThumbnail(m_curThumbnail); } void TonyEngine::OptionScreen(void) { diff --git a/engines/tony/tony.h b/engines/tony/tony.h index 69b54e8edb..4a80970bb9 100644 --- a/engines/tony/tony.h +++ b/engines/tony/tony.h @@ -194,7 +194,7 @@ public: void AutoSave(CORO_PARAM); void SaveState(int n, const char *name); void LoadState(CORO_PARAM, int n); - void GetSaveStateFileName(int n, char *buf); + Common::String GetSaveStateFileName(int n); // Prende il thumbnail void GrabThumbnail(void); diff --git a/engines/tony/window.cpp b/engines/tony/window.cpp index da49b91109..2518250bc7 100644 --- a/engines/tony/window.cpp +++ b/engines/tony/window.cpp @@ -90,7 +90,8 @@ void RMWindow::Close(void) { } void RMWindow::GrabThumbnail(uint16 *thumbmem) { - warning("TODO: RMWindow::GrabThumbnail"); + m_bGrabThumbnail = true; + m_wThumbBuf = thumbmem; } /** @@ -135,6 +136,14 @@ void RMWindow::GetNewFrame(byte *lpBuf, Common::Rect *rcBoundEllipse) { // Standard screen copy g_system->copyRectToScreen(lpBuf, RM_SX * 2, 0, 0, RM_SX, RM_SY); } + + if (m_bGrabThumbnail) { + // Need to generate a thumbnail + RMSnapshot s; + + s.GrabScreenshot(lpBuf, 4, m_wThumbBuf); + m_bGrabThumbnail = false; + } } /** @@ -270,7 +279,6 @@ bool RMSnapshot::GetFreeSnapName(char *fn) { } void RMSnapshot::GrabScreenshot(byte *lpBuf, int dezoom, uint16 *lpDestBuf) { -#ifdef REFACTOR_ME uint16 *src = (uint16 *)lpBuf; int dimx = RM_SX / dezoom; @@ -278,15 +286,15 @@ void RMSnapshot::GrabScreenshot(byte *lpBuf, int dezoom, uint16 *lpDestBuf) { int u, v, curv; - uint16 appo; - uint32 k = 0; + uint16 appo; + uint32 k = 0; int sommar, sommab, sommag; uint16 *cursrc; if (lpDestBuf == NULL) src += (RM_SY - 1) * RM_BBX; - if (dezoom == 1 && 0) { // @@@ NON E' TESTATA MOLTO BENE!!! + if (dezoom == 1 && 0) { byte *curOut = rgb; for (int y = 0; y < dimy; y++) { @@ -329,9 +337,10 @@ void RMSnapshot::GrabScreenshot(byte *lpBuf, int dezoom, uint16 *lpDestBuf) { rgb[k + 2] = (byte) (sommar * 8 / (dezoom * dezoom)); if (lpDestBuf!=NULL) - lpDestBuf[k/3] = ((int)rgb[k+0]>>3) | (((int)rgb[k+1]>>3)<<5) | (((int)rgb[k+2]>>3)<<10); + lpDestBuf[k / 3] = ((int)rgb[k + 0] >> 3) | (((int)rgb[k + 1] >> 3) << 5) | + (((int)rgb[k + 2] >> 3) << 10); - k+=3; + k += 3; } if (lpDestBuf == NULL) @@ -340,48 +349,6 @@ void RMSnapshot::GrabScreenshot(byte *lpBuf, int dezoom, uint16 *lpDestBuf) { src += RM_BBX * dezoom; } } - - - if (lpDestBuf == NULL) { - if (!GetFreeSnapName(filename)) - return; - - HANDLE hFile = CreateFile(filename, - GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, - NULL); - - BITMAPFILEHEADER bmfHeader; - bmfHeader.bfType = ((uint16) ('M' << 8) | 'B'); - bmfHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dimx * dimy * 3; - bmfHeader.bfReserved1 = 0; - bmfHeader.bfReserved2 = 0; - bmfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); - - BITMAPINFOHEADER bmiHeader; - bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmiHeader.biWidth = dimx; - bmiHeader.biHeight = dimy; - bmiHeader.biPlanes = 1; - bmiHeader.biBitCount = 24; - bmiHeader.biCompression = BI_RGB; - bmiHeader.biSizeImage = dimx * dimy * 3; - bmiHeader.biXPelsPerMeter = 0xB12; - bmiHeader.biYPelsPerMeter = 0xB12; - bmiHeader.biClrUsed = 0; - bmiHeader.biClrImportant = 0; - - uint32 dwWritten; - WriteFile(hFile, &bmfHeader, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); - WriteFile(hFile, &bmiHeader, sizeof(BITMAPINFOHEADER), &dwWritten, NULL); - - WriteFile(hFile, rgb, dimx * dimy * 3, &dwWritten, NULL); - CloseHandle(hFile); - } -#endif } } // End of namespace Tony |