Skip to content

Commit

Permalink
TONY: Properly implement game saving and loading.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dreammaster committed May 12, 2012
1 parent 109e5f8 commit 073e465
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 148 deletions.
62 changes: 36 additions & 26 deletions engines/tony/game.cpp
Expand Up @@ -371,6 +371,7 @@ RMOptionScreen::RMOptionScreen(void) {
m_menu = NULL;
m_HideLoadSave = NULL;
m_QuitConfirm = NULL;
m_bQuitConfirm = false;

Create(RM_SX, RM_SY);

Expand Down Expand Up @@ -1401,71 +1402,80 @@ 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
Common::fill(lpDestBuf, lpDestBuf + 160 * 120 * 2, 0);
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;
}

Expand Down
95 changes: 45 additions & 50 deletions engines/tony/gfxengine.cpp
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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();
Expand All @@ -845,64 +834,70 @@ 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;
}

_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];
_ctx->f->read(_ctx->statecmp, _ctx->sizecmp);
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);
}

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);
Expand Down Expand Up @@ -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();
Expand All @@ -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);
}

Expand All @@ -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();
}

Expand Down
10 changes: 10 additions & 0 deletions engines/tony/input.cpp
Expand Up @@ -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
2 changes: 1 addition & 1 deletion engines/tony/input.h
Expand Up @@ -98,7 +98,7 @@ class RMInput {
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
Expand Down

0 comments on commit 073e465

Please sign in to comment.