aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2012-05-12 21:54:37 +1000
committerPaul Gilbert2012-05-12 21:54:37 +1000
commit073e46503cd09130c3d7e2372ae50e47402569d2 (patch)
tree22ec65b1c51c3b02bb8368082c1655c8fe155f17
parent109e5f8226c1db18926e307d4ecb9c3c83fdd7bc (diff)
downloadscummvm-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.cpp62
-rw-r--r--engines/tony/gfxengine.cpp95
-rw-r--r--engines/tony/input.cpp10
-rw-r--r--engines/tony/input.h2
-rw-r--r--engines/tony/tony.cpp32
-rw-r--r--engines/tony/tony.h2
-rw-r--r--engines/tony/window.cpp65
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