Implemented savegame loading/saving and sprite clipping
Fixed bug in Screen::printTextEx Implemented opcodes: - o1_DRAWTEXT - o1_DRAWMENU - o1_MENUCOUNT - o1_SAVEGAME - o1_LOADGAME - o1_GAMENAME svn-id: r31794
This commit is contained in:
parent
e866aefdfd
commit
7509d66caf
4 changed files with 190 additions and 39 deletions
|
@ -23,8 +23,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/util.h"
|
||||
#include "common/savefile.h"
|
||||
|
||||
#include "made/database.h"
|
||||
|
||||
|
@ -222,8 +224,7 @@ void GameDatabase::load(Common::SeekableReadStream &sourceS) {
|
|||
uint32 objectsSize = sourceS.readUint32LE();
|
||||
_mainCodeObjectIndex = sourceS.readUint16LE();
|
||||
|
||||
debug(2, "objectIndexOffs = %08X; objectCount = %d; gameStateOffs = %08X; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n",
|
||||
objectIndexOffs, objectCount, gameStateOffs, _gameStateSize, objectsOffs, objectsSize);
|
||||
//debug(2, "objectIndexOffs = %08X; objectCount = %d; gameStateOffs = %08X; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n", objectIndexOffs, objectCount, gameStateOffs, _gameStateSize, objectsOffs, objectsSize);
|
||||
|
||||
_gameState = new byte[_gameStateSize];
|
||||
sourceS.seek(gameStateOffs);
|
||||
|
@ -241,14 +242,14 @@ void GameDatabase::load(Common::SeekableReadStream &sourceS) {
|
|||
// Constant objects are loaded from disk, while variable objects exist
|
||||
// in the _gameState buffer.
|
||||
|
||||
debug(2, "obj(%04X) ofs = %08X\n", i, objectOffsets[i]);
|
||||
//debug(2, "obj(%04X) ofs = %08X\n", i, objectOffsets[i]);
|
||||
|
||||
if (objectOffsets[i] & 1) {
|
||||
debug(2, "-> const %08X\n", objectsOffs + objectOffsets[i] - 1);
|
||||
//debug(2, "-> const %08X\n", objectsOffs + objectOffsets[i] - 1);
|
||||
sourceS.seek(objectsOffs + objectOffsets[i] - 1);
|
||||
obj->load(sourceS);
|
||||
} else {
|
||||
debug(2, "-> var\n");
|
||||
//debug(2, "-> var\n");
|
||||
obj->load(_gameState + objectOffsets[i]);
|
||||
}
|
||||
_objects.push_back(obj);
|
||||
|
@ -256,6 +257,79 @@ void GameDatabase::load(Common::SeekableReadStream &sourceS) {
|
|||
|
||||
}
|
||||
|
||||
bool GameDatabase::getSavegameDescription(const char *filename, Common::String &description) {
|
||||
|
||||
Common::InSaveFile *in;
|
||||
|
||||
if (!(in = g_system->getSavefileManager()->openForLoading(filename))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char desc[64];
|
||||
|
||||
in->skip(4); // TODO: Verify marker 'SGAM'
|
||||
in->skip(4); // TODO: Verify size
|
||||
in->skip(2); // TODO: Verify version
|
||||
in->read(desc, 64);
|
||||
description = desc;
|
||||
|
||||
printf("description = %s\n", description.c_str()); fflush(stdout);
|
||||
|
||||
delete in;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
int16 GameDatabase::savegame(const char *filename, const char *description, int16 version) {
|
||||
|
||||
Common::OutSaveFile *out;
|
||||
|
||||
if (!(out = g_system->getSavefileManager()->openForSaving(filename))) {
|
||||
warning("Can't create file '%s', game not saved", filename);
|
||||
return 6;
|
||||
}
|
||||
|
||||
uint32 size = 4 + 4 + 2 + _gameStateSize;
|
||||
char desc[64];
|
||||
|
||||
strncpy(desc, description, 64);
|
||||
|
||||
out->writeUint32BE(MKID_BE('SGAM'));
|
||||
out->writeUint32LE(size);
|
||||
out->writeUint16LE(version);
|
||||
out->write(desc, 64);
|
||||
out->write(_gameState, _gameStateSize);
|
||||
|
||||
delete out;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int16 GameDatabase::loadgame(const char *filename, int16 version) {
|
||||
|
||||
Common::InSaveFile *in;
|
||||
|
||||
if (!(in = g_system->getSavefileManager()->openForLoading(filename))) {
|
||||
warning("Can't open file '%s', game not loaded", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//uint32 expectedSize = 4 + 4 + 2 + _gameStateSize;
|
||||
|
||||
in->skip(4); // TODO: Verify marker 'SGAM'
|
||||
in->skip(4); // TODO: Verify size
|
||||
in->skip(2); // TODO: Verify version
|
||||
in->skip(64); // skip savegame description
|
||||
in->read(_gameState, _gameStateSize);
|
||||
|
||||
delete in;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int16 GameDatabase::getVar(int16 index) {
|
||||
return (int16)READ_LE_UINT16(_gameState + index * 2);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "common/util.h"
|
||||
#include "common/file.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/str.h"
|
||||
|
||||
#include "made/redreader.h"
|
||||
|
||||
|
@ -78,6 +79,10 @@ public:
|
|||
void open(const char *filename);
|
||||
void openFromRed(const char *redFilename, const char *filename);
|
||||
|
||||
bool getSavegameDescription(const char *filename, Common::String &description);
|
||||
int16 savegame(const char *filename, const char *description, int16 version);
|
||||
int16 loadgame(const char *filename, int16 version);
|
||||
|
||||
Object *getObject(int16 index) const {
|
||||
if (index >= 1)
|
||||
return _objects[index - 1];
|
||||
|
|
|
@ -92,23 +92,41 @@ void Screen::clearScreen() {
|
|||
_screen1->fillRect(Common::Rect(0, 0, 320, 200), 0);
|
||||
_screen2->fillRect(Common::Rect(0, 0, 320, 200), 0);
|
||||
_needPalette = true;
|
||||
//_vm->_system->clearScreen();
|
||||
}
|
||||
|
||||
void Screen::drawSurface(Graphics::Surface *sourceSurface, int x, int y, const ClipInfo &clipInfo) {
|
||||
|
||||
byte *source = (byte*)sourceSurface->getBasePtr(0, 0);
|
||||
byte *dest = (byte*)clipInfo.destSurface->getBasePtr(x, y);
|
||||
byte *source, *dest;
|
||||
int startX = 0;
|
||||
int startY = 0;
|
||||
int clipWidth = sourceSurface->w;
|
||||
int clipHeight = sourceSurface->h;
|
||||
|
||||
// FIXME: Implement actual clipping
|
||||
if (x + sourceSurface->w > clipInfo.destSurface->w || y + sourceSurface->h > clipInfo.destSurface->h) {
|
||||
debug(2, "CLIPPING PROBLEM: x = %d; y = %d; w = %d; h = %d; x+w = %d; y+h = %d\n",
|
||||
x, y, sourceSurface->w, sourceSurface->h, x + sourceSurface->w, y + sourceSurface->h);
|
||||
return;
|
||||
if (x < 0) {
|
||||
startX = -x;
|
||||
clipWidth -= startX;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
for (int16 yc = 0; yc < sourceSurface->h; yc++) {
|
||||
for (int16 xc = 0; xc < sourceSurface->w; xc++) {
|
||||
if (y < 0) {
|
||||
startY = -y;
|
||||
clipHeight -= startY;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if (x + clipWidth > clipInfo.x + clipInfo.w) {
|
||||
clipWidth = clipInfo.x + clipInfo.w - x;
|
||||
}
|
||||
|
||||
if (y + clipHeight > clipInfo.y + clipInfo.h) {
|
||||
clipHeight = clipInfo.y + clipInfo.h - y;
|
||||
}
|
||||
|
||||
source = (byte*)sourceSurface->getBasePtr(startX, startY);
|
||||
dest = (byte*)clipInfo.destSurface->getBasePtr(x, y);
|
||||
|
||||
for (int16 yc = 0; yc < clipHeight; yc++) {
|
||||
for (int16 xc = 0; xc < clipWidth; xc++) {
|
||||
if (source[xc])
|
||||
dest[xc] = source[xc];
|
||||
}
|
||||
|
@ -133,7 +151,7 @@ void Screen::setRGBPalette(byte *palRGB, int start, int count) {
|
|||
}
|
||||
|
||||
uint16 Screen::updateChannel(uint16 channelIndex) {
|
||||
return 0;
|
||||
return channelIndex;
|
||||
}
|
||||
|
||||
void Screen::deleteChannel(uint16 channelIndex) {
|
||||
|
@ -303,10 +321,6 @@ void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, u
|
|||
}
|
||||
|
||||
uint16 Screen::drawPic(uint16 index, int16 x, int16 y, uint16 flag1, uint16 flag2) {
|
||||
|
||||
//HACK (until clipping is implemented)
|
||||
if (y > 200) y = 0;
|
||||
|
||||
drawFlex(index, x, y, flag1, flag2, _clipInfo1);
|
||||
return 0;
|
||||
}
|
||||
|
@ -624,7 +638,6 @@ void Screen::printText(const char *text) {
|
|||
linePos = 1;
|
||||
x = _textRect.left;
|
||||
} else if (c == 32) {
|
||||
// TODO: Word-wrap
|
||||
int wrapPos = textPos + 1;
|
||||
int wrapX = x + charWidth;
|
||||
while (wrapPos < textLen && text[wrapPos] != 0 && text[wrapPos] != 32 && text[wrapPos] >= 28) {
|
||||
|
@ -682,6 +695,7 @@ void Screen::printTextEx(const char *text, int16 x, int16 y, int16 fontNum, int1
|
|||
|
||||
int16 oldFontNum = _currentFontNum;
|
||||
Common::Rect oldTextRect;
|
||||
ClipInfo oldFontDrawCtx = _fontDrawCtx;
|
||||
|
||||
_fontDrawCtx = clipInfo;
|
||||
|
||||
|
@ -693,6 +707,7 @@ void Screen::printTextEx(const char *text, int16 x, int16 y, int16 fontNum, int1
|
|||
printText(text);
|
||||
setTextRect(oldTextRect);
|
||||
setFont(oldFontNum);
|
||||
_fontDrawCtx = oldFontDrawCtx;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -408,9 +408,9 @@ int16 ScriptFunctionsRtz::o1_FONT(int16 argc, int16 *argv) {
|
|||
}
|
||||
|
||||
int16 ScriptFunctionsRtz::o1_DRAWTEXT(int16 argc, int16 *argv) {
|
||||
warning("Unimplemented opcode: o1_DRAWTEXT");
|
||||
Object *obj = _vm->_dat->getObject(argv[argc - 1]);
|
||||
warning("argc = %d; drawText = %s", argc, obj->getString());
|
||||
const char *text = obj->getString();
|
||||
_vm->_screen->printText(text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -420,7 +420,6 @@ int16 ScriptFunctionsRtz::o1_HOMETEXT(int16 argc, int16 *argv) {
|
|||
}
|
||||
|
||||
int16 ScriptFunctionsRtz::o1_TEXTRECT(int16 argc, int16 *argv) {
|
||||
warning("Unimplemented opcode: o1_TEXTRECT");
|
||||
int16 x1 = CLIP<int16>(argv[4], 1, 318);
|
||||
int16 y1 = CLIP<int16>(argv[3], 1, 198);
|
||||
int16 x2 = CLIP<int16>(argv[2], 1, 318);
|
||||
|
@ -536,7 +535,9 @@ int16 ScriptFunctionsRtz::o1_CDPLAYSEG(int16 argc, int16 *argv) {
|
|||
}
|
||||
|
||||
int16 ScriptFunctionsRtz::o1_PRINTF(int16 argc, int16 *argv) {
|
||||
warning("Unimplemented opcode: o1_PRINTF");
|
||||
Object *obj = _vm->_dat->getObject(argv[argc - 1]);
|
||||
const char *text = obj->getString();
|
||||
debug(4, "--> text = %s", text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -556,7 +557,7 @@ int16 ScriptFunctionsRtz::o1_SNDENERGY(int16 argc, int16 *argv) {
|
|||
|
||||
int16 ScriptFunctionsRtz::o1_CLEARTEXT(int16 argc, int16 *argv) {
|
||||
warning("Unimplemented opcode: o1_CLEARTEXT");
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int16 ScriptFunctionsRtz::o1_ANIMTEXT(int16 argc, int16 *argv) {
|
||||
|
@ -746,33 +747,89 @@ int16 ScriptFunctionsRtz::o1_READMENU(int16 argc, int16 *argv) {
|
|||
}
|
||||
|
||||
int16 ScriptFunctionsRtz::o1_DRAWMENU(int16 argc, int16 *argv) {
|
||||
warning("Unimplemented opcode: o1_DRAWMENU");
|
||||
int16 menuIndex = argv[1];
|
||||
int16 textIndex = argv[0];
|
||||
MenuResource *menu = _vm->_res->getMenu(menuIndex);
|
||||
if (menu) {
|
||||
const char *text = menu->getString(textIndex);
|
||||
if (text)
|
||||
_vm->_screen->printText(text);
|
||||
_vm->_res->freeResource(menu);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16 ScriptFunctionsRtz::o1_MENUCOUNT(int16 argc, int16 *argv) {
|
||||
warning("Unimplemented opcode: o1_MENUCOUNT");
|
||||
return 0;
|
||||
int16 menuIndex = argv[0];
|
||||
int16 count = 0;
|
||||
MenuResource *menu = _vm->_res->getMenu(menuIndex);
|
||||
if (menu) {
|
||||
count = menu->getCount();
|
||||
_vm->_res->freeResource(menu);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int16 ScriptFunctionsRtz::o1_SAVEGAME(int16 argc, int16 *argv) {
|
||||
warning("Unimplemented opcode: o1_SAVEGAME");
|
||||
return 0;
|
||||
|
||||
int16 saveNum = argv[2];
|
||||
int16 descObjectIndex = argv[1];
|
||||
int16 version = argv[0];
|
||||
|
||||
if (saveNum > 999)
|
||||
return 6;
|
||||
|
||||
Object *obj = _vm->_dat->getObject(descObjectIndex);
|
||||
const char *description = obj->getString();
|
||||
|
||||
// TODO: Use better filename
|
||||
char filename[256];
|
||||
snprintf(filename, 256, "rtz.%03d", saveNum);
|
||||
|
||||
return _vm->_dat->savegame(filename, description, version);
|
||||
|
||||
}
|
||||
|
||||
int16 ScriptFunctionsRtz::o1_LOADGAME(int16 argc, int16 *argv) {
|
||||
warning("Unimplemented opcode: o1_LOADGAME");
|
||||
return 0;
|
||||
|
||||
int16 saveNum = argv[1];
|
||||
int16 version = argv[0];
|
||||
|
||||
if (saveNum > 999)
|
||||
return 1;
|
||||
|
||||
// TODO: Use better filename
|
||||
char filename[256];
|
||||
snprintf(filename, 256, "rtz.%03d", saveNum);
|
||||
|
||||
return _vm->_dat->loadgame(filename, version);
|
||||
|
||||
}
|
||||
|
||||
int16 ScriptFunctionsRtz::o1_GAMENAME(int16 argc, int16 *argv) {
|
||||
warning("Unimplemented opcode: o1_GAMENAME");
|
||||
|
||||
warning("GAMENAME: 1) %d\n", argv[2]);
|
||||
warning("GAMENAME: 2) %d\n", argv[1]);
|
||||
warning("GAMENAME: 3) %d\n", argv[0]);
|
||||
int16 descObjectIndex = argv[2];
|
||||
int16 saveNum = argv[1];
|
||||
int16 version = argv[0];
|
||||
Common::String description;
|
||||
|
||||
if (saveNum > 999)
|
||||
return 1;
|
||||
|
||||
// TODO: Use better filename
|
||||
char filename[256];
|
||||
snprintf(filename, 256, "rtz.%03d", saveNum);
|
||||
|
||||
Object *obj = _vm->_dat->getObject(descObjectIndex);
|
||||
|
||||
if (_vm->_dat->getSavegameDescription(filename, description)) {
|
||||
obj->setString(description.c_str());
|
||||
return 0;
|
||||
} else {
|
||||
obj->setString("");
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int16 ScriptFunctionsRtz::o1_SHAKESCREEN(int16 argc, int16 *argv) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue