aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sword2/anims.cpp98
-rw-r--r--sword2/build_display.cpp209
-rw-r--r--sword2/build_display.h43
-rw-r--r--sword2/console.cpp79
-rw-r--r--sword2/console.h6
-rw-r--r--sword2/controls.cpp50
-rw-r--r--sword2/debug.cpp48
-rw-r--r--sword2/driver/_mouse.cpp107
-rw-r--r--sword2/driver/animation.cpp30
-rw-r--r--sword2/driver/d_sound.cpp8
-rw-r--r--sword2/driver/palette.cpp17
-rw-r--r--sword2/driver/render.cpp48
-rw-r--r--sword2/events.cpp6
-rw-r--r--sword2/function.cpp697
-rw-r--r--sword2/header.h299
-rw-r--r--sword2/icons.cpp41
-rw-r--r--sword2/icons.h10
-rw-r--r--sword2/interpreter.cpp172
-rw-r--r--sword2/interpreter.h8
-rw-r--r--sword2/layers.cpp44
-rw-r--r--sword2/logic.cpp86
-rw-r--r--sword2/logic.h24
-rw-r--r--sword2/maketext.cpp94
-rw-r--r--sword2/maketext.h4
-rw-r--r--sword2/mouse.cpp232
-rw-r--r--sword2/mouse.h26
-rw-r--r--sword2/object.h300
-rw-r--r--sword2/protocol.cpp133
-rw-r--r--sword2/resman.cpp213
-rw-r--r--sword2/resman.h23
-rw-r--r--sword2/router.cpp172
-rw-r--r--sword2/router.h64
-rw-r--r--sword2/save_rest.cpp308
-rw-r--r--sword2/scroll.cpp8
-rw-r--r--sword2/sound.cpp11
-rw-r--r--sword2/speech.cpp37
-rw-r--r--sword2/startup.cpp18
-rw-r--r--sword2/sword2.cpp26
-rw-r--r--sword2/sword2.h49
-rw-r--r--sword2/sync.cpp4
-rw-r--r--sword2/walker.cpp184
41 files changed, 2125 insertions, 1911 deletions
diff --git a/sword2/anims.cpp b/sword2/anims.cpp
index eab9e654ec..e48d3c36e8 100644
--- a/sword2/anims.cpp
+++ b/sword2/anims.cpp
@@ -40,12 +40,15 @@
namespace Sword2 {
-int Router::doAnimate(ObjectLogic *ob_logic, ObjectGraphic *ob_graphic, int32 animRes, bool reverse) {
+int Router::doAnimate(byte *ob_logic, byte *ob_graph, int32 animRes, bool reverse) {
+ AnimHeader anim_head;
byte *anim_file;
- AnimHeader *anim_head;
- if (ob_logic->looping == 0) {
- StandardHeader *head;
+ ObjectLogic obLogic(ob_logic);
+ ObjectGraphic obGraph(ob_graph);
+
+ if (obLogic.getLooping() == 0) {
+ byte *ptr;
// This is the start of the anim - set up the first frame
@@ -55,32 +58,32 @@ int Router::doAnimate(ObjectLogic *ob_logic, ObjectGraphic *ob_graphic, int32 an
// 'testing_routines' object in George's Player Character
// section of linc
- if (Logic::_scriptVars[SYSTEM_TESTING_ANIMS]) {
+ if (_vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) {
if (!_vm->_resman->checkValid(animRes)) {
// Not a valid resource number. Switch off
// the sprite. Don't animate - just continue
// script next cycle.
- setSpriteStatus(ob_graphic, NO_SPRITE);
+ setSpriteStatus(ob_graph, NO_SPRITE);
return IR_STOP;
}
- head = (StandardHeader *)_vm->_resman->openResource(animRes);
+ ptr = _vm->_resman->openResource(animRes);
// if it's not an animation file
- if (head->fileType != ANIMATION_FILE) {
+ if (_vm->_resman->fetchType(animRes) != ANIMATION_FILE) {
_vm->_resman->closeResource(animRes);
// switch off the sprite
// don't animate - just continue
// script next cycle
- setSpriteStatus(ob_graphic, NO_SPRITE);
+ setSpriteStatus(ob_graph, NO_SPRITE);
return IR_STOP;
}
_vm->_resman->closeResource(animRes);
// switch on the sprite
- setSpriteStatus(ob_graphic, SORT_SPRITE);
+ setSpriteStatus(ob_graph, SORT_SPRITE);
}
assert(animRes);
@@ -88,88 +91,94 @@ int Router::doAnimate(ObjectLogic *ob_logic, ObjectGraphic *ob_graphic, int32 an
// open anim file
anim_file = _vm->_resman->openResource(animRes);
- head = (StandardHeader *)anim_file;
- assert(head->fileType == ANIMATION_FILE);
+ assert(_vm->_resman->fetchType(animRes) == ANIMATION_FILE);
// point to anim header
- anim_head = _vm->fetchAnimHeader(anim_file);
+ anim_head.read(_vm->fetchAnimHeader(anim_file));
// now running an anim, looping back to this call again
- ob_logic->looping = 1;
- ob_graphic->anim_resource = animRes;
+ obLogic.setLooping(1);
+ obGraph.setAnimResource(animRes);
if (reverse)
- ob_graphic->anim_pc = anim_head->noAnimFrames - 1;
+ obGraph.setAnimPc(anim_head.noAnimFrames - 1);
else
- ob_graphic->anim_pc = 0;
+ obGraph.setAnimPc(0);
} else if (_vm->_logic->getSync() != -1) {
// We've received a sync - return to script immediately
- debug(5, "**sync stopped %d**", Logic::_scriptVars[ID]);
+ debug(5, "**sync stopped %d**", _vm->_logic->readVar(ID));
// If sync received, anim finishes right now (remaining on
// last frame). Quit animation, but continue script.
- ob_logic->looping = 0;
+ obLogic.setLooping(0);
return IR_CONT;
} else {
// Not first frame, and no sync received - set up the next
// frame of the anim.
// open anim file and point to anim header
- anim_file = _vm->_resman->openResource(ob_graphic->anim_resource);
- anim_head = _vm->fetchAnimHeader(anim_file);
+ anim_file = _vm->_resman->openResource(obGraph.getAnimResource());
+ anim_head.read(_vm->fetchAnimHeader(anim_file));
if (reverse)
- ob_graphic->anim_pc--;
+ obGraph.setAnimPc(obGraph.getAnimPc() - 1);
else
- ob_graphic->anim_pc++;
+ obGraph.setAnimPc(obGraph.getAnimPc() + 1);
}
// check for end of anim
if (reverse) {
- if (ob_graphic->anim_pc == 0)
- ob_logic->looping = 0;
+ if (obGraph.getAnimPc() == 0)
+ obLogic.setLooping(0);
} else {
- if (ob_graphic->anim_pc == anim_head->noAnimFrames - 1)
- ob_logic->looping = 0;
+ if (obGraph.getAnimPc() == anim_head.noAnimFrames - 1)
+ obLogic.setLooping(0);
}
// close the anim file
- _vm->_resman->closeResource(ob_graphic->anim_resource);
+ _vm->_resman->closeResource(obGraph.getAnimResource());
// check if we want the script to loop back & call this function again
- return ob_logic->looping ? IR_REPEAT : IR_STOP;
+ return obLogic.getLooping() ? IR_REPEAT : IR_STOP;
}
-int Router::megaTableAnimate(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, uint32 *animTable, bool reverse) {
+int Router::megaTableAnimate(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *animTable, bool reverse) {
int32 animRes = 0;
// If this is the start of the anim, read the anim table to get the
// appropriate anim resource
- if (ob_logic->looping == 0) {
+ ObjectLogic obLogic(ob_logic);
+
+ if (obLogic.getLooping() == 0) {
+ ObjectMega obMega(ob_mega);
+
// Appropriate anim resource is in 'table[direction]'
- animRes = animTable[ob_mega->current_dir];
+ animRes = READ_LE_UINT32(animTable + 4 * obMega.getCurDir());
}
return doAnimate(ob_logic, ob_graph, animRes, reverse);
}
-void Router::setSpriteStatus(ObjectGraphic *ob_graph, uint32 type) {
+void Router::setSpriteStatus(byte *ob_graph, uint32 type) {
+ ObjectGraphic obGraph(ob_graph);
+
// Remove the previous status, but don't affect the shading upper-word
- ob_graph->type = (ob_graph->type & 0xffff0000) | type;
+ obGraph.setType((obGraph.getType() & 0xffff0000) | type);
}
-void Router::setSpriteShading(ObjectGraphic *ob_graph, uint32 type) {
+void Router::setSpriteShading(byte *ob_graph, uint32 type) {
+ ObjectGraphic obGraph(ob_graph);
+
// Remove the previous shading, but don't affect the status lower-word.
// Note that mega frames may still be shaded automatically, even when
// not sent 'RDSPR_SHADOW'.
- ob_graph->type = (ob_graph->type & 0x0000ffff) | type;
+ obGraph.setType((obGraph.getType() & 0x0000ffff) | type);
}
void Logic::createSequenceSpeech(MovieTextObject *sequenceText[]) {
uint32 line;
- FrameHeader *frame;
uint32 local_text;
uint32 text_res;
byte *text;
@@ -192,7 +201,7 @@ void Logic::createSequenceSpeech(MovieTextObject *sequenceText[]) {
// open text resource & get the line
text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text);
- wavId = (int32) READ_LE_UINT16(text);
+ wavId = (int32)READ_LE_UINT16(text);
// now ok to close the text file
_vm->_resman->closeResource(text_res);
@@ -250,18 +259,19 @@ void Logic::createSequenceSpeech(MovieTextObject *sequenceText[]) {
if (_sequenceTextList[line].text_mem) {
// now fill out the SpriteInfo structure in the
// MovieTextObjectStructure
+ FrameHeader frame;
- frame = (FrameHeader *)_sequenceTextList[line].text_mem;
+ frame.read(_sequenceTextList[line].text_mem);
sequenceText[line]->textSprite = new SpriteInfo;
// center text at bottom of screen
- sequenceText[line]->textSprite->x = 320 - frame->width / 2;
- sequenceText[line]->textSprite->y = 440 - frame->height;
- sequenceText[line]->textSprite->w = frame->width;
- sequenceText[line]->textSprite->h = frame->height;
+ sequenceText[line]->textSprite->x = 320 - frame.width / 2;
+ sequenceText[line]->textSprite->y = 440 - frame.height;
+ sequenceText[line]->textSprite->w = frame.width;
+ sequenceText[line]->textSprite->h = frame.height;
sequenceText[line]->textSprite->type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION;
- sequenceText[line]->textSprite->data = _sequenceTextList[line].text_mem + sizeof(FrameHeader);
+ sequenceText[line]->textSprite->data = _sequenceTextList[line].text_mem + FrameHeader::size();
}
// if we've loaded a speech sample for this line...
diff --git a/sword2/build_display.cpp b/sword2/build_display.cpp
index 9a81780e67..d483355df6 100644
--- a/sword2/build_display.cpp
+++ b/sword2/build_display.cpp
@@ -116,7 +116,10 @@ void Screen::buildDisplay() {
startRenderCycle();
byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id);
- MultiScreenHeader *screenLayerTable = (MultiScreenHeader *)(file + sizeof(StandardHeader));
+
+ MultiScreenHeader screenLayerTable;
+
+ screenLayerTable.read(file + ResHeader::size());
// Render at least one frame, but if the screen is scrolling, and if
// there is time left, we will render extra frames to smooth out the
@@ -124,13 +127,13 @@ void Screen::buildDisplay() {
do {
// first background parallax + related anims
- if (screenLayerTable->bg_parallax[0]) {
+ if (screenLayerTable.bg_parallax[0]) {
renderParallax(_vm->fetchBackgroundParallaxLayer(file, 0), 0);
drawBackPar0Frames();
}
// second background parallax + related anims
- if (screenLayerTable->bg_parallax[1]) {
+ if (screenLayerTable.bg_parallax[1]) {
renderParallax(_vm->fetchBackgroundParallaxLayer(file, 1), 1);
drawBackPar1Frames();
}
@@ -145,14 +148,14 @@ void Screen::buildDisplay() {
// first foreground parallax + related anims
- if (screenLayerTable->fg_parallax[0]) {
+ if (screenLayerTable.fg_parallax[0]) {
renderParallax(_vm->fetchForegroundParallaxLayer(file, 0), 3);
drawForePar0Frames();
}
// second foreground parallax + related anims
- if (screenLayerTable->fg_parallax[1]) {
+ if (screenLayerTable.fg_parallax[1]) {
renderParallax(_vm->fetchForegroundParallaxLayer(file, 1), 4);
drawForePar1Frames();
}
@@ -199,23 +202,26 @@ void Screen::displayMsg(byte *text, int time) {
clearScene();
byte *text_spr = _vm->_fontRenderer->makeTextSprite(text, 640, 187, _vm->_speechFontId);
- FrameHeader *frame = (FrameHeader *)text_spr;
+
+ FrameHeader frame;
+
+ frame.read(text_spr);
SpriteInfo spriteInfo;
- spriteInfo.x = _screenWide / 2 - frame->width / 2;
+ spriteInfo.x = _screenWide / 2 - frame.width / 2;
if (!time)
- spriteInfo.y = _screenDeep / 2 - frame->height / 2 - MENUDEEP;
+ spriteInfo.y = _screenDeep / 2 - frame.height / 2 - MENUDEEP;
else
- spriteInfo.y = 400 - frame->height;
- spriteInfo.w = frame->width;
- spriteInfo.h = frame->height;
+ spriteInfo.y = 400 - frame.height;
+ spriteInfo.w = frame.width;
+ spriteInfo.h = frame.height;
spriteInfo.scale = 0;
spriteInfo.scaledWidth = 0;
spriteInfo.scaledHeight = 0;
spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS;
spriteInfo.blend = 0;
- spriteInfo.data = text_spr + sizeof(FrameHeader);
+ spriteInfo.data = text_spr + FrameHeader::size();
spriteInfo.colourTable = 0;
uint32 rv = drawSprite(&spriteInfo);
@@ -326,25 +332,27 @@ void Screen::drawForePar1Frames() {
}
void Screen::processLayer(byte *file, uint32 layer_number) {
- LayerHeader *layer_head = _vm->fetchLayerHeader(file, layer_number);
+ LayerHeader layer_head;
+
+ layer_head.read(_vm->fetchLayerHeader(file, layer_number));
SpriteInfo spriteInfo;
- spriteInfo.x = layer_head->x;
- spriteInfo.y = layer_head->y;
- spriteInfo.w = layer_head->width;
+ spriteInfo.x = layer_head.x;
+ spriteInfo.y = layer_head.y;
+ spriteInfo.w = layer_head.width;
spriteInfo.scale = 0;
spriteInfo.scaledWidth = 0;
spriteInfo.scaledHeight = 0;
- spriteInfo.h = layer_head->height;
+ spriteInfo.h = layer_head.height;
spriteInfo.type = RDSPR_TRANS | RDSPR_RLE256FAST;
spriteInfo.blend = 0;
- spriteInfo.data = file + sizeof(StandardHeader) + layer_head->offset;
+ spriteInfo.data = file + ResHeader::size() + layer_head.offset;
spriteInfo.colourTable = 0;
// check for largest layer for debug info
- uint32 current_layer_area = layer_head->width * layer_head->height;
+ uint32 current_layer_area = layer_head.width * layer_head.height;
if (current_layer_area > _largestLayerArea) {
byte buf[NAME_LEN];
@@ -352,8 +360,8 @@ void Screen::processLayer(byte *file, uint32 layer_number) {
_largestLayerArea = current_layer_area;
sprintf(_largestLayerInfo,
"largest layer: %s layer(%d) is %dx%d",
- _vm->fetchObjectName(_thisScreen.background_layer_id, buf),
- layer_number, layer_head->width, layer_head->height);
+ _vm->_resman->fetchName(_thisScreen.background_layer_id, buf),
+ layer_number, layer_head.width, layer_head.height);
}
uint32 rv = drawSprite(&spriteInfo);
@@ -365,22 +373,28 @@ void Screen::processImage(BuildUnit *build_unit) {
byte *file = _vm->_resman->openResource(build_unit->anim_resource);
byte *colTablePtr = NULL;
- AnimHeader *anim_head = _vm->fetchAnimHeader(file);
- CdtEntry *cdt_entry = _vm->fetchCdtEntry(file, build_unit->anim_pc);
- FrameHeader *frame_head = _vm->fetchFrameHeader(file, build_unit->anim_pc);
+ byte *frame = _vm->fetchFrameHeader(file, build_unit->anim_pc);
+
+ AnimHeader anim_head;
+ CdtEntry cdt_entry;
+ FrameHeader frame_head;
+
+ anim_head.read(_vm->fetchAnimHeader(file));
+ cdt_entry.read(_vm->fetchCdtEntry(file, build_unit->anim_pc));
+ frame_head.read(frame);
// so that 0-colour is transparent
uint32 spriteType = RDSPR_TRANS;
- if (anim_head->blend)
+ if (anim_head.blend)
spriteType |= RDSPR_BLEND;
// if the frame is to be flipped (only really applicable to frames
// using offsets)
- if (cdt_entry->frameType & FRAME_FLIPPED)
+ if (cdt_entry.frameType & FRAME_FLIPPED)
spriteType |= RDSPR_FLIP;
- if (cdt_entry->frameType & FRAME_256_FAST) {
+ if (cdt_entry.frameType & FRAME_256_FAST) {
// scaling, shading & blending don't work with RLE256FAST
// but the same compression can be decompressed using the
// RLE256 routines!
@@ -388,12 +402,12 @@ void Screen::processImage(BuildUnit *build_unit) {
// NOTE: If this restriction refers to drawSprite(), I don't
// think we have it any more. But I'm not sure.
- if (build_unit->scale || anim_head->blend || build_unit->shadingFlag)
+ if (build_unit->scale || anim_head.blend || build_unit->shadingFlag)
spriteType |= RDSPR_RLE256;
else
spriteType |= RDSPR_RLE256FAST;
} else {
- switch (anim_head->runTimeComp) {
+ switch (anim_head.runTimeComp) {
case NONE:
spriteType |= RDSPR_NOCOMPRESSION;
break;
@@ -404,7 +418,7 @@ void Screen::processImage(BuildUnit *build_unit) {
spriteType |= RDSPR_RLE16;
// points to just after last cdt_entry, ie.
// start of colour table
- colTablePtr = (byte *)(anim_head + 1) + anim_head->noAnimFrames * sizeof(CdtEntry);
+ colTablePtr = _vm->fetchAnimHeader(file) + AnimHeader::size() + anim_head.noAnimFrames * CdtEntry::size();
break;
}
}
@@ -418,19 +432,19 @@ void Screen::processImage(BuildUnit *build_unit) {
spriteInfo.x = build_unit->x;
spriteInfo.y = build_unit->y;
- spriteInfo.w = frame_head->width;
- spriteInfo.h = frame_head->height;
+ spriteInfo.w = frame_head.width;
+ spriteInfo.h = frame_head.height;
spriteInfo.scale = build_unit->scale;
spriteInfo.scaledWidth = build_unit->scaled_width;
spriteInfo.scaledHeight = build_unit->scaled_height;
spriteInfo.type = spriteType;
- spriteInfo.blend = anim_head->blend;
+ spriteInfo.blend = anim_head.blend;
// points to just after frame header, ie. start of sprite data
- spriteInfo.data = (byte *)(frame_head + 1);
- spriteInfo.colourTable = colTablePtr;
+ spriteInfo.data = frame + FrameHeader::size();
+ spriteInfo.colourTable = colTablePtr;
// check for largest layer for debug info
- uint32 current_sprite_area = frame_head->width * frame_head->height;
+ uint32 current_sprite_area = frame_head.width * frame_head.height;
if (current_sprite_area > _largestSpriteArea) {
byte buf[NAME_LEN];
@@ -438,13 +452,13 @@ void Screen::processImage(BuildUnit *build_unit) {
_largestSpriteArea = current_sprite_area;
sprintf(_largestSpriteInfo,
"largest sprite: %s frame(%d) is %dx%d",
- _vm->fetchObjectName(build_unit->anim_resource, buf),
+ _vm->_resman->fetchName(build_unit->anim_resource, buf),
build_unit->anim_pc,
- frame_head->width,
- frame_head->height);
+ frame_head.width,
+ frame_head.height);
}
- if (Logic::_scriptVars[SYSTEM_TESTING_ANIMS]) { // see anims.cpp
+ if (_vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) { // see anims.cpp
// bring the anim into the visible screen
// but leave extra pixel at edge for box
if (spriteInfo.x + spriteInfo.scaledWidth >= 639)
@@ -472,7 +486,7 @@ void Screen::processImage(BuildUnit *build_unit) {
error("Driver Error %.8x with sprite %s (%d) in processImage",
rv,
- _vm->fetchObjectName(build_unit->anim_resource, buf),
+ _vm->_resman->fetchName(build_unit->anim_resource, buf),
build_unit->anim_resource);
}
@@ -501,32 +515,39 @@ void Screen::resetRenderLists() {
}
}
-void Screen::registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, ObjectMega *ob_mega, BuildUnit *build_unit) {
- assert(ob_graph->anim_resource);
+void Screen::registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega, BuildUnit *build_unit) {
+ ObjectGraphic obGraph(ob_graph);
+ ObjectMega obMega(ob_mega);
- byte *file = _vm->_resman->openResource(ob_graph->anim_resource);
+ assert(obGraph.getAnimResource());
- AnimHeader *anim_head = _vm->fetchAnimHeader(file);
- CdtEntry *cdt_entry = _vm->fetchCdtEntry(file, ob_graph->anim_pc);
- FrameHeader *frame_head = _vm->fetchFrameHeader(file, ob_graph->anim_pc);
+ byte *file = _vm->_resman->openResource(obGraph.getAnimResource());
+
+ AnimHeader anim_head;
+ CdtEntry cdt_entry;
+ FrameHeader frame_head;
+
+ anim_head.read(_vm->fetchAnimHeader(file));
+ cdt_entry.read(_vm->fetchCdtEntry(file, obGraph.getAnimPc()));
+ frame_head.read(_vm->fetchFrameHeader(file, obGraph.getAnimPc()));
// update player graphic details for on-screen debug info
- if (Logic::_scriptVars[ID] == CUR_PLAYER_ID) {
- _vm->_debugger->_playerGraphic.type = ob_graph->type;
- _vm->_debugger->_playerGraphic.anim_resource = ob_graph->anim_resource;
+ if (_vm->_logic->readVar(ID) == CUR_PLAYER_ID) {
+ _vm->_debugger->_graphType = obGraph.getType();
+ _vm->_debugger->_graphAnimRes = obGraph.getAnimResource();
// counting 1st frame as 'frame 1'
- _vm->_debugger->_playerGraphic.anim_pc = ob_graph->anim_pc + 1;
- _vm->_debugger->_playerGraphicNoFrames = anim_head->noAnimFrames;
+ _vm->_debugger->_graphAnimPc = obGraph.getAnimPc() + 1;
+ _vm->_debugger->_graphNoFrames = anim_head.noAnimFrames;
}
// fill in the BuildUnit structure for this frame
- build_unit->anim_resource = ob_graph->anim_resource;
- build_unit->anim_pc = ob_graph->anim_pc;
+ build_unit->anim_resource = obGraph.getAnimResource();
+ build_unit->anim_pc = obGraph.getAnimPc();
build_unit->layer_number = 0;
// Affected by shading mask?
- if (ob_graph->type & SHADED_SPRITE)
+ if (obGraph.getType() & SHADED_SPRITE)
build_unit->shadingFlag = true;
else
build_unit->shadingFlag = false;
@@ -535,34 +556,28 @@ void Screen::registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, Objec
int scale = 0;
- if (cdt_entry->frameType & FRAME_OFFSET) {
- // Calc scale at which to print the sprite, based on feet
- // y-coord & scaling constants (NB. 'scale' is actually
- // 256 * true_scale, to maintain accuracy)
-
- // Ay+B gives 256 * scale ie. 256 * 256 * true_scale for even
- // better accuracy, ie. scale = (Ay + B) / 256
- scale = (ob_mega->scale_a * ob_mega->feet_y + ob_mega->scale_b) / 256;
+ if (cdt_entry.frameType & FRAME_OFFSET) {
+ scale = obMega.calcScale();
// calc final render coordinates (top-left of sprite), based
// on feet coords & scaled offsets
// add scaled offsets to feet coords
- build_unit->x = ob_mega->feet_x + (cdt_entry->x * scale) / 256;
- build_unit->y = ob_mega->feet_y + (cdt_entry->y * scale) / 256;
+ build_unit->x = obMega.getFeetX() + (cdt_entry.x * scale) / 256;
+ build_unit->y = obMega.getFeetY() + (cdt_entry.y * scale) / 256;
// Work out new width and height. Always divide by 256 after
// everything else, to maintain accurary
- build_unit->scaled_width = ((scale * frame_head->width) / 256);
- build_unit->scaled_height = ((scale * frame_head->height) / 256);
+ build_unit->scaled_width = ((scale * frame_head.width) / 256);
+ build_unit->scaled_height = ((scale * frame_head.height) / 256);
} else {
// It's a non-scaling anim. Get render coords for sprite, from cdt
- build_unit->x = cdt_entry->x;
- build_unit->y = cdt_entry->y;
+ build_unit->x = cdt_entry.x;
+ build_unit->y = cdt_entry.y;
// Get width and height
- build_unit->scaled_width = frame_head->width;
- build_unit->scaled_height = frame_head->height;
+ build_unit->scaled_width = frame_head.width;
+ build_unit->scaled_height = frame_head.height;
}
// either 0 or required scale, depending on whether 'scale' computed
@@ -577,12 +592,14 @@ void Screen::registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, Objec
}
- _vm->_resman->closeResource(ob_graph->anim_resource);
+ _vm->_resman->closeResource(obGraph.getAnimResource());
}
-void Screen::registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, ObjectMega *ob_mega) {
+void Screen::registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega) {
+ ObjectGraphic obGraph(ob_graph);
+
// check low word for sprite type
- switch (ob_graph->type & 0x0000ffff) {
+ switch (obGraph.getType() & 0x0000ffff) {
case BGP0_SPRITE:
assert(_curBgp0 < MAX_bgp0_sprites);
registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp0List[_curBgp0]);
@@ -861,7 +878,7 @@ void Screen::rollCredits() {
// credits. Note that musicTimeRemaining() will return 0 if the music
// is muted, so we need a sensible fallback for that case.
- uint32 musicLength = MAX((int32) (1000 * (_vm->_sound->musicTimeRemaining() - 3)), 25 * (int32) scrollSteps);
+ uint32 musicLength = MAX((int32)(1000 * (_vm->_sound->musicTimeRemaining() - 3)), 25 * (int32)scrollSteps);
while (scrollPos < scrollSteps && !_vm->_quit) {
bool foundStartLine = false;
@@ -892,16 +909,18 @@ void Screen::rollCredits() {
creditsLines[i].sprite = _vm->_fontRenderer->makeTextSprite((byte *)creditsLines[i].str, 600, 14, _vm->_speechFontId, 0);
}
- FrameHeader *frame = (FrameHeader *)creditsLines[i].sprite;
+ FrameHeader frame;
+
+ frame.read(creditsLines[i].sprite);
spriteInfo.y = creditsLines[i].top - scrollPos;
- spriteInfo.w = frame->width;
- spriteInfo.h = frame->height;
- spriteInfo.data = creditsLines[i].sprite + sizeof(FrameHeader);
+ spriteInfo.w = frame.width;
+ spriteInfo.h = frame.height;
+ spriteInfo.data = creditsLines[i].sprite + FrameHeader::size();
switch (creditsLines[i].type) {
case LINE_LEFT:
- spriteInfo.x = RENDERWIDE / 2 - 5 - frame->width;
+ spriteInfo.x = RENDERWIDE / 2 - 5 - frame.width;
break;
case LINE_RIGHT:
spriteInfo.x = RENDERWIDE / 2 + 5;
@@ -913,7 +932,7 @@ void Screen::rollCredits() {
spriteInfo.w = logoWidth;
spriteInfo.h = logoHeight;
} else
- spriteInfo.x = (RENDERWIDE - frame->width) / 2;
+ spriteInfo.x = (RENDERWIDE - frame.width) / 2;
break;
}
@@ -978,7 +997,7 @@ void Screen::rollCredits() {
if (!_vm->_mouse->getMouseStatus() || _vm->_mouse->isChoosing())
_vm->_mouse->setMouse(NORMAL_MOUSE_ID);
- if (Logic::_scriptVars[DEAD])
+ if (_vm->_logic->readVar(DEAD))
_vm->_mouse->buildSystemMenu();
}
@@ -1001,32 +1020,38 @@ void Screen::splashScreen() {
closeBackgroundLayer();
byte *loadingBar = _vm->_resman->openResource(2951);
- AnimHeader *animHead = _vm->fetchAnimHeader(loadingBar);
- FrameHeader *frame = _vm->fetchFrameHeader(loadingBar, 0);
- CdtEntry *cdt = _vm->fetchCdtEntry(loadingBar, 0);
+ byte *frame = _vm->fetchFrameHeader(loadingBar, 0);
+
+ AnimHeader animHead;
+ CdtEntry cdt;
+ FrameHeader frame_head;
+
+ animHead.read(_vm->fetchAnimHeader(loadingBar));
+ cdt.read(_vm->fetchCdtEntry(loadingBar, 0));
+ frame_head.read(_vm->fetchFrameHeader(loadingBar, 0));
SpriteInfo barSprite;
- barSprite.x = cdt->x;
- barSprite.y = cdt->y;
- barSprite.w = frame->width;
- barSprite.h = frame->height;
+ barSprite.x = cdt.x;
+ barSprite.y = cdt.y;
+ barSprite.w = frame_head.width;
+ barSprite.h = frame_head.height;
barSprite.scale = 0;
barSprite.scaledWidth = 0;
barSprite.scaledHeight = 0;
barSprite.type = RDSPR_RLE256FAST | RDSPR_TRANS;
barSprite.blend = 0;
barSprite.colourTable = 0;
- barSprite.data = (byte *)(frame + 1);
+ barSprite.data = frame + FrameHeader::size();
drawSprite(&barSprite);
fadeUp();
waitForFade();
- for (int i = 0; i < animHead->noAnimFrames; i++) {
+ for (int i = 0; i < animHead.noAnimFrames; i++) {
frame = _vm->fetchFrameHeader(loadingBar, i);
- barSprite.data = (byte *)(frame + 1);
+ barSprite.data = frame + FrameHeader::size();
drawSprite(&barSprite);
updateDisplay();
_vm->_system->delayMillis(30);
diff --git a/sword2/build_display.h b/sword2/build_display.h
index 403fb809e5..77562502bf 100644
--- a/sword2/build_display.h
+++ b/sword2/build_display.h
@@ -22,6 +22,7 @@
#define _BUILD_DISPLAY
#include "common/rect.h"
+#include "common/stream.h"
#define MAX_bgp0_sprites 6
#define MAX_bgp1_sprites 6
@@ -53,10 +54,6 @@ namespace Sword2 {
class Sword2Engine;
-struct ObjectMouse;
-struct ObjectGraphic;
-struct ObjectMega;
-
// Sprite defines
enum {
@@ -176,19 +173,31 @@ struct BlockSurface {
bool transparent;
};
-#if !defined(__GNUC__)
- #pragma START_PACK_STRUCTS
-#endif
-
struct Parallax {
uint16 w;
uint16 h;
- uint32 offset[2]; // 2 is arbitrary
-} GCC_PACK;
-#if !defined(__GNUC__)
- #pragma END_PACK_STRUCTS
-#endif
+ // The dimensions are followed by an offset table, but we don't know in
+ // advance how big it is. See initializeBackgroundLayer().
+
+ static const int size() {
+ return 4;
+ }
+
+ void read(byte *addr) {
+ Common::MemoryReadStream readS(addr, size());
+
+ w = readS.readUint16LE();
+ h = readS.readUint16LE();
+ }
+
+ void write(byte *addr) {
+ Common::MemoryWriteStream writeS(addr, size());
+
+ writeS.writeUint16LE(w);
+ writeS.writeUint16LE(h);
+ }
+};
class Screen {
private:
@@ -310,13 +319,13 @@ private:
char _largestLayerInfo[128];
char _largestSpriteInfo[128];
- void registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, ObjectMega *ob_mega, BuildUnit *build_unit);
+ void registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega, BuildUnit *build_unit);
void mirrorSprite(byte *dst, byte *src, int16 w, int16 h);
int32 decompressRLE256(byte *dst, byte *src, int32 decompSize);
void unwindRaw16(byte *dst, byte *src, uint8 blockSize, byte *colTable);
int32 decompressRLE16(byte *dst, byte *src, int32 decompSize, byte *colTable);
- void renderParallax(Parallax *p, int16 layer);
+ void renderParallax(byte *ptr, int16 layer);
void markAsDirty(int16 x0, int16 y0, int16 x1, int16 y1);
@@ -370,13 +379,13 @@ public:
void resetRenderLists();
void setLocationMetrics(uint16 w, uint16 h);
- int32 initialiseBackgroundLayer(Parallax *p);
+ int32 initialiseBackgroundLayer(byte *parallax);
void closeBackgroundLayer();
void initialiseRenderCycle();
void initBackground(int32 res, int32 new_palette);
- void registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, ObjectMega *ob_mega);
+ void registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega);
void setScrollFraction(uint8 f) { _scrollFraction = f; }
void setScrollTarget(int16 x, int16 y);
diff --git a/sword2/console.cpp b/sword2/console.cpp
index de489f3408..a8062fb4aa 100644
--- a/sword2/console.cpp
+++ b/sword2/console.cpp
@@ -69,7 +69,7 @@ Debugger::Debugger(Sword2Engine *vm)
_textNumber = 0; // Current system text line number
- _playerGraphicNoFrames = 0; // No. of frames in currently displayed
+ _graphNoFrames = 0; // No. of frames in currently displayed
// anim
// Register commands
@@ -118,13 +118,13 @@ Debugger::Debugger(Sword2Engine *vm)
}
void Debugger::varGet(int var) {
- DebugPrintf("%d\n", Logic::_scriptVars[var]);
+ DebugPrintf("%d\n", _vm->_logic->readVar(var));
}
void Debugger::varSet(int var, int val) {
- DebugPrintf("was %d, ", Logic::_scriptVars[var]);
- Logic::_scriptVars[var] = val;
- DebugPrintf("now %d\n", Logic::_scriptVars[var]);
+ DebugPrintf("was %d, ", _vm->_logic->readVar(var));
+ _vm->_logic->writeVar(var, val);
+ DebugPrintf("now %d\n", _vm->_logic->readVar(var));
}
void Debugger::preEnter() {
@@ -210,10 +210,9 @@ bool Debugger::Cmd_Mem(int argc, const char **argv) {
DebugPrintf("---------------------------------------------------------------------------\n");
for (i = 0; i < numBlocks; i++) {
- StandardHeader *head = (StandardHeader *)blocks[i]->ptr;
const char *type;
- switch (head->fileType) {
+ switch (_vm->_resman->fetchType(blocks[i]->ptr)) {
case ANIMATION_FILE:
type = "ANIMATION_FILE";
break;
@@ -258,7 +257,7 @@ bool Debugger::Cmd_Mem(int argc, const char **argv) {
break;
}
- DebugPrintf("%9ld %-3d %-4d %-20s %s\n", blocks[i]->size, blocks[i]->id, blocks[i]->uid, type, head->name);
+ DebugPrintf("%9ld %-3d %-4d %-20s %s\n", blocks[i]->size, blocks[i]->id, blocks[i]->uid, type, _vm->_resman->fetchName(blocks[i]->ptr));
}
free(blocks);
@@ -321,8 +320,7 @@ bool Debugger::Cmd_ResList(int argc, const char **argv) {
for (uint i = 0; i < numResFiles; i++) {
if (resList[i].ptr && resList[i].refCount >= minCount) {
- StandardHeader *head = (StandardHeader *)resList[i].ptr;
- DebugPrintf("%-4d: %-35s refCount: %-3d\n", i, head->name, resList[i].refCount);
+ DebugPrintf("%-4d: %-35s refCount: %-3d\n", i, _vm->_resman->fetchName(resList[i].ptr), resList[i].refCount);
}
}
@@ -369,7 +367,7 @@ bool Debugger::Cmd_Start(int argc, const char **argv) {
int start = atoi(argv[1]);
- if (start < 0 || start >= (int) numStarts) {
+ if (start < 0 || start >= (int)numStarts) {
DebugPrintf("Not a legal start position\n");
return true;
}
@@ -434,7 +432,7 @@ bool Debugger::Cmd_ResLook(int argc, const char **argv) {
int res = atoi(argv[1]);
uint32 numResFiles = _vm->_resman->getNumResFiles();
- if (res < 0 || res >= (int) numResFiles) {
+ if (res < 0 || res >= (int)numResFiles) {
DebugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n",
res, numResFiles, numResFiles - 1);
return true;
@@ -446,48 +444,50 @@ bool Debugger::Cmd_ResLook(int argc, const char **argv) {
}
// Open up the resource and take a look inside!
- StandardHeader *file_header = (StandardHeader *)_vm->_resman->openResource(res);
+ uint8 type = _vm->_resman->fetchType(res);;
+ byte name[NAME_LEN];
- switch (file_header->fileType) {
+ _vm->_resman->fetchName(res, name);
+
+ switch (type) {
case ANIMATION_FILE:
- DebugPrintf("<anim> %s\n", file_header->name);
+ DebugPrintf("<anim> %s\n", name);
break;
case SCREEN_FILE:
- DebugPrintf("<layer> %s\n", file_header->name);
+ DebugPrintf("<layer> %s\n", name);
break;
case GAME_OBJECT:
- DebugPrintf("<game object> %s\n", file_header->name);
+ DebugPrintf("<game object> %s\n", name);
break;
case WALK_GRID_FILE:
- DebugPrintf("<walk grid> %s\n", file_header->name);
+ DebugPrintf("<walk grid> %s\n", name);
break;
case GLOBAL_VAR_FILE:
- DebugPrintf("<global variables> %s\n", file_header->name);
+ DebugPrintf("<global variables> %s\n", name);
break;
case PARALLAX_FILE_null:
- DebugPrintf("<parallax file NOT USED!> %s\n", file_header->name);
+ DebugPrintf("<parallax file NOT USED!> %s\n", name);
break;
case RUN_LIST:
- DebugPrintf("<run list> %s\n", file_header->name);
+ DebugPrintf("<run list> %s\n", name);
break;
case TEXT_FILE:
- DebugPrintf("<text file> %s\n", file_header->name);
+ DebugPrintf("<text file> %s\n", name);
break;
case SCREEN_MANAGER:
- DebugPrintf("<screen manager> %s\n", file_header->name);
+ DebugPrintf("<screen manager> %s\n", name);
break;
case MOUSE_FILE:
- DebugPrintf("<mouse pointer> %s\n", file_header->name);
+ DebugPrintf("<mouse pointer> %s\n", name);
break;
case ICON_FILE:
- DebugPrintf("<menu icon> %s\n", file_header->name);
+ DebugPrintf("<menu icon> %s\n", name);
break;
default:
- DebugPrintf("unrecognised fileType %d\n", file_header->fileType);
+ DebugPrintf("unrecognised fileType %d\n", type);
break;
}
- _vm->_resman->closeResource(res);
return true;
}
@@ -507,20 +507,23 @@ bool Debugger::Cmd_CurrentInfo(int argc, const char **argv) {
}
bool Debugger::Cmd_RunList(int argc, const char **argv) {
- uint32 *game_object_list;
- StandardHeader *file_header;
-
uint32 runList = _vm->_logic->getRunList();
if (runList) {
- game_object_list = (uint32 *)(_vm->_resman->openResource(runList) + sizeof(StandardHeader));
+ Common::MemoryReadStream readS(_vm->_resman->openResource(runList), _vm->_resman->fetchLen(runList));
+
+ readS.seek(ResHeader::size());
DebugPrintf("Runlist number %d\n", runList);
- for (int i = 0; game_object_list[i]; i++) {
- file_header = (StandardHeader *)_vm->_resman->openResource(game_object_list[i]);
- DebugPrintf("%d %s\n", game_object_list[i], file_header->name);
- _vm->_resman->closeResource(game_object_list[i]);
+ while (1) {
+ uint32 res = readS.readUint32LE();
+ if (!res)
+ break;
+
+ byte name[NAME_LEN];
+
+ DebugPrintf("%d %s\n", res, _vm->_resman->fetchName(res, name));
}
_vm->_resman->closeResource(runList);
@@ -539,7 +542,7 @@ bool Debugger::Cmd_Kill(int argc, const char **argv) {
int res = atoi(argv[1]);
uint32 numResFiles = _vm->_resman->getNumResFiles();
- if (res < 0 || res >= (int) numResFiles) {
+ if (res < 0 || res >= (int)numResFiles) {
DebugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n",
res, numResFiles, numResFiles - 1);
return true;
@@ -797,8 +800,8 @@ bool Debugger::Cmd_Events(int argc, const char **argv) {
uint32 target = eventList[i].id;
uint32 script = eventList[i].interact_id;
- DebugPrintf("slot %2d: id = %s (%d)\n", i, _vm->fetchObjectName(target, buf), target);
- DebugPrintf(" script = %s (%d) pos %d\n", _vm->fetchObjectName(script / 65536, buf), script / 65536, script % 65536);
+ DebugPrintf("slot %2d: id = %s (%d)\n", i, _vm->_resman->fetchName(target, buf), target);
+ DebugPrintf(" script = %s (%d) pos %d\n", _vm->_resman->fetchName(script / 65536, buf), script / 65536, script % 65536);
}
}
diff --git a/sword2/console.h b/sword2/console.h
index 0a2cc4e725..660ab6cc5f 100644
--- a/sword2/console.h
+++ b/sword2/console.h
@@ -67,8 +67,10 @@ public:
int32 _textNumber;
- ObjectGraphic _playerGraphic;
- uint32 _playerGraphicNoFrames;
+ int32 _graphType;
+ int32 _graphAnimRes;
+ int32 _graphAnimPc;
+ uint32 _graphNoFrames;
void buildDebugText();
void drawDebugGraphics();
diff --git a/sword2/controls.cpp b/sword2/controls.cpp
index 47edd52d09..6ff0c876b2 100644
--- a/sword2/controls.cpp
+++ b/sword2/controls.cpp
@@ -139,19 +139,23 @@ public:
FontRendererGui::FontRendererGui(Sword2Engine *vm, int fontId)
: _vm(vm), _fontId(fontId) {
byte *font = _vm->_resman->openResource(fontId);
- FrameHeader *head;
SpriteInfo sprite;
sprite.type = RDSPR_NOCOMPRESSION | RDSPR_TRANS;
for (int i = 0; i < SIZE_OF_CHAR_SET; i++) {
- head = (FrameHeader *)_vm->fetchFrameHeader(font, i);
- sprite.data = (byte *)(head + 1);
- sprite.w = head->width;
- sprite.h = head->height;
+ byte *frame = _vm->fetchFrameHeader(font, i);
+
+ FrameHeader frame_head;
+
+ frame_head.read(frame);
+
+ sprite.data = frame + FrameHeader::size();
+ sprite.w = frame_head.width;
+ sprite.h = frame_head.height;
_vm->_screen->createSurface(&sprite, &_glyph[i]._data);
- _glyph[i]._width = head->width;
- _glyph[i]._height = head->height;
+ _glyph[i]._width = frame_head.width;
+ _glyph[i]._height = frame_head.height;
}
_vm->_resman->closeResource(fontId);
@@ -413,27 +417,29 @@ Widget::~Widget() {
void Widget::createSurfaceImage(int state, uint32 res, int x, int y, uint32 pc) {
byte *file, *colTablePtr = NULL;
- AnimHeader *anim_head;
- FrameHeader *frame_head;
- CdtEntry *cdt_entry;
+ AnimHeader anim_head;
+ FrameHeader frame_head;
+ CdtEntry cdt_entry;
uint32 spriteType = RDSPR_TRANS;
// open anim resource file, point to base
file = _vm->_resman->openResource(res);
- anim_head = _vm->fetchAnimHeader(file);
- cdt_entry = _vm->fetchCdtEntry(file, pc);
- frame_head = _vm->fetchFrameHeader(file, pc);
+ byte *frame = _vm->fetchFrameHeader(file, pc);
+
+ anim_head.read(_vm->fetchAnimHeader(file));
+ cdt_entry.read(_vm->fetchCdtEntry(file, pc));
+ frame_head.read(frame);
// If the frame is flipped. (Only really applicable to frames using
// offsets.)
- if (cdt_entry->frameType & FRAME_FLIPPED)
+ if (cdt_entry.frameType & FRAME_FLIPPED)
spriteType |= RDSPR_FLIP;
// Which compression was used?
- switch (anim_head->runTimeComp) {
+ switch (anim_head.runTimeComp) {
case NONE:
spriteType |= RDSPR_NOCOMPRESSION;
break;
@@ -444,21 +450,21 @@ void Widget::createSurfaceImage(int state, uint32 res, int x, int y, uint32 pc)
spriteType |= RDSPR_RLE256;
// Points to just after last cdt_entry, i.e. start of colour
// table
- colTablePtr = (byte *)(anim_head + 1) +
- anim_head->noAnimFrames * sizeof(CdtEntry);
+ colTablePtr = _vm->fetchAnimHeader(file) + AnimHeader::size()
+ + anim_head.noAnimFrames * CdtEntry::size();
break;
}
_sprites[state].x = x;
_sprites[state].y = y;
- _sprites[state].w = frame_head->width;
- _sprites[state].h = frame_head->height;
+ _sprites[state].w = frame_head.width;
+ _sprites[state].h = frame_head.height;
_sprites[state].scale = 0;
_sprites[state].type = spriteType;
- _sprites[state].blend = anim_head->blend;
+ _sprites[state].blend = anim_head.blend;
// Points to just after frame header, ie. start of sprite data
- _sprites[state].data = (byte *)(frame_head + 1);
+ _sprites[state].data = frame + FrameHeader::size();
_vm->_screen->createSurface(&_sprites[state], &_surfaces[state]._surface);
_surfaces[state]._original = true;
@@ -661,7 +667,7 @@ private:
}
int valueFromPos(int x) {
- return (int) ((double) (_maxValue * (x - _hitRect.left)) / (double) (_hitRect.width() - 38) + 0.5);
+ return (int)((double)(_maxValue * (x - _hitRect.left)) / (double)(_hitRect.width() - 38) + 0.5);
}
public:
diff --git a/sword2/debug.cpp b/sword2/debug.cpp
index 75afc49f04..c3e6d635de 100644
--- a/sword2/debug.cpp
+++ b/sword2/debug.cpp
@@ -85,7 +85,7 @@ void Debugger::buildDebugText() {
// mouse area coords
// defining a mouse area the easy way, by creating a box on-screen
- if (_draggingRectangle || Logic::_scriptVars[SYSTEM_TESTING_ANIMS]) {
+ if (_draggingRectangle || _vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) {
// so we can see what's behind the lines
_rectFlicker = !_rectFlicker;
@@ -137,8 +137,8 @@ void Debugger::buildDebugText() {
if (_displayTextNumbers) {
if (_textNumber) {
- if (Logic::_scriptVars[SYSTEM_TESTING_TEXT]) {
- if (Logic::_scriptVars[SYSTEM_WANT_PREVIOUS_LINE])
+ if (_vm->_logic->readVar(SYSTEM_TESTING_TEXT)) {
+ if (_vm->_logic->readVar(SYSTEM_WANT_PREVIOUS_LINE))
sprintf(buf, "backwards");
else
sprintf(buf, "forwards");
@@ -159,8 +159,8 @@ void Debugger::buildDebugText() {
// resource number currently being checking for animation
- if (Logic::_scriptVars[SYSTEM_TESTING_ANIMS]) {
- sprintf(buf, "trying resource %d", Logic::_scriptVars[SYSTEM_TESTING_ANIMS]);
+ if (_vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) {
+ sprintf(buf, "trying resource %d", _vm->_logic->readVar(SYSTEM_TESTING_ANIMS));
makeDebugTextBlock(buf, 0, 90);
}
@@ -177,16 +177,16 @@ void Debugger::buildDebugText() {
// mouse coords & object pointed to
- if (Logic::_scriptVars[CLICKED_ID])
+ if (_vm->_logic->readVar(CLICKED_ID))
sprintf(buf, "last click at %d,%d (id %d: %s)",
- Logic::_scriptVars[MOUSE_X],
- Logic::_scriptVars[MOUSE_Y],
- Logic::_scriptVars[CLICKED_ID],
- _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], name));
+ _vm->_logic->readVar(MOUSE_X),
+ _vm->_logic->readVar(MOUSE_Y),
+ _vm->_logic->readVar(CLICKED_ID),
+ _vm->_resman->fetchName(_vm->_logic->readVar(CLICKED_ID), name));
else
sprintf(buf, "last click at %d,%d (---)",
- Logic::_scriptVars[MOUSE_X],
- Logic::_scriptVars[MOUSE_Y]);
+ _vm->_logic->readVar(MOUSE_X),
+ _vm->_logic->readVar(MOUSE_Y));
makeDebugTextBlock(buf, 0, 15);
@@ -201,7 +201,7 @@ void Debugger::buildDebugText() {
mouseX + screenInfo->scroll_offset_x,
mouseY + screenInfo->scroll_offset_y,
mouseTouching,
- _vm->fetchObjectName(mouseTouching, name));
+ _vm->_resman->fetchName(mouseTouching, name));
else
sprintf(buf, "mouse %d,%d (not touching)",
mouseX + screenInfo->scroll_offset_x,
@@ -212,19 +212,19 @@ void Debugger::buildDebugText() {
// player coords & graphic info
// if player objct has a graphic
- if (_playerGraphic.anim_resource)
+ if (_graphAnimRes)
sprintf(buf, "player %d,%d %s (%d) #%d/%d",
screenInfo->player_feet_x,
screenInfo->player_feet_y,
- _vm->fetchObjectName(_playerGraphic.anim_resource, name),
- _playerGraphic.anim_resource,
- _playerGraphic.anim_pc,
- _playerGraphicNoFrames);
+ _vm->_resman->fetchName(_graphAnimRes, name),
+ _graphAnimRes,
+ _graphAnimPc,
+ _graphNoFrames);
else
sprintf(buf, "player %d,%d --- %d",
screenInfo->player_feet_x,
screenInfo->player_feet_y,
- _playerGraphic.anim_pc);
+ _graphAnimPc);
makeDebugTextBlock(buf, 0, 45);
@@ -235,12 +235,12 @@ void Debugger::buildDebugText() {
// location number
- sprintf(buf, "location=%d", Logic::_scriptVars[LOCATION]);
+ sprintf(buf, "location=%d", _vm->_logic->readVar(LOCATION));
makeDebugTextBlock(buf, 440, 15);
// "result" variable
- sprintf(buf, "result=%d", Logic::_scriptVars[RESULT]);
+ sprintf(buf, "result=%d", _vm->_logic->readVar(RESULT));
makeDebugTextBlock(buf, 440, 30);
// no. of events in event list
@@ -282,7 +282,7 @@ void Debugger::buildDebugText() {
if (_speechScriptWaiting) {
sprintf(buf, "script waiting for %s (%d)",
- _vm->fetchObjectName(_speechScriptWaiting, name),
+ _vm->_resman->fetchName(_speechScriptWaiting, name),
_speechScriptWaiting);
makeDebugTextBlock(buf, 0, 90);
}
@@ -298,7 +298,7 @@ void Debugger::buildDebugText() {
// anyway because it changes throughout the logic loop
if (varNo) {
- sprintf(buf, "var(%d) = %d", varNo, Logic::_scriptVars[varNo]);
+ sprintf(buf, "var(%d) = %d", varNo, _vm->_logic->readVar(varNo));
makeDebugTextBlock(buf, 530, showVarPos);
showVarPos += 15; // next line down
}
@@ -345,7 +345,7 @@ void Debugger::drawDebugGraphics() {
// mouse area rectangle / sprite box rectangle when testing anims
- if (Logic::_scriptVars[SYSTEM_TESTING_ANIMS]) {
+ if (_vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) {
// draw box around current frame
drawRect(_rectX1, _rectY1, _rectX2, _rectY2, 184);
} else if (_draggingRectangle) {
diff --git a/sword2/driver/_mouse.cpp b/sword2/driver/_mouse.cpp
index 9d153f0c56..80af551f5d 100644
--- a/sword2/driver/_mouse.cpp
+++ b/sword2/driver/_mouse.cpp
@@ -20,6 +20,7 @@
#include "common/stdafx.h"
#include "common/system.h"
+#include "common/stream.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
@@ -33,12 +34,14 @@ namespace Sword2 {
#define MOUSEFLASHFRAME 6
-void Mouse::decompressMouse(byte *decomp, byte *comp, int width, int height, int pitch, int xOff, int yOff) {
+void Mouse::decompressMouse(byte *decomp, byte *comp, uint8 frame, int width, int height, int pitch, int xOff, int yOff) {
int32 size = width * height;
int32 i = 0;
int x = 0;
int y = 0;
+ comp = comp + READ_LE_UINT32(comp + frame * 4) - MOUSE_ANIM_HEADER_SIZE;
+
while (i < size) {
if (*comp > 183) {
decomp[(y + yOff) * pitch + x + xOff] = *comp++;
@@ -61,7 +64,7 @@ void Mouse::decompressMouse(byte *decomp, byte *comp, int width, int height, int
void Mouse::drawMouse() {
byte mouseData[MAX_MOUSE_W * MAX_MOUSE_H];
- if (!_mouseAnim && !_luggageAnim)
+ if (!_mouseAnim.data && !_luggageAnim.data)
return;
// When an object is used in the game, the mouse cursor should be a
@@ -77,27 +80,27 @@ void Mouse::drawMouse() {
int deltaX = 0;
int deltaY = 0;
- if (_mouseAnim) {
- hotspot_x = _mouseAnim->xHotSpot;
- hotspot_y = _mouseAnim->yHotSpot;
- mouse_width = _mouseAnim->mousew;
- mouse_height = _mouseAnim->mouseh;
+ if (_mouseAnim.data) {
+ hotspot_x = _mouseAnim.xHotSpot;
+ hotspot_y = _mouseAnim.yHotSpot;
+ mouse_width = _mouseAnim.mousew;
+ mouse_height = _mouseAnim.mouseh;
}
- if (_luggageAnim) {
- if (!_mouseAnim) {
- hotspot_x = _luggageAnim->xHotSpot;
- hotspot_y = _luggageAnim->yHotSpot;
+ if (_luggageAnim.data) {
+ if (!_mouseAnim.data) {
+ hotspot_x = _luggageAnim.xHotSpot;
+ hotspot_y = _luggageAnim.yHotSpot;
}
- if (_luggageAnim->mousew > mouse_width)
- mouse_width = _luggageAnim->mousew;
- if (_luggageAnim->mouseh > mouse_height)
- mouse_height = _luggageAnim->mouseh;
+ if (_luggageAnim.mousew > mouse_width)
+ mouse_width = _luggageAnim.mousew;
+ if (_luggageAnim.mouseh > mouse_height)
+ mouse_height = _luggageAnim.mouseh;
}
- if (_mouseAnim && _luggageAnim) {
- deltaX = _mouseAnim->xHotSpot - _luggageAnim->xHotSpot;
- deltaY = _mouseAnim->yHotSpot - _luggageAnim->yHotSpot;
+ if (_mouseAnim.data && _luggageAnim.data) {
+ deltaX = _mouseAnim.xHotSpot - _luggageAnim.xHotSpot;
+ deltaY = _mouseAnim.yHotSpot - _luggageAnim.yHotSpot;
}
assert(deltaX >= 0);
@@ -114,19 +117,21 @@ void Mouse::drawMouse() {
mouse_width += deltaX;
mouse_height += deltaY;
- if ((uint32) (mouse_width * mouse_height) > sizeof(mouseData)) {
+ if ((uint32)(mouse_width * mouse_height) > sizeof(mouseData)) {
warning("Mouse cursor too large");
return;
}
memset(mouseData, 0, mouse_width * mouse_height);
- if (_luggageAnim)
- decompressMouse(mouseData, (byte *)_luggageAnim + READ_LE_UINT32(_luggageOffset), _luggageAnim->mousew,
- _luggageAnim->mouseh, mouse_width, deltaX, deltaY);
+ if (_luggageAnim.data)
+ decompressMouse(mouseData, _luggageAnim.data, 0,
+ _luggageAnim.mousew, _luggageAnim.mouseh,
+ mouse_width, deltaX, deltaY);
- if (_mouseAnim)
- decompressMouse(mouseData, _mouseSprite, _mouseAnim->mousew, _mouseAnim->mouseh, mouse_width);
+ if (_mouseAnim.data)
+ decompressMouse(mouseData, _mouseAnim.data, _mouseFrame,
+ _mouseAnim.mousew, _mouseAnim.mouseh, mouse_width);
_vm->_system->setMouseCursor(mouseData, mouse_width, mouse_height, hotspot_x, hotspot_y, 0);
}
@@ -138,14 +143,12 @@ void Mouse::drawMouse() {
int32 Mouse::animateMouse() {
uint8 prevMouseFrame = _mouseFrame;
- if (!_mouseAnim)
+ if (!_mouseAnim.data)
return RDERR_UNKNOWN;
- if (++_mouseFrame == _mouseAnim->noAnimFrames)
+ if (++_mouseFrame == _mouseAnim.noAnimFrames)
_mouseFrame = MOUSEFLASHFRAME;
- _mouseSprite = (byte *)_mouseAnim + READ_LE_UINT32(_mouseOffsets + _mouseFrame);
-
if (_mouseFrame != prevMouseFrame)
drawMouse();
@@ -161,10 +164,8 @@ int32 Mouse::animateMouse() {
*/
int32 Mouse::setMouseAnim(byte *ma, int32 size, int32 mouseFlash) {
- if (_mouseAnim) {
- free(_mouseAnim);
- _mouseAnim = NULL;
- }
+ free(_mouseAnim.data);
+ _mouseAnim.data = NULL;
if (ma) {
if (mouseFlash == RDMOUSE_FLASH)
@@ -172,19 +173,27 @@ int32 Mouse::setMouseAnim(byte *ma, int32 size, int32 mouseFlash) {
else
_mouseFrame = MOUSEFLASHFRAME;
- _mouseAnim = (MouseAnim *)malloc(size);
- if (!_mouseAnim)
+ Common::MemoryReadStream readS(ma, size);
+
+ _mouseAnim.runTimeComp = readS.readByte();
+ _mouseAnim.noAnimFrames = readS.readByte();
+ _mouseAnim.xHotSpot = readS.readSByte();
+ _mouseAnim.yHotSpot = readS.readSByte();
+ _mouseAnim.mousew = readS.readByte();
+ _mouseAnim.mouseh = readS.readByte();
+
+ _mouseAnim.data = (byte *)malloc(size - MOUSE_ANIM_HEADER_SIZE);
+ if (!_mouseAnim.data)
return RDERR_OUTOFMEMORY;
- memcpy((byte *)_mouseAnim, ma, size);
- _mouseOffsets = (int32 *)((byte *)_mouseAnim + sizeof(MouseAnim));
+ readS.read(_mouseAnim.data, size - MOUSE_ANIM_HEADER_SIZE);
animateMouse();
drawMouse();
_vm->_system->showMouse(true);
} else {
- if (_luggageAnim)
+ if (_luggageAnim.data)
drawMouse();
else
_vm->_system->showMouse(false);
@@ -201,25 +210,31 @@ int32 Mouse::setMouseAnim(byte *ma, int32 size, int32 mouseFlash) {
*/
int32 Mouse::setLuggageAnim(byte *ma, int32 size) {
- if (_luggageAnim) {
- free(_luggageAnim);
- _luggageAnim = NULL;
- }
+ free(_luggageAnim.data);
+ _luggageAnim.data = NULL;
if (ma) {
- _luggageAnim = (MouseAnim *)malloc(size);
- if (!_luggageAnim)
+ Common::MemoryReadStream readS(ma, size);
+
+ _luggageAnim.runTimeComp = readS.readByte();
+ _luggageAnim.noAnimFrames = readS.readByte();
+ _luggageAnim.xHotSpot = readS.readSByte();
+ _luggageAnim.yHotSpot = readS.readSByte();
+ _luggageAnim.mousew = readS.readByte();
+ _luggageAnim.mouseh = readS.readByte();
+
+ _luggageAnim.data = (byte *)malloc(size - MOUSE_ANIM_HEADER_SIZE);
+ if (!_luggageAnim.data)
return RDERR_OUTOFMEMORY;
- memcpy((byte *)_luggageAnim, ma, size);
- _luggageOffset = (int32 *)((byte *)_luggageAnim + sizeof(MouseAnim));
+ readS.read(_luggageAnim.data, size - MOUSE_ANIM_HEADER_SIZE);
animateMouse();
drawMouse();
_vm->_system->showMouse(true);
} else {
- if (_mouseAnim)
+ if (_mouseAnim.data)
drawMouse();
else
_vm->_system->showMouse(false);
diff --git a/sword2/driver/animation.cpp b/sword2/driver/animation.cpp
index 41987dd2d4..071a88ac1a 100644
--- a/sword2/driver/animation.cpp
+++ b/sword2/driver/animation.cpp
@@ -176,12 +176,11 @@ int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], int32 lea
if (leadInRes) {
byte *leadIn = _vm->_resman->openResource(leadInRes);
- uint32 leadInLen = _vm->_resman->fetchLen(leadInRes) - sizeof(StandardHeader);
- StandardHeader *header = (StandardHeader *)leadIn;
+ uint32 leadInLen = _vm->_resman->fetchLen(leadInRes) - ResHeader::size();
- assert(header->fileType == WAV_FILE);
+ assert(_vm->_resman->fetchType(leadIn) == WAV_FILE);
- leadIn += sizeof(StandardHeader);
+ leadIn += ResHeader::size();
_vm->_sound->playFx(&leadInHandle, leadIn, leadInLen, Audio::Mixer::kMaxChannelVolume, 0, false, Audio::Mixer::kMusicSoundType);
}
@@ -191,15 +190,14 @@ int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], int32 lea
if (leadOutRes) {
leadOut = _vm->_resman->openResource(leadOutRes);
- leadOutLen = _vm->_resman->fetchLen(leadOutRes) - sizeof(StandardHeader);
- StandardHeader *header = (StandardHeader *)leadOut;
+ leadOutLen = _vm->_resman->fetchLen(leadOutRes) - ResHeader::size();
- assert(header->fileType == WAV_FILE);
+ assert(_vm->_resman->fetchType(leadOut) == WAV_FILE);
- leadOut += sizeof(StandardHeader);
+ leadOut += ResHeader::size();
}
- _leadOutFrame = (uint) -1;
+ _leadOutFrame = (uint)-1;
int i;
@@ -420,16 +418,18 @@ void MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], byte
data = _vm->_fontRenderer->makeTextSprite(msg, RENDERWIDE, 255, _vm->_speechFontId);
}
- FrameHeader *frame = (FrameHeader *)data;
+ FrameHeader frame_head;
SpriteInfo msgSprite;
byte *msgSurface;
- msgSprite.x = _vm->_screen->getScreenWide() / 2 - frame->width / 2;
- msgSprite.y = MENUDEEP / 2 - frame->height / 2;
- msgSprite.w = frame->width;
- msgSprite.h = frame->height;
+ frame_head.read(data);
+
+ msgSprite.x = _vm->_screen->getScreenWide() / 2 - frame_head.width / 2;
+ msgSprite.y = MENUDEEP / 2 - frame_head.height / 2;
+ msgSprite.w = frame_head.width;
+ msgSprite.h = frame_head.height;
msgSprite.type = RDSPR_NOCOMPRESSION;
- msgSprite.data = data + sizeof(FrameHeader);
+ msgSprite.data = data + FrameHeader::size();
_vm->_screen->createSurface(&msgSprite, &msgSurface);
_vm->_screen->drawSurface(&msgSprite, msgSurface);
diff --git a/sword2/driver/d_sound.cpp b/sword2/driver/d_sound.cpp
index ed12eaaaf9..8f3426c220 100644
--- a/sword2/driver/d_sound.cpp
+++ b/sword2/driver/d_sound.cpp
@@ -177,7 +177,7 @@ CLUInputStream::~CLUInputStream() {
int CLUInputStream::readBuffer(int16 *buffer, const int numSamples) {
int samples = 0;
while (samples < numSamples && !eosIntern()) {
- const int len = MIN(numSamples - samples, (int) (_bufferEnd - _pos));
+ const int len = MIN(numSamples - samples, (int)(_bufferEnd - _pos));
memcpy(buffer, _pos, len * 2);
buffer += len;
_pos += len;
@@ -195,7 +195,7 @@ void CLUInputStream::refill() {
_file->seek(_file_pos, SEEK_SET);
- uint len_left = _file->read(in, MIN((uint32) BUFFER_SIZE, _end_pos - _file->pos()));
+ uint len_left = _file->read(in, MIN((uint32)BUFFER_SIZE, _end_pos - _file->pos()));
_file_pos = _file->pos();
@@ -270,7 +270,7 @@ int MusicInputStream::readBuffer(int16 *buffer, const int numSamples) {
int samples = 0;
while (samples < numSamples && !eosIntern()) {
- const int len = MIN(numSamples - samples, (int) (_bufferEnd - _pos));
+ const int len = MIN(numSamples - samples, (int)(_bufferEnd - _pos));
memcpy(buffer, _pos, len * 2);
buffer += len;
_pos += len;
@@ -290,7 +290,7 @@ void MusicInputStream::refill() {
len_left = BUFFER_SIZE;
- if (_fading > 0 && (uint32) _fading < len_left)
+ if (_fading > 0 && (uint32)_fading < len_left)
len_left = _fading;
if (_samplesLeft < len_left)
diff --git a/sword2/driver/palette.cpp b/sword2/driver/palette.cpp
index 731c9449c0..2dd4f79343 100644
--- a/sword2/driver/palette.cpp
+++ b/sword2/driver/palette.cpp
@@ -60,7 +60,7 @@ void Screen::setFullPalette(int32 palRes) {
// is apparently needed for the palette to be restored properly when
// you turn the light off. (I didn't even notice the light switch!)
- if (Logic::_scriptVars[LOCATION] == 13) {
+ if (_vm->_logic->readVar(LOCATION) == 13) {
// unpausing
if (palRes == -1) {
// restore whatever palette was last set (screen
@@ -88,10 +88,9 @@ void Screen::setFullPalette(int32 palRes) {
if (palRes) {
byte *pal = _vm->_resman->openResource(palRes);
- StandardHeader *head = (StandardHeader *)pal;
- assert(head->fileType == PALETTE_FILE);
+ assert(_vm->_resman->fetchType(pal) == PALETTE_FILE);
- pal += sizeof(StandardHeader);
+ pal += ResHeader::size();
// always set colour 0 to black because most background screen
// palettes have a bright colour 0 although it should come out
@@ -130,7 +129,7 @@ void Screen::setFullPalette(int32 palRes) {
// linker complained when I tried to use it in sprite.cpp.
uint8 Screen::quickMatch(uint8 r, uint8 g, uint8 b) {
- return _paletteMatch[((int32) (r >> 2) << 12) + ((int32) (g >> 2) << 6) + (b >> 2)];
+ return _paletteMatch[((int32)(r >> 2) << 12) + ((int32)(g >> 2) << 6) + (b >> 2)];
}
/**
@@ -174,7 +173,7 @@ int32 Screen::fadeUp(float time) {
if (getFadeStatus() != RDFADE_BLACK && getFadeStatus() != RDFADE_NONE)
return RDERR_FADEINCOMPLETE;
- _fadeTotalTime = (int32) (time * 1000);
+ _fadeTotalTime = (int32)(time * 1000);
_fadeStatus = RDFADE_UP;
_fadeStartTime = _vm->_system->getMillis();
@@ -190,7 +189,7 @@ int32 Screen::fadeDown(float time) {
if (getFadeStatus() != RDFADE_BLACK && getFadeStatus() != RDFADE_NONE)
return RDERR_FADEINCOMPLETE;
- _fadeTotalTime = (int32) (time * 1000);
+ _fadeTotalTime = (int32)(time * 1000);
_fadeStatus = RDFADE_DOWN;
_fadeStartTime = _vm->_system->getMillis();
@@ -239,7 +238,7 @@ void Screen::fadeServer() {
_fadeStatus = RDFADE_NONE;
newPalette = _palette;
} else {
- fadeMultiplier = (int16) (((int32) (currentTime - _fadeStartTime) * 256) / _fadeTotalTime);
+ fadeMultiplier = (int16)(((int32)(currentTime - _fadeStartTime) * 256) / _fadeTotalTime);
for (i = 0; i < 256; i++) {
newPalette[i * 4 + 0] = (_palette[i * 4 + 0] * fadeMultiplier) >> 8;
newPalette[i * 4 + 1] = (_palette[i * 4 + 1] * fadeMultiplier) >> 8;
@@ -251,7 +250,7 @@ void Screen::fadeServer() {
_fadeStatus = RDFADE_BLACK;
memset(newPalette, 0, sizeof(fadePalette));
} else {
- fadeMultiplier = (int16) (((int32) (_fadeTotalTime - (currentTime - _fadeStartTime)) * 256) / _fadeTotalTime);
+ fadeMultiplier = (int16)(((int32)(_fadeTotalTime - (currentTime - _fadeStartTime)) * 256) / _fadeTotalTime);
for (i = 0; i < 256; i++) {
newPalette[i * 4 + 0] = (_palette[i * 4 + 0] * fadeMultiplier) >> 8;
newPalette[i * 4 + 1] = (_palette[i * 4 + 1] * fadeMultiplier) >> 8;
diff --git a/sword2/driver/render.cpp b/sword2/driver/render.cpp
index 5da110fc40..ae91a5346e 100644
--- a/sword2/driver/render.cpp
+++ b/sword2/driver/render.cpp
@@ -248,19 +248,22 @@ void Screen::setLocationMetrics(uint16 w, uint16 h) {
* parallax can be either foreground, background or the main screen.
*/
-void Screen::renderParallax(Parallax *p, int16 l) {
+void Screen::renderParallax(byte *ptr, int16 l) {
+ Parallax p;
int16 x, y;
Common::Rect r;
+ p.read(ptr);
+
if (_locationWide == _screenWide)
x = 0;
else
- x = ((int32) ((p->w - _screenWide) * _scrollX) / (int32) (_locationWide - _screenWide));
+ x = ((int32)((p.w - _screenWide) * _scrollX) / (int32)(_locationWide - _screenWide));
if (_locationDeep == _screenDeep - MENUDEEP * 2)
y = 0;
else
- y = ((int32) ((p->h - (_screenDeep - MENUDEEP * 2)) * _scrollY) / (int32) (_locationDeep - (_screenDeep - MENUDEEP * 2)));
+ y = ((int32)((p.h - (_screenDeep - MENUDEEP * 2)) * _scrollY) / (int32)(_locationDeep - (_screenDeep - MENUDEEP * 2)));
Common::Rect clipRect;
@@ -315,8 +318,8 @@ void Screen::startRenderCycle() {
_scrollY = _scrollYTarget;
_renderTooSlow = true;
} else {
- _scrollX = (int16) (_scrollXOld + ((_scrollXTarget - _scrollXOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
- _scrollY = (int16) (_scrollYOld + ((_scrollYTarget - _scrollYOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
+ _scrollX = (int16)(_scrollXOld + ((_scrollXTarget - _scrollXOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
+ _scrollY = (int16)(_scrollYOld + ((_scrollYTarget - _scrollYOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
_renderTooSlow = false;
}
@@ -377,8 +380,8 @@ bool Screen::endRenderCycle() {
_scrollX = _scrollXTarget;
_scrollY = _scrollYTarget;
} else {
- _scrollX = (int16) (_scrollXOld + ((_scrollXTarget - _scrollXOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
- _scrollY = (int16) (_scrollYOld + ((_scrollYTarget - _scrollYOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
+ _scrollX = (int16)(_scrollXOld + ((_scrollXTarget - _scrollXOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
+ _scrollY = (int16)(_scrollYOld + ((_scrollYTarget - _scrollYOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
}
if (_scrollX != _scrollXOld || _scrollY != _scrollYOld)
@@ -410,7 +413,8 @@ void Screen::resetRenderEngine() {
* or a NULL pointer in order of background parallax to foreground parallax.
*/
-int32 Screen::initialiseBackgroundLayer(Parallax *p) {
+int32 Screen::initialiseBackgroundLayer(byte *parallax) {
+ Parallax p;
uint16 i, j, k;
byte *data;
byte *dst;
@@ -419,13 +423,15 @@ int32 Screen::initialiseBackgroundLayer(Parallax *p) {
assert(_layer < MAXLAYERS);
- if (!p) {
+ if (!parallax) {
_layer++;
return RD_OK;
}
- _xBlocks[_layer] = (p->w + BLOCKWIDTH - 1) / BLOCKWIDTH;
- _yBlocks[_layer] = (p->h + BLOCKHEIGHT - 1) / BLOCKHEIGHT;
+ p.read(parallax);
+
+ _xBlocks[_layer] = (p.w + BLOCKWIDTH - 1) / BLOCKWIDTH;
+ _yBlocks[_layer] = (p.h + BLOCKHEIGHT - 1) / BLOCKHEIGHT;
_blockSurfaces[_layer] = (BlockSurface **)calloc(_xBlocks[_layer] * _yBlocks[_layer], sizeof(BlockSurface *));
if (!_blockSurfaces[_layer])
@@ -437,19 +443,21 @@ int32 Screen::initialiseBackgroundLayer(Parallax *p) {
if (!memchunk)
return RDERR_OUTOFMEMORY;
- for (i = 0; i < p->h; i++) {
- if (!p->offset[i])
+ for (i = 0; i < p.h; i++) {
+ uint32 p_offset = READ_LE_UINT32(parallax + Parallax::size() + 4 * i);
+
+ if (!p_offset)
continue;
- byte *pLine = (byte *)p + FROM_LE_32(p->offset[i]);
+ byte *pLine = parallax + p_offset;
uint16 packets = READ_LE_UINT16(pLine);
uint16 offset = READ_LE_UINT16(pLine + 2);
data = pLine + 4;
- dst = memchunk + i * p->w + offset;
+ dst = memchunk + i * p.w + offset;
if (!packets) {
- memcpy(dst, data, p->w);
+ memcpy(dst, data, p.w);
continue;
}
@@ -487,12 +495,12 @@ int32 Screen::initialiseBackgroundLayer(Parallax *p) {
int x = BLOCKWIDTH * (i % _xBlocks[_layer]);
int y = BLOCKHEIGHT * (i / _xBlocks[_layer]);
- data = memchunk + p->w * y + x;
+ data = memchunk + p.w * y + x;
for (j = 0; j < BLOCKHEIGHT; j++) {
for (k = 0; k < BLOCKWIDTH; k++) {
- if (x + k < p->w && y + j < p->h) {
- if (data[j * p->w + k])
+ if (x + k < p.w && y + j < p.h) {
+ if (data[j * p.w + k])
block_has_data = true;
else
block_is_transparent = true;
@@ -509,7 +517,7 @@ int32 Screen::initialiseBackgroundLayer(Parallax *p) {
dst = _blockSurfaces[_layer][i]->data;
for (j = 0; j < BLOCKHEIGHT; j++) {
memcpy(dst, data, BLOCKWIDTH);
- data += p->w;
+ data += p.w;
dst += BLOCKWIDTH;
}
diff --git a/sword2/events.cpp b/sword2/events.cpp
index 41b61b0fb8..289c60b5cc 100644
--- a/sword2/events.cpp
+++ b/sword2/events.cpp
@@ -44,7 +44,7 @@ void Logic::setPlayerActionEvent(uint32 id, uint32 interact_id) {
int Logic::checkEventWaiting() {
for (int i = 0; i < MAX_events; i++) {
- if (_eventList[i].id == _scriptVars[ID])
+ if (_eventList[i].id == readVar(ID))
return 1;
}
@@ -56,14 +56,14 @@ void Logic::startEvent() {
// you must follow with a return IR_TERMINATE
for (int i = 0; i < MAX_events; i++) {
- if (_eventList[i].id == _scriptVars[ID]) {
+ if (_eventList[i].id == readVar(ID)) {
logicOne(_eventList[i].interact_id);
_eventList[i].id = 0;
return;
}
}
- error("startEvent() can't find event for id %d", _scriptVars[ID]);
+ error("startEvent() can't find event for id %d", readVar(ID));
}
void Logic::clearEvent(uint32 id) {
diff --git a/sword2/function.cpp b/sword2/function.cpp
index d7c2e545f7..9f015f3bac 100644
--- a/sword2/function.cpp
+++ b/sword2/function.cpp
@@ -19,8 +19,8 @@
*/
#include "common/stdafx.h"
-#include "common/file.h"
#include "common/system.h"
+#include "common/file.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
@@ -81,19 +81,19 @@ int32 Logic::fnSetSession(int32 *params) {
int32 Logic::fnBackSprite(int32 *params) {
// params: 0 pointer to object's graphic structure
- _router->setSpriteStatus((ObjectGraphic *)decodePtr(params[0]), BACK_SPRITE);
+ _router->setSpriteStatus(decodePtr(params[0]), BACK_SPRITE);
return IR_CONT;
}
int32 Logic::fnSortSprite(int32 *params) {
// params: 0 pointer to object's graphic structure
- _router->setSpriteStatus((ObjectGraphic *)decodePtr(params[0]), SORT_SPRITE);
+ _router->setSpriteStatus(decodePtr(params[0]), SORT_SPRITE);
return IR_CONT;
}
int32 Logic::fnForeSprite(int32 *params) {
// params: 0 pointer to object's graphic structure
- _router->setSpriteStatus((ObjectGraphic *)decodePtr(params[0]), FORE_SPRITE);
+ _router->setSpriteStatus(decodePtr(params[0]), FORE_SPRITE);
return IR_CONT;
}
@@ -106,7 +106,7 @@ int32 Logic::fnRegisterMouse(int32 *params) {
// params: 0 pointer to ObjectMouse or 0 for no write to mouse
// list
- _vm->_mouse->registerMouse((ObjectMouse *)decodePtr(params[0]), NULL);
+ _vm->_mouse->registerMouse(decodePtr(params[0]), NULL);
return IR_CONT;
}
@@ -117,8 +117,8 @@ int32 Logic::fnAnim(int32 *params) {
// Normal forward animation
return _router->doAnimate(
- (ObjectLogic *)decodePtr(params[0]),
- (ObjectGraphic *)decodePtr(params[1]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
params[2], false);
}
@@ -126,7 +126,7 @@ int32 Logic::fnRandom(int32 *params) {
// params: 0 min
// 1 max
- _scriptVars[RESULT] = _vm->_rnd.getRandomNumberRng(params[0], params[1]);
+ writeVar(RESULT, _vm->_rnd.getRandomNumberRng(params[0], params[1]));
return IR_CONT;
}
@@ -157,7 +157,7 @@ int32 Logic::fnInteract(int32 *params) {
// params: 0 id of target from which we derive action script
// reference
- _scriptVars[PLAYER_ACTION] = 0; // must clear this
+ writeVar(PLAYER_ACTION, 0); // must clear this
logicUp((params[0] << 16) | 2); // 3rd script of clicked on id
// Out, up and around again - pc is saved for current level to be
@@ -177,7 +177,7 @@ int32 Logic::fnChoose(int32 *params) {
uint32 response = _vm->_mouse->chooseMouse();
- if (response == (uint32) -1)
+ if (response == (uint32)-1)
return IR_REPEAT;
return IR_CONT | (response << 3);
@@ -198,10 +198,10 @@ int32 Logic::fnWalk(int32 *params) {
// 6 target direction (8 means end walk on ANY direction)
return _router->doWalk(
- (ObjectLogic *)decodePtr(params[0]),
- (ObjectGraphic *)decodePtr(params[1]),
- (ObjectMega *)decodePtr(params[2]),
- (ObjectWalkdata *)decodePtr(params[3]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
+ decodePtr(params[2]),
+ decodePtr(params[3]),
params[4], params[5], params[6]);
}
@@ -217,10 +217,10 @@ int32 Logic::fnWalkToAnim(int32 *params) {
// 4 anim resource id
return _router->walkToAnim(
- (ObjectLogic *)decodePtr(params[0]),
- (ObjectGraphic *)decodePtr(params[1]),
- (ObjectMega *)decodePtr(params[2]),
- (ObjectWalkdata *)decodePtr(params[3]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
+ decodePtr(params[2]),
+ decodePtr(params[3]),
params[4]);
}
@@ -236,10 +236,10 @@ int32 Logic::fnTurn(int32 *params) {
// 4 target direction
return _router->doFace(
- (ObjectLogic *)decodePtr(params[0]),
- (ObjectGraphic *)decodePtr(params[1]),
- (ObjectMega *)decodePtr(params[2]),
- (ObjectWalkdata *)decodePtr(params[3]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
+ decodePtr(params[2]),
+ decodePtr(params[3]),
params[4]);
}
@@ -257,8 +257,8 @@ int32 Logic::fnStandAt(int32 *params) {
// 4 target direction
_router->standAt(
- (ObjectGraphic *)decodePtr(params[0]),
- (ObjectMega *)decodePtr(params[1]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
params[2], params[3], params[4]);
return IR_CONT;
}
@@ -272,11 +272,13 @@ int32 Logic::fnStand(int32 *params) {
// params: 0 pointer to object's graphic structure
// 1 pointer to object's mega structure
// 2 target direction
- ObjectMega *ob_mega = (ObjectMega *)decodePtr(params[1]);
+ byte *ob_mega = decodePtr(params[1]);
+
+ ObjectMega obMega(ob_mega);
_router->standAt(
- (ObjectGraphic *)decodePtr(params[0]),
- ob_mega, ob_mega->feet_x, ob_mega->feet_y, params[2]);
+ decodePtr(params[0]),
+ ob_mega, obMega.getFeetX(), obMega.getFeetY(), params[2]);
return IR_CONT;
}
@@ -290,8 +292,8 @@ int32 Logic::fnStandAfterAnim(int32 *params) {
// 2 anim resource id
_router->standAfterAnim(
- (ObjectGraphic *)decodePtr(params[0]),
- (ObjectMega *)decodePtr(params[1]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
params[2]);
return IR_CONT;
}
@@ -303,19 +305,19 @@ int32 Logic::fnPause(int32 *params) {
// NB. Pause-value of 0 causes script to continue, 1 causes a 1-cycle
// quit, 2 gives 2 cycles, etc.
- ObjectLogic *ob_logic = (ObjectLogic *)decodePtr(params[0]);
+ ObjectLogic obLogic(decodePtr(params[0]));
- if (ob_logic->looping == 0) {
- ob_logic->looping = 1;
- ob_logic->pause = params[1];
+ if (obLogic.getLooping() == 0) {
+ obLogic.setLooping(1);
+ obLogic.setPause(params[1]);
}
- if (ob_logic->pause) {
- ob_logic->pause--;
+ if (obLogic.getPause()) {
+ obLogic.setPause(obLogic.getPause() - 1);
return IR_REPEAT;
}
- ob_logic->looping = 0;
+ obLogic.setLooping(0);
return IR_CONT;
}
@@ -327,17 +329,17 @@ int32 Logic::fnMegaTableAnim(int32 *params) {
// Normal forward anim
return _router->megaTableAnimate(
- (ObjectLogic *)decodePtr(params[0]),
- (ObjectGraphic *)decodePtr(params[1]),
- (ObjectMega *)decodePtr(params[2]),
- (uint32 *)decodePtr(params[3]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
+ decodePtr(params[2]),
+ decodePtr(params[3]),
false);
}
int32 Logic::fnAddMenuObject(int32 *params) {
// params: 0 pointer to a MenuObject structure to copy down
- _vm->_mouse->addMenuObject((MenuObject *)decodePtr(params[0]));
+ _vm->_mouse->addMenuObject(decodePtr(params[0]));
return IR_CONT;
}
@@ -379,20 +381,21 @@ int32 Logic::fnSetFrame(int32 *params) {
// open the resource (& check it's valid)
byte *anim_file = _vm->_resman->openResource(res);
- StandardHeader *head = (StandardHeader *)anim_file;
- assert(head->fileType == ANIMATION_FILE);
+ assert(_vm->_resman->fetchType(res) == ANIMATION_FILE);
// set up pointer to the animation header
- AnimHeader *anim_head = _vm->fetchAnimHeader(anim_file);
+ AnimHeader anim_head;
+
+ anim_head.read(_vm->fetchAnimHeader(anim_file));
// set up anim resource in graphic object
- ObjectGraphic *ob_graphic = (ObjectGraphic *)decodePtr(params[0]);
+ ObjectGraphic obGraph(decodePtr(params[0]));
- ob_graphic->anim_resource = res;
- ob_graphic->anim_pc = params[2] ? anim_head->noAnimFrames - 1 : 0;
+ obGraph.setAnimResource(res);
+ obGraph.setAnimPc(params[2] ? anim_head.noAnimFrames - 1 : 0);
// Close the anim file and drop out of script
- _vm->_resman->closeResource(ob_graphic->anim_resource);
+ _vm->_resman->closeResource(obGraph.getAnimResource());
return IR_CONT;
}
@@ -401,14 +404,14 @@ int32 Logic::fnRandomPause(int32 *params) {
// 1 minimum number of game-cycles to pause
// 2 maximum number of game-cycles to pause
- ObjectLogic *ob_logic = (ObjectLogic *)decodePtr(params[0]);
+ ObjectLogic obLogic(decodePtr(params[0]));
int32 pars[2];
- if (ob_logic->looping == 0) {
+ if (obLogic.getLooping() == 0) {
pars[0] = params[1];
pars[1] = params[2];
fnRandom(pars);
- pars[1] = _scriptVars[RESULT];
+ pars[1] = readVar(RESULT);
}
pars[0] = params[0];
@@ -424,17 +427,16 @@ int32 Logic::fnRegisterFrame(int32 *params) {
// 1 pointer to graphic structure
// 2 pointer to mega structure or NULL if not a mega
- ObjectMouse *ob_mouse = (ObjectMouse *)decodePtr(params[0]);
- ObjectGraphic *ob_graph = (ObjectGraphic *)decodePtr(params[1]);
- ObjectMega *ob_mega = (ObjectMega *)decodePtr(params[2]);
-
- _vm->_screen->registerFrame(ob_mouse, ob_graph, ob_mega);
+ _vm->_screen->registerFrame(
+ decodePtr(params[0]),
+ decodePtr(params[1]),
+ decodePtr(params[2]));
return IR_CONT;
}
int32 Logic::fnNoSprite(int32 *params) {
// params: 0 pointer to object's graphic structure
- _router->setSpriteStatus((ObjectGraphic *)decodePtr(params[0]), NO_SPRITE);
+ _router->setSpriteStatus(decodePtr(params[0]), NO_SPRITE);
return IR_CONT;
}
@@ -444,7 +446,7 @@ int32 Logic::fnSendSync(int32 *params) {
for (int i = 0; i < MAX_syncs; i++) {
if (_syncList[i].id == 0) {
- debug(5, "%d sends sync %d to %d", _scriptVars[ID], params[1], params[0]);
+ debug(5, "%d sends sync %d to %d", readVar(ID), params[1], params[0]);
_syncList[i].id = params[0];
_syncList[i].sync = params[1];
return IR_CONT;
@@ -463,19 +465,21 @@ int32 Logic::fnUpdatePlayerStats(int32 *params) {
// params: 0 pointer to mega structure
- ObjectMega *ob_mega = (ObjectMega *)decodePtr(params[0]);
+ ObjectMega obMega(decodePtr(params[0]));
+
ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
- screenInfo->player_feet_x = ob_mega->feet_x;
- screenInfo->player_feet_y = ob_mega->feet_y;
+ screenInfo->player_feet_x = obMega.getFeetX();
+ screenInfo->player_feet_y = obMega.getFeetY();
// for the script
- _scriptVars[PLAYER_FEET_X] = ob_mega->feet_x;
- _scriptVars[PLAYER_FEET_Y] = ob_mega->feet_y;
- _scriptVars[PLAYER_CUR_DIR] = ob_mega->current_dir;
- _scriptVars[SCROLL_OFFSET_X] = screenInfo->scroll_offset_x;
+ writeVar(PLAYER_FEET_X, obMega.getFeetX());
+ writeVar(PLAYER_FEET_Y, obMega.getFeetY());
+ writeVar(PLAYER_CUR_DIR, obMega.getCurDir());
+ writeVar(SCROLL_OFFSET_X, screenInfo->scroll_offset_x);
- debug(5, "fnUpdatePlayerStats: %d %d", ob_mega->feet_x, ob_mega->feet_y);
+ debug(5, "fnUpdatePlayerStats: %d %d",
+ obMega.getFeetX(), obMega.getFeetY());
return IR_CONT;
}
@@ -496,31 +500,34 @@ int32 Logic::fnPassGraph(int32 *params) {
int32 Logic::fnInitFloorMouse(int32 *params) {
// params: 0 pointer to object's mouse structure
- ObjectMouse *ob_mouse = (ObjectMouse *)decodePtr(params[0]);
+ byte *ob_mouse = decodePtr(params[0]);
ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
// floor is always lowest priority
- ob_mouse->x1 = 0;
- ob_mouse->y1 = 0;
- ob_mouse->x2 = screenInfo->screen_wide - 1;
- ob_mouse->y2 = screenInfo->screen_deep - 1;
- ob_mouse->priority = 9;
- ob_mouse->pointer = NORMAL_MOUSE_ID;
+ ObjectMouse mouse;
+
+ mouse.x1 = 0;
+ mouse.y1 = 0;
+ mouse.x2 = screenInfo->screen_wide - 1;
+ mouse.y2 = screenInfo->screen_deep - 1;
+ mouse.priority = 9;
+ mouse.pointer = NORMAL_MOUSE_ID;
+
+ mouse.write(ob_mouse);
return IR_CONT;
}
int32 Logic::fnPassMega(int32 *params) {
- // makes an engine local copy of passed graphic_structure and
- // mega_structure - run script 4 of an object to request this
- // used by fnTurnTo(id) etc
+ // makes an engine local copy of passed mega_structure - run script 4
+ // of an object to request this used by fnTurnTo(id) etc
//
// remember, we cannot simply read a compact any longer but instead
// must request it from the object itself
// params: 0 pointer to a mega structure
- memcpy(&_engineMega, decodePtr(params[0]), sizeof(ObjectMega));
+ memcpy(_engineMega, decodePtr(params[0]), ObjectMega::size());
return IR_CONT;
}
@@ -537,10 +544,10 @@ int32 Logic::fnFaceXY(int32 *params) {
// 5 target y-coord
return _router->faceXY(
- (ObjectLogic *)decodePtr(params[0]),
- (ObjectGraphic *)decodePtr(params[1]),
- (ObjectMega *)decodePtr(params[2]),
- (ObjectWalkdata *)decodePtr(params[3]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
+ decodePtr(params[2]),
+ decodePtr(params[3]),
params[4], params[5]);
}
@@ -582,22 +589,14 @@ int32 Logic::fnAddHuman(int32 *params) {
int32 Logic::fnWeWait(int32 *params) {
// params: 0 target
- StandardHeader *head = (StandardHeader *)_vm->_resman->openResource(params[0]);
- assert(head->fileType == GAME_OBJECT);
+ assert(_vm->_resman->fetchType(params[0]) == GAME_OBJECT);
// Run the target's get-speech-state script
+ runResScript(params[0], 5);
- int32 target = params[0];
- char *raw_script_ad = (char *)head;
- uint32 null_pc = 5;
-
- runScript(raw_script_ad, raw_script_ad, &null_pc);
-
- _vm->_resman->closeResource(target);
-
- if (_scriptVars[RESULT] == 0) {
+ if (readVar(RESULT) == 0) {
// The target is busy. Try again.
- _vm->_debugger->_speechScriptWaiting = target;
+ _vm->_debugger->_speechScriptWaiting = params[0];
return IR_REPEAT;
}
@@ -622,60 +621,52 @@ int32 Logic::fnTheyDoWeWait(int32 *params) {
// 6 ins4
// 7 ins5
- StandardHeader *head = (StandardHeader *)_vm->_resman->openResource(params[1]);
- assert(head->fileType == GAME_OBJECT);
+ assert(_vm->_resman->fetchType(params[1]) == GAME_OBJECT);
// Run the target's get-speech-state script
+ runResScript(params[1], 5);
- int32 target = params[1];
- char *raw_script_ad = (char *)head;
- uint32 null_pc = 5;
+ ObjectLogic obLogic(decodePtr(params[0]));
- runScript(raw_script_ad, raw_script_ad, &null_pc);
-
- _vm->_resman->closeResource(target);
-
- ObjectLogic *ob_logic = (ObjectLogic *)decodePtr(params[0]);
-
- if (_scriptVars[RESULT] == 1 && !_scriptVars[INS_COMMAND] && ob_logic->looping == 0) {
+ if (readVar(RESULT) == 1 && readVar(INS_COMMAND) == 0 && obLogic.getLooping() == 0) {
// The target is waiting, i.e. not busy, and there is no other
// command queued. We haven't sent the command yet, so do it.
- debug(5, "fnTheyDoWeWait: sending command to %d", target);
+ debug(5, "fnTheyDoWeWait: sending command to %d", params[1]);
- _vm->_debugger->_speechScriptWaiting = target;
- ob_logic->looping = 1;
+ _vm->_debugger->_speechScriptWaiting = params[1];
+ obLogic.setLooping(1);
- _scriptVars[SPEECH_ID] = params[1];
- _scriptVars[INS_COMMAND] = params[2];
- _scriptVars[INS1] = params[3];
- _scriptVars[INS2] = params[4];
- _scriptVars[INS3] = params[5];
- _scriptVars[INS4] = params[6];
- _scriptVars[INS5] = params[7];
+ writeVar(SPEECH_ID, params[1]);
+ writeVar(INS_COMMAND, params[2]);
+ writeVar(INS1, params[3]);
+ writeVar(INS2, params[4]);
+ writeVar(INS3, params[5]);
+ writeVar(INS4, params[6]);
+ writeVar(INS5, params[7]);
return IR_REPEAT;
}
- if (ob_logic->looping == 0) {
+ if (obLogic.getLooping() == 0) {
// The command has not been sent yet. Keep waiting.
- _vm->_debugger->_speechScriptWaiting = target;
+ _vm->_debugger->_speechScriptWaiting = params[1];
return IR_REPEAT;
}
- if (_scriptVars[RESULT] == 0) {
+ if (readVar(RESULT) == 0) {
// The command has been sent, and the target is busy doing it.
// Wait for it to finish.
- debug(5, "fnTheyDoWeWait: Waiting for %d to finish", target);
+ debug(5, "fnTheyDoWeWait: Waiting for %d to finish", params[1]);
- _vm->_debugger->_speechScriptWaiting = target;
+ _vm->_debugger->_speechScriptWaiting = params[1];
return IR_REPEAT;
}
- debug(5, "fnTheyDoWeWait: %d finished", target);
+ debug(5, "fnTheyDoWeWait: %d finished", params[1]);
- ob_logic->looping = 0;
+ obLogic.setLooping(0);
_vm->_debugger->_speechScriptWaiting = 0;
return IR_CONT;
}
@@ -694,41 +685,33 @@ int32 Logic::fnTheyDo(int32 *params) {
// 5 ins4
// 6 ins5
- StandardHeader *head = (StandardHeader *)_vm->_resman->openResource(params[0]);
- assert(head->fileType == GAME_OBJECT);
+ assert(_vm->_resman->fetchType(params[0]) == GAME_OBJECT);
// Run the target's get-speech-state script
+ runResScript(params[0], 5);
- int32 target = params[0];
- char *raw_script_ad = (char *)head;
- uint32 null_pc = 5;
-
- runScript(raw_script_ad, raw_script_ad, &null_pc);
-
- _vm->_resman->closeResource(target);
-
- if (_scriptVars[RESULT] == 1 && !_scriptVars[INS_COMMAND]) {
+ if (readVar(RESULT) == 1 && !readVar(INS_COMMAND)) {
// The target is waiting, i.e. not busy, and there is no other
// command queued. Send the command.
- debug(5, "fnTheyDo: sending command to %d", target);
+ debug(5, "fnTheyDo: sending command to %d", params[0]);
_vm->_debugger->_speechScriptWaiting = 0;
- _scriptVars[SPEECH_ID] = params[0];
- _scriptVars[INS_COMMAND] = params[1];
- _scriptVars[INS1] = params[2];
- _scriptVars[INS2] = params[3];
- _scriptVars[INS3] = params[4];
- _scriptVars[INS4] = params[5];
- _scriptVars[INS5] = params[6];
+ writeVar(SPEECH_ID, params[0]);
+ writeVar(INS_COMMAND, params[1]);
+ writeVar(INS1, params[2]);
+ writeVar(INS2, params[3]);
+ writeVar(INS3, params[4]);
+ writeVar(INS4, params[5]);
+ writeVar(INS5, params[6]);
return IR_CONT;
}
// The target is busy. Come back again next cycle.
- _vm->_debugger->_speechScriptWaiting = target;
+ _vm->_debugger->_speechScriptWaiting = params[0];
return IR_REPEAT;
}
@@ -745,10 +728,10 @@ int32 Logic::fnWalkToTalkToMega(int32 *params) {
// 5 separation
return _router->walkToTalkToMega(
- (ObjectLogic *)decodePtr(params[0]),
- (ObjectGraphic *)decodePtr(params[1]),
- (ObjectMega *)decodePtr(params[2]),
- (ObjectWalkdata *)decodePtr(params[3]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
+ decodePtr(params[2]),
+ decodePtr(params[3]),
params[4], params[5]);
}
@@ -801,13 +784,13 @@ int32 Logic::fnISpeak(int32 *params) {
// Set up the pointers which we know we'll always need
- ObjectLogic *ob_logic = (ObjectLogic *)decodePtr(params[S_OB_LOGIC]);
- ObjectGraphic *ob_graphic = (ObjectGraphic *)decodePtr(params[S_OB_GRAPHIC]);
+ ObjectLogic obLogic(decodePtr(params[S_OB_LOGIC]));
+ ObjectGraphic obGraph(decodePtr(params[S_OB_GRAPHIC]));
// FIRST TIME ONLY: create the text, load the wav, set up the anim,
// etc.
- if (!ob_logic->looping) {
+ if (obLogic.getLooping() == 0) {
// New fudge to wait for smacker samples to finish
// since they can over-run into the game
@@ -850,32 +833,30 @@ int32 Logic::fnISpeak(int32 *params) {
// See 'testing_routines' object in George's Player Character
// section of linc
- if (_scriptVars[SYSTEM_TESTING_TEXT]) {
+ if (readVar(SYSTEM_TESTING_TEXT)) {
if (!_vm->_resman->checkValid(text_res)) {
// Not a valid resource number - invalid (null
// resource)
- _scriptVars[RESULT] = 1;
+ writeVar(RESULT, 1);
return IR_CONT;
}
- StandardHeader *head = (StandardHeader *)_vm->_resman->openResource(text_res);
-
- if (head->fileType != TEXT_FILE) {
+ if (_vm->_resman->fetchType(text_res) != TEXT_FILE) {
// Invalid - not a text resource
_vm->_resman->closeResource(text_res);
- _scriptVars[RESULT] = 1;
+ writeVar(RESULT, 1);
return IR_CONT;
}
- if (!_vm->checkTextLine((byte *)head, local_text)) {
+ if (!_vm->checkTextLine(_vm->_resman->openResource(text_res), local_text)) {
// Line number out of range
_vm->_resman->closeResource(text_res);
- _scriptVars[RESULT] = 2;
+ writeVar(RESULT, 2);
return IR_CONT;
}
_vm->_resman->closeResource(text_res);
- _scriptVars[RESULT] = 0;
+ writeVar(RESULT, 0);
}
byte *text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text);
@@ -885,11 +866,11 @@ int32 Logic::fnISpeak(int32 *params) {
// Prevent dud lines from appearing while testing text & speech
// since these will not occur in the game anyway
- if (_scriptVars[SYSTEM_TESTING_TEXT]) {
+ if (readVar(SYSTEM_TESTING_TEXT)) {
// If actor number is 0 and text line is just a 'dash'
// character
if (_officialTextNumber == 0 && text[2] == '-' && text[3] == 0) {
- _scriptVars[RESULT] = 3;
+ writeVar(RESULT, 3);
return IR_CONT;
}
}
@@ -898,16 +879,16 @@ int32 Logic::fnISpeak(int32 *params) {
// left-click past the text after half a second, and
// right-click past it after a quarter of a second.
- ob_logic->looping = 1;
+ obLogic.setLooping(1);
_leftClickDelay = 6;
_rightClickDelay = 3;
- if (_scriptVars[PLAYER_ID] != CUR_PLAYER_ID)
+ if (readVar(PLAYER_ID) != CUR_PLAYER_ID)
debug(5, "(%d) Nico: %s", _officialTextNumber, text + 2);
else {
byte buf[NAME_LEN];
- debug(5, "(%d) %s: %s", _officialTextNumber, _vm->fetchObjectName(_scriptVars[ID], buf), text + 2);
+ debug(5, "(%d) %s: %s", _officialTextNumber, _vm->_resman->fetchName(readVar(ID), buf), text + 2);
}
// Set up the speech animation
@@ -919,10 +900,10 @@ int32 Logic::fnISpeak(int32 *params) {
// Use this direction table to derive the anim
// NB. ASSUMES WE HAVE A MEGA OBJECT!!
- ObjectMega *ob_mega = (ObjectMega *)decodePtr(params[S_OB_MEGA]);
- int32 *anim_table = (int32 *)decodePtr(params[S_DIR_TABLE]);
+ ObjectMega obMega(decodePtr(params[S_OB_MEGA]));
+ byte *anim_table = decodePtr(params[S_DIR_TABLE]);
- _animId = anim_table[ob_mega->current_dir];
+ _animId = READ_LE_UINT32(anim_table + 4 * obMega.getCurDir());
} else {
// No animation choosen
_animId = 0;
@@ -932,13 +913,13 @@ int32 Logic::fnISpeak(int32 *params) {
// Set the talker's graphic to the first frame of this
// speech anim for now.
- _speechAnimType = _scriptVars[SPEECHANIMFLAG];
- ob_graphic->anim_resource = _animId;
- ob_graphic->anim_pc = 0;
+ _speechAnimType = readVar(SPEECHANIMFLAG);
+ obGraph.setAnimResource(_animId);
+ obGraph.setAnimPc(0);
}
// Default back to looped lip synced anims.
- _scriptVars[SPEECHANIMFLAG] = 0;
+ writeVar(SPEECHANIMFLAG, 0);
// Set up _textX and _textY for speech panning and/or text
// sprite position.
@@ -959,7 +940,7 @@ int32 Logic::fnISpeak(int32 *params) {
// from the 1st 2 chars of the text line.
if (!params[S_WAV])
- params[S_WAV] = (int32) _officialTextNumber;
+ params[S_WAV] = (int32)_officialTextNumber;
// Panning goes from -16 (left) to 16 (right)
int8 speech_pan = ((_textX - 320) * 16) / 320;
@@ -996,32 +977,34 @@ int32 Logic::fnISpeak(int32 *params) {
if (_animId) {
// There is an animation - Increment the anim frame number.
- ob_graphic->anim_pc++;
+ obGraph.setAnimPc(obGraph.getAnimPc() + 1);
+
+ byte *anim_file = _vm->_resman->openResource(obGraph.getAnimResource());
+ AnimHeader anim_head;
- byte *anim_file = _vm->_resman->openResource(ob_graphic->anim_resource);
- AnimHeader *anim_head = _vm->fetchAnimHeader(anim_file);
+ anim_head.read(_vm->fetchAnimHeader(anim_file));
if (!_speechAnimType) {
// ANIM IS TO BE LIP-SYNC'ED & REPEATING
- if (ob_graphic->anim_pc == (int32) (anim_head->noAnimFrames)) {
+ if (obGraph.getAnimPc() == (int32)anim_head.noAnimFrames) {
// End of animation - restart from frame 0
- ob_graphic->anim_pc = 0;
+ obGraph.setAnimPc(0);
} else if (speechRunning && _vm->_sound->amISpeaking() == RDSE_QUIET) {
// The speech is running, but we're at a quiet
// bit. Restart from frame 0 (closed mouth).
- ob_graphic->anim_pc = 0;
+ obGraph.setAnimPc(0);
}
} else {
// ANIM IS TO PLAY ONCE ONLY
- if (ob_graphic->anim_pc == (int32) (anim_head->noAnimFrames) - 1) {
+ if (obGraph.getAnimPc() == (int32)anim_head.noAnimFrames - 1) {
// Reached the last frame of the anim. Hold
// anim on this last frame
_animId = 0;
}
}
- _vm->_resman->closeResource(ob_graphic->anim_resource);
+ _vm->_resman->closeResource(obGraph.getAnimResource());
} else if (_speechAnimType) {
// Placed here so we actually display the last frame of the
// anim.
@@ -1061,7 +1044,7 @@ int32 Logic::fnISpeak(int32 *params) {
// So that we can go to the options panel while text & speech is
// being tested
- if (_scriptVars[SYSTEM_TESTING_TEXT] == 0 || mouseY > 0) {
+ if (readVar(SYSTEM_TESTING_TEXT) == 0 || mouseY > 0) {
MouseEvent *me = _vm->mouseEvent();
// Note that we now have TWO click-delays - one for LEFT
@@ -1073,14 +1056,14 @@ int32 Logic::fnISpeak(int32 *params) {
// the speech.
// if testing text & speech
- if (_scriptVars[SYSTEM_TESTING_TEXT]) {
+ if (readVar(SYSTEM_TESTING_TEXT)) {
// and RB used to click past text
if (me->buttons & RD_RIGHTBUTTONDOWN) {
// then we want the previous line again
- _scriptVars[SYSTEM_WANT_PREVIOUS_LINE] = 1;
+ writeVar(SYSTEM_WANT_PREVIOUS_LINE, 1);
} else {
// LB just want next line again
- _scriptVars[SYSTEM_WANT_PREVIOUS_LINE] = 0;
+ writeVar(SYSTEM_WANT_PREVIOUS_LINE, 0);
}
}
@@ -1107,13 +1090,13 @@ int32 Logic::fnISpeak(int32 *params) {
// if there is a speech anim, end it on closed mouth frame
if (_animId) {
_animId = 0;
- ob_graphic->anim_pc = 0;
+ obGraph.setAnimPc(0);
}
speechRunning = false;
// no longer in a script function loop
- ob_logic->looping = 0;
+ obLogic.setLooping(0);
_vm->_debugger->_textNumber = 0;
@@ -1121,7 +1104,7 @@ int32 Logic::fnISpeak(int32 *params) {
// this number comes from the text line)
_officialTextNumber = 0;
- _scriptVars[RESULT] = 0;
+ writeVar(RESULT, 0);
return IR_CONT;
}
@@ -1141,16 +1124,15 @@ int32 Logic::fnISpeak(int32 *params) {
* Reset the object and restart script 1 on level 0
*/
-#define LEVEL (_curObjectHub->logic_level)
-
int32 Logic::fnTotalRestart(int32 *params) {
// mega runs this to restart its base logic again - like being cached
// in again
// params: none
- LEVEL = 0;
- _curObjectHub->script_pc[0] = 1;
+ _curObjectHub.setLogicLevel(0);
+ _curObjectHub.setScriptPc(0, 1);
+
return IR_TERMINATE;
}
@@ -1194,7 +1176,7 @@ int32 Logic::fnSpeechProcess(int32 *params) {
// 3 pointer to ob_mega
// 4 pointer to ob_walkdata
- ObjectSpeech *ob_speech = (ObjectSpeech *)decodePtr(params[1]);
+ ObjectSpeech obSpeech(decodePtr(params[1]));
while (1) {
int32 pars[9];
@@ -1209,7 +1191,7 @@ int32 Logic::fnSpeechProcess(int32 *params) {
// Note: I can't see that we ever check the value of wait_state
// but perhaps it accesses that memory location directly?
- switch (ob_speech->command) {
+ switch (obSpeech.getCommand()) {
case 0:
break;
case INS_talk:
@@ -1217,15 +1199,15 @@ int32 Logic::fnSpeechProcess(int32 *params) {
pars[1] = params[1]; // ob_speech
pars[2] = params[2]; // ob_logic
pars[3] = params[3]; // ob_mega
- pars[4] = ob_speech->ins1; // encoded text number
- pars[5] = ob_speech->ins2; // wav res id
- pars[6] = ob_speech->ins3; // anim res id
- pars[7] = ob_speech->ins4; // anim table res id
- pars[8] = ob_speech->ins5; // animation mode - 0 lip synced, 1 just straight animation
+ pars[4] = obSpeech.getIns1(); // encoded text number
+ pars[5] = obSpeech.getIns2(); // wav res id
+ pars[6] = obSpeech.getIns3(); // anim res id
+ pars[7] = obSpeech.getIns4(); // anim table res id
+ pars[8] = obSpeech.getIns5(); // animation mode - 0 lip synced, 1 just straight animation
if (fnISpeak(pars) != IR_REPEAT) {
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
}
return IR_REPEAT;
@@ -1234,11 +1216,11 @@ int32 Logic::fnSpeechProcess(int32 *params) {
pars[1] = params[0]; // ob_graphic
pars[2] = params[3]; // ob_mega
pars[3] = params[4]; // ob_walkdata
- pars[4] = ob_speech->ins1; // direction to turn to
+ pars[4] = obSpeech.getIns1(); // direction to turn to
if (fnTurn(pars) != IR_REPEAT) {
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
}
return IR_REPEAT;
@@ -1247,33 +1229,33 @@ int32 Logic::fnSpeechProcess(int32 *params) {
pars[1] = params[0]; // ob_graphic
pars[2] = params[3]; // ob_mega
pars[3] = params[4]; // ob_walkdata
- pars[4] = ob_speech->ins1; // target
+ pars[4] = obSpeech.getIns1(); // target
if (fnFaceMega(pars) != IR_REPEAT) {
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
}
return IR_REPEAT;
case INS_anim:
pars[0] = params[2]; // ob_logic
pars[1] = params[0]; // ob_graphic
- pars[2] = ob_speech->ins1; // anim res
+ pars[2] = obSpeech.getIns1(); // anim res
if (fnAnim(pars) != IR_REPEAT) {
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
}
return IR_REPEAT;
case INS_reverse_anim:
pars[0] = params[2]; // ob_logic
pars[1] = params[0]; // ob_graphic
- pars[2] = ob_speech->ins1; // anim res
+ pars[2] = obSpeech.getIns1(); // anim res
if (fnReverseAnim(pars) != IR_REPEAT) {
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
}
return IR_REPEAT;
@@ -1281,11 +1263,11 @@ int32 Logic::fnSpeechProcess(int32 *params) {
pars[0] = params[2]; // ob_logic
pars[1] = params[0]; // ob_graphic
pars[2] = params[3]; // ob_mega
- pars[3] = ob_speech->ins1; // pointer to anim table
+ pars[3] = obSpeech.getIns1(); // pointer to anim table
if (fnMegaTableAnim(pars) != IR_REPEAT) {
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
}
return IR_REPEAT;
@@ -1293,50 +1275,50 @@ int32 Logic::fnSpeechProcess(int32 *params) {
pars[0] = params[2]; // ob_logic
pars[1] = params[0]; // ob_graphic
pars[2] = params[3]; // ob_mega
- pars[3] = ob_speech->ins1; // pointer to anim table
+ pars[3] = obSpeech.getIns1(); // pointer to anim table
if (fnReverseMegaTableAnim(pars) != IR_REPEAT) {
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
}
return IR_REPEAT;
case INS_no_sprite:
fnNoSprite(params); // ob_graphic
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
return IR_REPEAT ;
case INS_sort:
fnSortSprite(params); // ob_graphic
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
return IR_REPEAT;
case INS_foreground:
fnForeSprite(params); // ob_graphic
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
return IR_REPEAT;
case INS_background:
fnBackSprite(params); // ob_graphic
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
return IR_REPEAT;
case INS_walk:
pars[0] = params[2]; // ob_logic
pars[1] = params[0]; // ob_graphic
pars[2] = params[3]; // ob_mega
pars[3] = params[4]; // ob_walkdata
- pars[4] = ob_speech->ins1; // target x
- pars[5] = ob_speech->ins2; // target y
- pars[6] = ob_speech->ins3; // target direction
+ pars[4] = obSpeech.getIns1(); // target x
+ pars[5] = obSpeech.getIns2(); // target y
+ pars[6] = obSpeech.getIns3(); // target direction
if (fnWalk(pars) != IR_REPEAT) {
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
}
return IR_REPEAT;
@@ -1345,69 +1327,69 @@ int32 Logic::fnSpeechProcess(int32 *params) {
pars[1] = params[0]; // ob_graphic
pars[2] = params[3]; // ob_mega
pars[3] = params[4]; // ob_walkdata
- pars[4] = ob_speech->ins1; // anim resource
+ pars[4] = obSpeech.getIns1(); // anim resource
if (fnWalkToAnim(pars) != IR_REPEAT) {
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
}
return IR_REPEAT;
case INS_stand_after_anim:
pars[0] = params[0]; // ob_graphic
pars[1] = params[3]; // ob_mega
- pars[2] = ob_speech->ins1; // anim resource
+ pars[2] = obSpeech.getIns1(); // anim resource
fnStandAfterAnim(pars);
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
return IR_REPEAT;
case INS_set_frame:
pars[0] = params[0]; // ob_graphic
- pars[1] = ob_speech->ins1; // anim_resource
- pars[2] = ob_speech->ins2; // FIRST_FRAME or LAST_FRAME
+ pars[1] = obSpeech.getIns1(); // anim_resource
+ pars[2] = obSpeech.getIns2(); // FIRST_FRAME or LAST_FRAME
fnSetFrame(pars);
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
return IR_REPEAT;
case INS_quit:
// That's it - we're finished with this
- ob_speech->command = 0;
- // ob_speech->wait_state = 0;
+ obSpeech.setCommand(0);
+ // obSpeech.setWaitState(0);
return IR_CONT;
default:
// Unimplemented command - just cancel
- ob_speech->command = 0;
- ob_speech->wait_state = 1;
+ obSpeech.setCommand(0);
+ obSpeech.setWaitState(1);
break;
}
- if (_scriptVars[SPEECH_ID] == _scriptVars[ID]) {
+ if (readVar(SPEECH_ID) == readVar(ID)) {
// There's a new command for us! Grab the command -
// potentially we only have this cycle to do this - and
// set things up so that the command will be picked up
// on the next iteration of the while loop.
- debug(5, "fnSpeechProcess: Received new command %d", _scriptVars[INS_COMMAND]);
+ debug(5, "fnSpeechProcess: Received new command %d", readVar(INS_COMMAND));
- _scriptVars[SPEECH_ID] = 0;
+ writeVar(SPEECH_ID, 0);
- ob_speech->command = _scriptVars[INS_COMMAND];
- ob_speech->ins1 = _scriptVars[INS1];
- ob_speech->ins2 = _scriptVars[INS2];
- ob_speech->ins3 = _scriptVars[INS3];
- ob_speech->ins4 = _scriptVars[INS4];
- ob_speech->ins5 = _scriptVars[INS5];
- ob_speech->wait_state = 0;
+ obSpeech.setCommand(readVar(INS_COMMAND));
+ obSpeech.setIns1(readVar(INS1));
+ obSpeech.setIns2(readVar(INS2));
+ obSpeech.setIns3(readVar(INS3));
+ obSpeech.setIns4(readVar(INS4));
+ obSpeech.setIns5(readVar(INS5));
+ obSpeech.setWaitState(0);
- _scriptVars[INS_COMMAND] = 0;
+ writeVar(INS_COMMAND, 0);
} else {
// No new command. We could run a blink anim (or
// something) here.
- ob_speech->wait_state = 1;
+ obSpeech.setWaitState(1);
return IR_REPEAT;
}
}
@@ -1423,10 +1405,10 @@ int32 Logic::fnSetScaling(int32 *params) {
// Where s is system scale, which itself is (256 * actual_scale) ie.
// s == 128 is half size
- ObjectMega *ob_mega = (ObjectMega *)decodePtr(params[0]);
+ ObjectMega obMega(decodePtr(params[0]));
- ob_mega->scale_a = params[1];
- ob_mega->scale_b = params[2];
+ obMega.setScaleA(params[1]);
+ obMega.setScaleB(params[2]);
return IR_CONT;
}
@@ -1441,7 +1423,7 @@ int32 Logic::fnStartEvent(int32 *params) {
int32 Logic::fnCheckEventWaiting(int32 *params) {
// params: none
- _scriptVars[RESULT] = checkEventWaiting();
+ writeVar(RESULT, checkEventWaiting());
return IR_CONT;
}
@@ -1480,55 +1462,47 @@ int32 Logic::fnTimedWait(int32 *params) {
// 1 target
// 2 number of cycles before give up
- StandardHeader *head = (StandardHeader *)_vm->_resman->openResource(params[1]);
- assert(head->fileType == GAME_OBJECT);
+ assert(_vm->_resman->fetchType(params[1]) == GAME_OBJECT);
- ObjectLogic *ob_logic = (ObjectLogic *)decodePtr(params[0]);
+ ObjectLogic obLogic(decodePtr(params[0]));
- if (!ob_logic->looping) {
+ if (obLogic.getLooping() == 0) {
// This is the first time, so set up the time-out.
- ob_logic->looping = params[2];
+ obLogic.setLooping(params[2]);
}
// Run the target's get-speech-state script
+ runResScript(params[1], 5);
- int32 target = params[1];
- char *raw_script_ad = (char *)head;
- uint32 null_pc = 5;
-
- runScript(raw_script_ad, raw_script_ad, &null_pc);
-
- _vm->_resman->closeResource(target);
-
- if (_scriptVars[RESULT] == 1) {
+ if (readVar(RESULT) == 1) {
// The target is waiting, i.e. not busy
_vm->_debugger->_speechScriptWaiting = 0;
- ob_logic->looping = 0;
- _scriptVars[RESULT] = 0;
+ obLogic.setLooping(0);
+ writeVar(RESULT, 0);
return IR_CONT;
}
- ob_logic->looping--;
+ obLogic.setLooping(obLogic.getLooping() - 1);
- if (!ob_logic->looping) {
+ if (obLogic.getLooping() == 0) {
// Time's up.
- debug(5, "fnTimedWait: Timed out waiting for %d", target);
+ debug(5, "fnTimedWait: Timed out waiting for %d", params[1]);
_vm->_debugger->_speechScriptWaiting = 0;
// Clear the event that hasn't been picked up - in theory,
// none of this should ever happen.
- killAllIdsEvents(target);
- _scriptVars[RESULT] = 1;
+ killAllIdsEvents(params[1]);
+ writeVar(RESULT, 1);
return IR_CONT;
}
// Target is busy. Keep trying.
- _vm->_debugger->_speechScriptWaiting = target;
+ _vm->_debugger->_speechScriptWaiting = params[1];
return IR_REPEAT;
}
@@ -1605,9 +1579,9 @@ int32 Logic::fnSetValue(int32 *params) {
// params: 0 pointer to object's mega structure
// 1 value to set it to
- ObjectMega *ob_mega = (ObjectMega *)decodePtr(params[0]);
+ ObjectMega obMega(decodePtr(params[0]));
- ob_mega->megaset_res = params[1];
+ obMega.setMegasetRes(params[1]);
return IR_CONT;
}
@@ -1617,7 +1591,7 @@ int32 Logic::fnNewScript(int32 *params) {
// params: 0 id of script
- _scriptVars[PLAYER_ACTION] = 0; // must clear this
+ writeVar(PLAYER_ACTION, 0); // must clear this
logicReplace(params[0]);
return IR_TERMINATE;
}
@@ -1632,7 +1606,7 @@ int32 Logic::fnGetSync(int32 *params) {
int slot = getSync();
- _scriptVars[RESULT] = (slot != -1) ? _syncList[slot].sync : 0;
+ writeVar(RESULT, (slot != -1) ? _syncList[slot].sync : 0);
return IR_CONT;
}
@@ -1644,15 +1618,15 @@ int32 Logic::fnGetSync(int32 *params) {
int32 Logic::fnWaitSync(int32 *params) {
// params: none
- debug(6, "fnWaitSync: %d waits", _scriptVars[ID]);
+ debug(6, "fnWaitSync: %d waits", readVar(ID));
int slot = getSync();
if (slot == -1)
return IR_REPEAT;
- debug(5, "fnWaitSync: %d got sync %d", _scriptVars[ID], _syncList[slot].sync);
- _scriptVars[RESULT] = _syncList[slot].sync;
+ debug(5, "fnWaitSync: %d got sync %d", readVar(ID), _syncList[slot].sync);
+ writeVar(RESULT, _syncList[slot].sync);
return IR_CONT;
}
@@ -1671,10 +1645,10 @@ int32 Logic::fnReverseMegaTableAnim(int32 *params) {
// Reverse anim
return _router->megaTableAnimate(
- (ObjectLogic *)decodePtr(params[0]),
- (ObjectGraphic *)decodePtr(params[1]),
- (ObjectMega *)decodePtr(params[2]),
- (uint32 *)decodePtr(params[3]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
+ decodePtr(params[2]),
+ decodePtr(params[3]),
true);
}
@@ -1685,8 +1659,8 @@ int32 Logic::fnReverseAnim(int32 *params) {
// Reverse anim
return _router->doAnimate(
- (ObjectLogic *)decodePtr(params[0]),
- (ObjectGraphic *)decodePtr(params[1]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
params[2], true);
}
@@ -1702,21 +1676,22 @@ int32 Logic::fnReverseAnim(int32 *params) {
int32 Logic::fnAddToKillList(int32 *params) {
// params: none
+ uint32 id = readVar(ID);
// DON'T EVER KILL GEORGE!
- if (_scriptVars[ID] == CUR_PLAYER_ID)
+ if (id == CUR_PLAYER_ID)
return IR_CONT;
// Scan the list to see if it's already included
for (uint32 i = 0; i < _kills; i++) {
- if (_objectKillList[i] == _scriptVars[ID])
+ if (_objectKillList[i] == id)
return IR_CONT;
}
assert(_kills < OBJECT_KILL_LIST_SIZE); // no room at the inn
- _objectKillList[_kills++] = _scriptVars[ID];
+ _objectKillList[_kills++] = id;
// "another one bites the dust"
@@ -1745,25 +1720,25 @@ int32 Logic::fnSetStandbyCoords(int32 *params) {
int32 Logic::fnBackPar0Sprite(int32 *params) {
// params: 0 pointer to object's graphic structure
- _router->setSpriteStatus((ObjectGraphic *)decodePtr(params[0]), BGP0_SPRITE);
+ _router->setSpriteStatus(decodePtr(params[0]), BGP0_SPRITE);
return IR_CONT;
}
int32 Logic::fnBackPar1Sprite(int32 *params) {
// params: 0 pointer to object's graphic structure
- _router->setSpriteStatus((ObjectGraphic *)decodePtr(params[0]), BGP1_SPRITE);
+ _router->setSpriteStatus(decodePtr(params[0]), BGP1_SPRITE);
return IR_CONT;
}
int32 Logic::fnForePar0Sprite(int32 *params) {
// params: 0 pointer to object's graphic structure
- _router->setSpriteStatus((ObjectGraphic *)decodePtr(params[0]), FGP0_SPRITE);
+ _router->setSpriteStatus(decodePtr(params[0]), FGP0_SPRITE);
return IR_CONT;
}
int32 Logic::fnForePar1Sprite(int32 *params) {
// params: 0 pointer to object's graphic structure
- _router->setSpriteStatus((ObjectGraphic *)decodePtr(params[0]), FGP1_SPRITE);
+ _router->setSpriteStatus(decodePtr(params[0]), FGP1_SPRITE);
return IR_CONT;
}
@@ -1816,8 +1791,8 @@ int32 Logic::fnStandAtAnim(int32 *params) {
// 2 anim resource id
_router->standAtAnim(
- (ObjectGraphic *)decodePtr(params[0]),
- (ObjectMega *)decodePtr(params[1]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
params[2]);
return IR_CONT;
}
@@ -1827,50 +1802,56 @@ int32 Logic::fnStandAtAnim(int32 *params) {
int32 Logic::fnSetScrollLeftMouse(int32 *params) {
// params: 0 pointer to object's mouse structure
- ObjectMouse *ob_mouse = (ObjectMouse *)decodePtr(params[0]);
+ byte *ob_mouse = decodePtr(params[0]);
ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
// Highest priority
- ob_mouse->x1 = 0;
- ob_mouse->y1 = 0;
- ob_mouse->x2 = screenInfo->scroll_offset_x + SCROLL_MOUSE_WIDTH;
- ob_mouse->y2 = screenInfo->screen_deep - 1;
- ob_mouse->priority = 0;
+ ObjectMouse mouse;
+
+ mouse.x1 = 0;
+ mouse.y1 = 0;
+ mouse.x2 = screenInfo->scroll_offset_x + SCROLL_MOUSE_WIDTH;
+ mouse.y2 = screenInfo->screen_deep - 1;
+ mouse.priority = 0;
if (screenInfo->scroll_offset_x > 0) {
// not fully scrolled to the left
- ob_mouse->pointer = SCROLL_LEFT_MOUSE_ID;
+ mouse.pointer = SCROLL_LEFT_MOUSE_ID;
} else {
// so the mouse area doesn't get registered
- ob_mouse->pointer = 0;
+ mouse.pointer = 0;
}
+ mouse.write(ob_mouse);
return IR_CONT;
}
int32 Logic::fnSetScrollRightMouse(int32 *params) {
// params: 0 pointer to object's mouse structure
- ObjectMouse *ob_mouse = (ObjectMouse *)decodePtr(params[0]);
+ byte *ob_mouse = decodePtr(params[0]);
ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
// Highest priority
- ob_mouse->x1 = screenInfo->scroll_offset_x + _vm->_screen->getScreenWide() - SCROLL_MOUSE_WIDTH;
- ob_mouse->y1 = 0;
- ob_mouse->x2 = screenInfo->screen_wide - 1;
- ob_mouse->y2 = screenInfo->screen_deep - 1;
- ob_mouse->priority = 0;
+ ObjectMouse mouse;
+
+ mouse.x1 = screenInfo->scroll_offset_x + _vm->_screen->getScreenWide() - SCROLL_MOUSE_WIDTH;
+ mouse.y1 = 0;
+ mouse.x2 = screenInfo->screen_wide - 1;
+ mouse.y2 = screenInfo->screen_deep - 1;
+ mouse.priority = 0;
if (screenInfo->scroll_offset_x < screenInfo->max_scroll_offset_x) {
// not fully scrolled to the right
- ob_mouse->pointer = SCROLL_RIGHT_MOUSE_ID;
+ mouse.pointer = SCROLL_RIGHT_MOUSE_ID;
} else {
// so the mouse area doesn't get registered
- ob_mouse->pointer = 0;
+ mouse.pointer = 0;
}
+ mouse.write(ob_mouse);
return IR_CONT;
}
@@ -1971,36 +1952,36 @@ int32 Logic::fnGetPlayerSaveData(int32 *params) {
// 1 pointer to object's graphic structure
// 2 pointer to object's mega structure
- byte *logic_ptr = decodePtr(params[0]);
- byte *graphic_ptr = decodePtr(params[1]);
- byte *mega_ptr = decodePtr(params[2]);
+ byte *ob_logic = decodePtr(params[0]);
+ byte *ob_graph = decodePtr(params[1]);
+ byte *ob_mega = decodePtr(params[2]);
- // Copy from savegame header to player object
+ // Copy from savegame buffers to player object
- memcpy(logic_ptr, &_vm->_saveGameHeader.logic, sizeof(ObjectLogic));
- memcpy(graphic_ptr, &_vm->_saveGameHeader.graphic, sizeof(ObjectGraphic));
- memcpy(mega_ptr, &_vm->_saveGameHeader.mega, sizeof(ObjectMega));
+ memcpy(ob_logic, _saveLogic, ObjectLogic::size());
+ memcpy(ob_graph, _saveGraphic, ObjectGraphic::size());
+ memcpy(ob_mega, _saveMega, ObjectMega::size());
// Any walk-data must be cleared - the player will be set to stand if
// he was walking when saved.
- ObjectMega *ob_mega = (ObjectMega *)mega_ptr;
+ ObjectMega obMega(ob_mega);
+
+ if (obMega.getIsWalking()) {
+ ObjectLogic obLogic(ob_logic);
- if (ob_mega->currently_walking) {
- ob_mega->currently_walking = 0;
+ obMega.setIsWalking(0);
int32 pars[3];
pars[0] = params[1]; // ob_graphic;
pars[1] = params[2]; // ob_mega
- pars[2] = ob_mega->current_dir;
+ pars[2] = obMega.getCurDir();
fnStand(pars);
// Reset looping flag (which would have been 1 during fnWalk)
- ObjectLogic *ob_logic = (ObjectLogic *)logic_ptr;
-
- ob_logic->looping = 0;
+ obLogic.setLooping(0);
}
return IR_CONT;
@@ -2019,11 +2000,11 @@ int32 Logic::fnPassPlayerSaveData(int32 *params) {
// 1 pointer to object's graphic structure
// 2 pointer to object's mega structure
- // Copy from player object to savegame header
+ // Copy from player object to savegame buffers
- memcpy(&_vm->_saveGameHeader.logic, decodePtr(params[0]), sizeof(ObjectLogic));
- memcpy(&_vm->_saveGameHeader.graphic, decodePtr(params[1]), sizeof(ObjectGraphic));
- memcpy(&_vm->_saveGameHeader.mega, decodePtr(params[2]), sizeof(ObjectMega));
+ memcpy(_saveLogic, decodePtr(params[0]), ObjectLogic::size());
+ memcpy(_saveGraphic, decodePtr(params[1]), ObjectGraphic::size());
+ memcpy(_saveMega, decodePtr(params[2]), ObjectMega::size());
return IR_CONT;
}
@@ -2051,7 +2032,7 @@ int32 Logic::fnAddWalkGrid(int32 *params) {
// re-enter a location.
// DON'T EVER KILL GEORGE!
- if (_scriptVars[ID] != 8) {
+ if (readVar(ID) != CUR_PLAYER_ID) {
// Need to call this in case it wasn't called in script!
fnAddToKillList(NULL);
}
@@ -2095,10 +2076,10 @@ int32 Logic::fnPauseForEvent(int32 *params) {
// params: 0 pointer to object's logic structure
// 1 number of game-cycles to pause
- ObjectLogic *ob_logic = (ObjectLogic *)decodePtr(params[0]);
+ ObjectLogic obLogic(decodePtr(params[0]));
if (checkEventWaiting()) {
- ob_logic->looping = 0;
+ obLogic.setLooping(0);
startEvent();
return IR_TERMINATE;
}
@@ -2109,7 +2090,7 @@ int32 Logic::fnPauseForEvent(int32 *params) {
int32 Logic::fnClearEvent(int32 *params) {
// params: none
- clearEvent(_scriptVars[ID]);
+ clearEvent(readVar(ID));
return IR_CONT;
}
@@ -2121,10 +2102,10 @@ int32 Logic::fnFaceMega(int32 *params) {
// 4 id of target mega to face
return _router->faceMega(
- (ObjectLogic *)decodePtr(params[0]),
- (ObjectGraphic *)decodePtr(params[1]),
- (ObjectMega *)decodePtr(params[2]),
- (ObjectWalkdata *)decodePtr(params[3]),
+ decodePtr(params[0]),
+ decodePtr(params[1]),
+ decodePtr(params[2]),
+ decodePtr(params[3]),
params[4]);
}
@@ -2163,7 +2144,7 @@ int32 Logic::fnPlaySequence(int32 *params) {
MoviePlayer player(_vm);
uint32 rv;
- if (_sequenceTextLines && !_scriptVars[DEMO])
+ if (_sequenceTextLines && !readVar(DEMO))
rv = player.play(filename, sequenceSpeechArray, _smackerLeadIn, _smackerLeadOut);
else
rv = player.play(filename, NULL, _smackerLeadIn, _smackerLeadOut);
@@ -2201,13 +2182,13 @@ int32 Logic::fnPlaySequence(int32 *params) {
int32 Logic::fnShadedSprite(int32 *params) {
// params: 0 pointer to object's graphic structure
- _router->setSpriteShading((ObjectGraphic *)decodePtr(params[0]), SHADED_SPRITE);
+ _router->setSpriteShading(decodePtr(params[0]), SHADED_SPRITE);
return IR_CONT;
}
int32 Logic::fnUnshadedSprite(int32 *params) {
// params: 0 pointer to object's graphic structure
- _router->setSpriteShading((ObjectGraphic *)decodePtr(params[0]), UNSHADED_SPRITE);
+ _router->setSpriteShading(decodePtr(params[0]), UNSHADED_SPRITE);
return IR_CONT;
}
@@ -2243,7 +2224,7 @@ int32 Logic::fnDisplayMsg(int32 *params) {
int32 Logic::fnSetObjectHeld(int32 *params) {
// params: 0 luggage icon to set
- uint32 res = (uint32) params[0];
+ uint32 res = (uint32)params[0];
_vm->_mouse->setObjectHeld(res);
return IR_CONT;
@@ -2271,16 +2252,11 @@ int32 Logic::fnResetGlobals(int32 *params) {
ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
- int32 size;
- uint32 *globals;
-
- size = _vm->_resman->fetchLen(1);
- size -= sizeof(StandardHeader);
+ byte *globals = _vm->_resman->openResource(1) + ResHeader::size();
+ int32 size = _vm->_resman->fetchLen(1) - ResHeader::size();
debug(5, "globals size: %d", size);
- globals = (uint32 *)((byte *)_vm->_resman->openResource(1) + sizeof(StandardHeader));
-
// blank each global variable
memset(globals, 0, size);
@@ -2384,7 +2360,7 @@ int32 Logic::fnCheckPlayerActivity(int32 *params) {
// params: 0 threshold delay in seconds, ie. what we want to
// check the actual delay against
- uint32 seconds = (uint32) params[0];
+ uint32 seconds = (uint32)params[0];
_vm->_mouse->checkPlayerActivity(seconds);
return IR_CONT;
@@ -2407,8 +2383,7 @@ int32 Logic::fnCheckMusicPlaying(int32 *params) {
// or 0 if no music playing
// in seconds, rounded up to the nearest second
- _scriptVars[RESULT] = _vm->_sound->musicTimeRemaining();
-
+ writeVar(RESULT, _vm->_sound->musicTimeRemaining());
return IR_CONT;
}
@@ -2418,7 +2393,7 @@ int32 Logic::fnPlayCredits(int32 *params) {
// params: none
- if (_scriptVars[DEMO]) {
+ if (readVar(DEMO)) {
_vm->closeGame();
return IR_STOP;
}
diff --git a/sword2/header.h b/sword2/header.h
index cf630397c6..c64b78263c 100644
--- a/sword2/header.h
+++ b/sword2/header.h
@@ -21,16 +21,14 @@
#ifndef _HEADER
#define _HEADER
+#include "common/stream.h"
+
namespace Sword2 {
//----------------------------------------------------------
// SYSTEM FILE & FRAME HEADERS
//----------------------------------------------------------
-#if !defined(__GNUC__)
- #pragma START_PACK_STRUCTS
-#endif
-
//----------------------------------------------------------
// ALL FILES
//----------------------------------------------------------
@@ -39,7 +37,7 @@ namespace Sword2 {
#define NAME_LEN 34
-struct StandardHeader {
+struct ResHeader {
uint8 fileType; // Byte to define file type (see below)
uint8 compType; // Type of file compression used ie.
// on whole file (see below)
@@ -49,7 +47,31 @@ struct StandardHeader {
// memory (NB. frames still held
// compressed)
byte name[NAME_LEN]; // Name of object
-} GCC_PACK;
+
+ static const int size() {
+ return 44;
+ }
+
+ void read(byte *addr) {
+ Common::MemoryReadStream readS(addr, size());
+
+ fileType = readS.readByte();
+ compType = readS.readByte();
+ compSize = readS.readUint32LE();
+ decompSize = readS.readUint32LE();
+ readS.read(name, NAME_LEN);
+ }
+
+ void write(byte *addr) {
+ Common::MemoryWriteStream writeS(addr, size());
+
+ writeS.writeByte(fileType);
+ writeS.writeByte(compType);
+ writeS.writeUint32LE(compSize);
+ writeS.writeUint32LE(decompSize);
+ writeS.write(name, NAME_LEN);
+ }
+};
// fileType
@@ -121,7 +143,40 @@ struct AnimHeader {
// place from the start)
uint8 feetEndDir; // Direction to start in after running anim
uint16 blend;
-} GCC_PACK;
+
+ static const int size() {
+ return 15;
+ }
+
+ void read(byte *addr) {
+ Common::MemoryReadStream readS(addr, size());
+
+ runTimeComp = readS.readByte();
+ noAnimFrames = readS.readUint16LE();
+ feetStartX = readS.readUint16LE();
+ feetStartY = readS.readUint16LE();
+ feetStartDir = readS.readByte();
+ feetEndX = readS.readUint16LE();
+ feetEndY = readS.readUint16LE();
+ feetEndDir = readS.readByte();
+ blend = readS.readUint16LE();
+ }
+
+ void write(byte *addr) {
+ Common::MemoryWriteStream writeS(addr, size());
+
+ writeS.writeByte(runTimeComp);
+ writeS.writeUint16LE(noAnimFrames);
+ writeS.writeUint16LE(feetStartX);
+ writeS.writeUint16LE(feetStartY);
+ writeS.writeByte(feetStartDir);
+ writeS.writeUint16LE(feetEndX);
+ writeS.writeUint16LE(feetEndY);
+ writeS.writeByte(feetEndDir);
+ writeS.writeUint16LE(blend);
+ }
+
+};
// runtimeComp - compression used on each frame of the anim
@@ -145,7 +200,29 @@ struct CdtEntry {
// of file header)
uint8 frameType; // 0 = print sprite normally with top-left
// corner at (x,y), otherwise see below...
-} GCC_PACK;
+
+ static const int size() {
+ return 9;
+ }
+
+ void read(byte *addr) {
+ Common::MemoryReadStream readS(addr, size());
+
+ x = readS.readUint16LE();
+ y = readS.readUint16LE();
+ frameOffset = readS.readUint32LE();
+ frameType = readS.readByte();
+ }
+
+ void write(byte *addr) {
+ Common::MemoryWriteStream writeS(addr, size());
+
+ writeS.writeUint16LE(x);
+ writeS.writeUint16LE(y);
+ writeS.writeUint32LE(frameOffset);
+ writeS.writeByte(frameType);
+ }
+};
// 'frameType' bit values
@@ -164,7 +241,27 @@ struct FrameHeader {
// type is now in Anim Header
uint16 width; // Dimensions of frame
uint16 height;
-} GCC_PACK;
+
+ static const int size() {
+ return 8;
+ }
+
+ void read(byte *addr) {
+ Common::MemoryReadStream readS(addr, size());
+
+ compSize = readS.readUint32LE();
+ width = readS.readUint16LE();
+ height = readS.readUint16LE();
+ }
+
+ void write(byte *addr) {
+ Common::MemoryWriteStream writeS(addr, size());
+
+ writeS.writeUint32LE(compSize);
+ writeS.writeUint16LE(width);
+ writeS.writeUint16LE(height);
+ }
+};
//----------------------------------------------------------
// (2) SCREEN FILES
@@ -193,7 +290,39 @@ struct MultiScreenHeader {
uint32 layers;
uint32 paletteTable;
uint32 maskOffset;
-} GCC_PACK;
+
+ static const int size() {
+ return 36;
+ }
+
+ void read(byte *addr) {
+ Common::MemoryReadStream readS(addr, size());
+
+ palette = readS.readUint32LE();
+ bg_parallax[0] = readS.readUint32LE();
+ bg_parallax[1] = readS.readUint32LE();
+ screen = readS.readUint32LE();
+ fg_parallax[0] = readS.readUint32LE();
+ fg_parallax[1] = readS.readUint32LE();
+ layers = readS.readUint32LE();
+ paletteTable = readS.readUint32LE();
+ maskOffset = readS.readUint32LE();
+ }
+
+ void write(byte *addr) {
+ Common::MemoryWriteStream writeS(addr, size());
+
+ writeS.writeUint32LE(palette);
+ writeS.writeUint32LE(bg_parallax[0]);
+ writeS.writeUint32LE(bg_parallax[1]);
+ writeS.writeUint32LE(screen);
+ writeS.writeUint32LE(fg_parallax[0]);
+ writeS.writeUint32LE(fg_parallax[1]);
+ writeS.writeUint32LE(layers);
+ writeS.writeUint32LE(paletteTable);
+ writeS.writeUint32LE(maskOffset);
+ }
+};
// Screen Header
@@ -201,7 +330,27 @@ struct ScreenHeader {
uint16 width; // dimensions of the background screen
uint16 height;
uint16 noLayers; // number of layer areas
-} GCC_PACK;
+
+ static const int size() {
+ return 6;
+ }
+
+ void read(byte *addr) {
+ Common::MemoryReadStream readS(addr, size());
+
+ width = readS.readUint16LE();
+ height = readS.readUint16LE();
+ noLayers = readS.readUint16LE();
+ }
+
+ void write(byte *addr) {
+ Common::MemoryWriteStream writeS(addr, size());
+
+ writeS.writeUint16LE(width);
+ writeS.writeUint16LE(height);
+ writeS.writeUint16LE(noLayers);
+ }
+};
// Layer Header
@@ -216,7 +365,33 @@ struct LayerHeader {
uint32 maskSize;
uint32 offset; // where to find mask data (from start of
// standard file header)
-} GCC_PACK;
+
+ static const int size() {
+ return 16;
+ }
+
+ void read(byte *addr) {
+ Common::MemoryReadStream readS(addr, size());
+
+ x = readS.readUint16LE();
+ y = readS.readUint16LE();
+ width = readS.readUint16LE();
+ height = readS.readUint16LE();
+ maskSize = readS.readUint32LE();
+ offset = readS.readUint32LE();
+ }
+
+ void write(byte *addr) {
+ Common::MemoryWriteStream writeS(addr, size());
+
+ writeS.writeUint16LE(x);
+ writeS.writeUint16LE(y);
+ writeS.writeUint16LE(width);
+ writeS.writeUint16LE(height);
+ writeS.writeUint32LE(maskSize);
+ writeS.writeUint32LE(offset);
+ }
+};
//----------------------------------------------------------
// (3) SCRIPT OBJECT FILES
@@ -228,22 +403,6 @@ struct LayerHeader {
// script object data
//----------------------------------------------------------
-// (4) WALK-GRID FILES
-//----------------------------------------------------------
-// a walk-grid file consists of:
-//
-// standard file header
-// walk-grid file header
-// walk-grid data
-
-// Walk-Grid Header - taken directly from old "header.h" in STD_INC
-
-struct WalkGridHeader {
- int32 numBars; // number of bars on the floor
- int32 numNodes; // number of nodes
-} GCC_PACK;
-
-//----------------------------------------------------------
// (5) PALETTE FILES
//----------------------------------------------------------
// a palette file consists of:
@@ -254,35 +413,89 @@ struct WalkGridHeader {
// an object hub - which represents all that remains of the compact concept
-#define TREE_SIZE 3
-
-struct ObjectHub {
- int32 type; // type of object
- uint32 logic_level; // what level?
- uint32 logic[TREE_SIZE]; // NOT USED
- uint32 script_id[TREE_SIZE]; // need this if script
- uint32 script_pc[TREE_SIZE]; // need this also
-} GCC_PACK;
+class ObjectHub {
+ // int32 type; // type of object
+ // uint32 logic_level; // what level?
+ // uint32 logic[3] // NOT USED
+ // uint32 script_id[3] // need this if script
+ // uint32 script_pc[3] // need this also
+
+private:
+ byte *_addr;
+
+public:
+ ObjectHub() {
+ _addr = NULL;
+ }
+
+ static const int size() {
+ return 44;
+ }
+
+ byte *data() {
+ return _addr;
+ }
+
+ void setAddress(byte *addr) {
+ _addr = addr;
+ }
+
+ byte *getScriptPcPtr(int level) {
+ return _addr + 32 + 4 * level;
+ }
+
+ uint32 getLogicLevel() {
+ return READ_LE_UINT32(_addr + 4);
+ }
+ uint32 getScriptId(int level) {
+ return READ_LE_UINT32(_addr + 20 + 4 * level);
+ }
+ uint32 getScriptPc(int level) {
+ return READ_LE_UINT32(_addr + 32 + 4 * level);
+ }
+
+ void setLogicLevel(uint32 x) {
+ WRITE_LE_UINT32(_addr + 4, x);
+ }
+ void setScriptId(int level, uint32 x) {
+ WRITE_LE_UINT32(_addr + 20 + 4 * level, x);
+ }
+ void setScriptPc(int level, uint32 x) {
+ WRITE_LE_UINT32(_addr + 32 + 4 * level, x);
+ }
+};
// (6) text module header
struct TextHeader {
uint32 noOfLines; // how many lines of text are there in this
// module
-} GCC_PACK;
+
+ static const int size() {
+ return 4;
+ }
+
+ void read(byte *addr) {
+ Common::MemoryReadStream readS(addr, size());
+
+ noOfLines = readS.readUint32LE();
+ }
+
+ void write(byte *addr) {
+ Common::MemoryWriteStream writeS(addr, size());
+
+ writeS.writeUint32LE(noOfLines);
+ }
+};
// a text file has:
//
-// StandardHeader
+// ResHeader
// TextHeader
// look up table, to
// line of text,0
// line of text,0
-#if !defined(__GNUC__)
- #pragma END_PACK_STRUCTS
-#endif
-
} // End of namespace Sword2
#endif
diff --git a/sword2/icons.cpp b/sword2/icons.cpp
index 2e6eaedd32..cb44f46697 100644
--- a/sword2/icons.cpp
+++ b/sword2/icons.cpp
@@ -19,6 +19,7 @@
*/
#include "common/stdafx.h"
+#include "common/stream.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
#include "sword2/logic.h"
@@ -27,14 +28,20 @@
namespace Sword2 {
-void Mouse::addMenuObject(MenuObject *obj) {
+void Mouse::addMenuObject(byte *ptr) {
assert(_totalTemp < TOTAL_engine_pockets);
- memcpy(&_tempList[_totalTemp], obj, sizeof(MenuObject));
+
+ Common::MemoryReadStream readS(ptr, 2 * sizeof(int32));
+
+ _tempList[_totalTemp].icon_resource = readS.readSint32LE();
+ _tempList[_totalTemp].luggage_resource = readS.readSint32LE();
_totalTemp++;
}
void Mouse::addSubject(int32 id, int32 ref) {
- if (Logic::_scriptVars[IN_SUBJECT] == 0) {
+ uint32 in_subject = _vm->_logic->readVar(IN_SUBJECT);
+
+ if (in_subject == 0) {
// This is the start of the new subject list. Set the default
// repsonse id to zero in case we're never passed one.
_defaultResponseId = 0;
@@ -48,9 +55,9 @@ void Mouse::addSubject(int32 id, int32 ref) {
_defaultResponseId = ref;
} else {
debug(5, "fnAddSubject res %d, uid %d", id, ref);
- _subjectList[Logic::_scriptVars[IN_SUBJECT]].res = id;
- _subjectList[Logic::_scriptVars[IN_SUBJECT]].ref = ref;
- Logic::_scriptVars[IN_SUBJECT]++;
+ _subjectList[in_subject].res = id;
+ _subjectList[in_subject].ref = ref;
+ _vm->_logic->writeVar(IN_SUBJECT, in_subject + 1);
}
}
@@ -72,10 +79,7 @@ void Mouse::buildMenu() {
// Run the 'build_menu' script in the 'menu_master' object. This will
// register all carried menu objects.
- uint32 null_pc = 0;
- char *menuScript = (char *)_vm->_resman->openResource(MENU_MASTER_OBJECT);
- _vm->_logic->runScript(menuScript, menuScript, &null_pc);
- _vm->_resman->closeResource(MENU_MASTER_OBJECT);
+ _vm->_logic->runResScript(MENU_MASTER_OBJECT, 0);
// Create a new master list based on the old master inventory list and
// the new temporary inventory list. The purpose of all this is, as
@@ -139,23 +143,26 @@ void Mouse::buildMenu() {
if (res) {
bool icon_coloured;
+ uint32 object_held = _vm->_logic->readVar(OBJECT_HELD);
+ uint32 combine_base = _vm->_logic->readVar(COMBINE_BASE);
+
if (_examiningMenuIcon) {
// When examining an object, that object is
// coloured. The rest are greyed out.
- icon_coloured = (res == Logic::_scriptVars[OBJECT_HELD]);
- } else if (Logic::_scriptVars[COMBINE_BASE]) {
+ icon_coloured = (res == object_held);
+ } else if (combine_base) {
// When combining two menu object (i.e. using
// one on another), both are coloured. The rest
// are greyed out.
- icon_coloured = (res == Logic::_scriptVars[OBJECT_HELD] || res == Logic::_scriptVars[COMBINE_BASE]);
+ icon_coloured = (res == object_held || combine_base);
} else {
// If an object is selected but we are not yet
// doing anything with it, the selected object
// is greyed out. The rest are coloured.
- icon_coloured = (res != Logic::_scriptVars[OBJECT_HELD]);
+ icon_coloured = (res != object_held);
}
- icon = _vm->_resman->openResource(res) + sizeof(StandardHeader);
+ icon = _vm->_resman->openResource(res) + ResHeader::size();
// The coloured icon is stored directly after the
// greyed out one.
@@ -190,12 +197,12 @@ void Mouse::buildSystemMenu() {
// rest will grey out.
for (int i = 0; i < ARRAYSIZE(icon_list); i++) {
- byte *icon = _vm->_resman->openResource(icon_list[i]) + sizeof(StandardHeader);
+ byte *icon = _vm->_resman->openResource(icon_list[i]) + ResHeader::size();
// The only case when an icon is grayed is when the player
// is dead. Then SAVE is not available.
- if (!Logic::_scriptVars[DEAD] || icon_list[i] != SAVE_ICON)
+ if (!_vm->_logic->readVar(DEAD) || icon_list[i] != SAVE_ICON)
icon += (RDMENU_ICONWIDE * RDMENU_ICONDEEP);
setMenuIcon(RDMENU_TOP, i, icon);
diff --git a/sword2/icons.h b/sword2/icons.h
index 84b308a3a9..ae37974036 100644
--- a/sword2/icons.h
+++ b/sword2/icons.h
@@ -29,19 +29,11 @@ namespace Sword2 {
// define these in a script and then register them with the system
-#if !defined(__GNUC__)
- #pragma START_PACK_STRUCTS
-#endif
-
struct MenuObject {
int32 icon_resource; // icon graphic graphic
int32 luggage_resource; // luggage icon resource (for attaching to
// mouse pointer)
-} GCC_PACK;
-
-#if !defined(__GNUC__)
- #pragma END_PACK_STRUCTS
-#endif
+};
} // End of namespace Sword2
diff --git a/sword2/interpreter.cpp b/sword2/interpreter.cpp
index ea57ae1c89..278834c578 100644
--- a/sword2/interpreter.cpp
+++ b/sword2/interpreter.cpp
@@ -25,6 +25,7 @@
#include "sword2/interpreter.h"
#include "sword2/logic.h"
#include "sword2/memory.h"
+#include "sword2/resman.h"
namespace Sword2 {
@@ -205,18 +206,58 @@ do { \
#define pop() (assert(stackPtr < ARRAYSIZE(stack)), stack[--stackPtr])
-uint32 *Logic::_scriptVars = NULL;
+int Logic::runResScript(uint32 scriptRes, uint32 offset) {
+ byte *scriptAddr;
+ int result;
-int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
+ scriptAddr = _vm->_resman->openResource(scriptRes);
+ result = runScript(scriptAddr, scriptAddr, offset);
+ _vm->_resman->closeResource(scriptRes);
+
+ return result;
+}
+
+int Logic::runResObjScript(uint32 scriptRes, uint32 objRes, uint32 offset) {
+ byte *scriptAddr, *objAddr;
+ int result;
+
+ scriptAddr = _vm->_resman->openResource(scriptRes);
+ objAddr = _vm->_resman->openResource(objRes);
+ result = runScript(scriptAddr, objAddr, offset);
+ _vm->_resman->closeResource(objRes);
+ _vm->_resman->closeResource(scriptRes);
+
+ return result;
+}
+
+int Logic::runScript(byte *scriptData, byte *objectData, uint32 offset) {
+ byte pc[4];
+
+ WRITE_LE_UINT32(pc, offset);
+ return runScript2(scriptData, objectData, pc);
+}
+
+// This form of the runScript function is only called directly from
+// the processSession() function, which uses it to update the script PC in the
+// current object hub. For reasons which I do not understand, I couldn't get it
+// to work if I called the function first with a dummy offset variable, and
+// and then updated the object hub myself.
+
+int Logic::runScript2(byte *scriptData, byte *objectData, byte *offsetPtr) {
// Interestingly, unlike our BASS engine the stack is a local variable.
- // This has some interesting implications which may or may not be
- // necessary to the BS2 engine.
+ // I don't know whether or not this is relevant to the working of the
+ // BS2 engine.
int32 stack[STACK_SIZE];
int32 stackPtr = 0;
- StandardHeader *header = (StandardHeader *)scriptData;
- scriptData += sizeof(StandardHeader) + sizeof(ObjectHub);
+ uint32 offset = READ_LE_UINT32(offsetPtr);
+
+ ResHeader header;
+
+ header.read(scriptData);
+
+ scriptData += ResHeader::size() + ObjectHub::size();
// The script data format:
// int32_TYPE 1 Size of variable space in bytes
@@ -231,25 +272,25 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
// Get the start of variables and start of code
- uint32 *localVars = (uint32 *)(scriptData + sizeof(int32));
- char *code = scriptData + READ_LE_UINT32(scriptData) + sizeof(int32);
+ byte *localVars = scriptData + 4;
+ byte *code = scriptData + READ_LE_UINT32(scriptData) + 4;
uint32 noScripts = READ_LE_UINT32(code);
- code += sizeof(int32);
+ code += 4;
- const uint32 *offsetTable = (const uint32 *)code;
+ byte *offsetTable = code;
- if (*offset < noScripts) {
- ip = FROM_LE_32(offsetTable[*offset]);
- scriptNumber = *offset;
- debug(4, "Start script %d with offset %d", *offset, ip);
+ if (offset < noScripts) {
+ ip = READ_LE_UINT32(offsetTable + offset * 4);
+ scriptNumber = offset;
+ debug(4, "Start script %d with offset %d", offset, ip);
} else {
uint i;
- ip = *offset;
+ ip = offset;
for (i = 1; i < noScripts; i++) {
- if (FROM_LE_32(offsetTable[i]) >= ip)
+ if (READ_LE_UINT32(offsetTable + 4 * i) >= ip)
break;
}
@@ -265,23 +306,23 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
bool checkElevatorBug = false;
if (scriptNumber == 2) {
- if (strcmp((char *)header->name, "mop_73") == 0)
+ if (strcmp((char *)header.name, "mop_73") == 0)
checkMopBug = true;
- else if (strcmp((char *)header->name, "titipoco_81") == 0)
+ else if (strcmp((char *)header.name, "titipoco_81") == 0)
checkPyramidBug = true;
- else if (strcmp((char *)header->name, "lift_82") == 0)
+ else if (strcmp((char *)header.name, "lift_82") == 0)
checkElevatorBug = true;
}
- code += noScripts * sizeof(int32);
+ code += noScripts * 4;
// Code should now be pointing at an identifier and a checksum
- const char *checksumBlock = code;
+ byte *checksumBlock = code;
- code += sizeof(int32) * 3;
+ code += 4 * 3;
if (READ_LE_UINT32(checksumBlock) != 12345678) {
- error("Invalid script in object %s", header->name);
+ error("Invalid script in object %s", header.name);
return 0;
}
@@ -291,8 +332,8 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
for (int i = 0; i < codeLen; i++)
checksum += (unsigned char) code[i];
- if (checksum != (int32) READ_LE_UINT32(checksumBlock + 8)) {
- debug(1, "Checksum error in object %s", header->name);
+ if (checksum != (int32)READ_LE_UINT32(checksumBlock + 8)) {
+ debug(1, "Checksum error in object %s", header.name);
// This could be bad, but there has been a report about someone
// who had problems running the German version because of
// checksum errors. Could there be a version where checksums
@@ -341,9 +382,9 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
// So if his click hander finishes, and variable 913 is
// 1, we set it back to 0 manually.
- if (checkPyramidBug && _scriptVars[913] == 1) {
+ if (checkPyramidBug && readVar(913) == 1) {
warning("Working around pyramid bug: Resetting Titipoco's state");
- _scriptVars[913] = 0;
+ writeVar(913, 0);
}
// WORKAROUND: The not-so-known-but-should-be-dreaded
@@ -354,7 +395,7 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
// examining it, the mouse cursor is removed but never
// restored.
- if (checkElevatorBug && Logic::_scriptVars[RIGHT_BUTTON]) {
+ if (checkElevatorBug && readVar(RIGHT_BUTTON)) {
warning("Working around elevator bug: Restoring mouse pointer");
fnAddHuman(NULL);
}
@@ -363,7 +404,7 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
break;
case CP_QUIT:
// Quit out for a cycle
- *offset = ip;
+ WRITE_LE_UINT32(offsetPtr, ip);
debug(9, "CP_QUIT");
return 0;
case CP_TERMINATE:
@@ -388,16 +429,14 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
case CP_PUSH_LOCAL_VAR32:
// Push the contents of a local variable
Read16ip(parameter);
- parameter /= 4;
- push(localVars[parameter]);
- debug(9, "CP_PUSH_LOCAL_VAR32: localVars[%d] => %d", parameter, localVars[parameter]);
+ push(READ_LE_UINT32(localVars + parameter));
+ debug(9, "CP_PUSH_LOCAL_VAR32: localVars[%d] => %d", parameter / 4, READ_LE_UINT32(localVars + parameter));
break;
case CP_PUSH_GLOBAL_VAR32:
// Push a global variable
- assert(_scriptVars);
Read16ip(parameter);
- push(_scriptVars[parameter]);
- debug(9, "CP_PUSH_GLOBAL_VAR32: scriptVars[%d] => %d", parameter, _scriptVars[parameter]);
+ push(readVar(parameter));
+ debug(9, "CP_PUSH_GLOBAL_VAR32: scriptVars[%d] => %d", parameter, readVar(parameter));
break;
case CP_PUSH_LOCAL_ADDR:
// Push the address of a local variable
@@ -410,10 +449,8 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
// CP_PUSH_DEREFERENCED_STRUCTURE opcode.
Read16ip(parameter);
- parameter /= 4;
- ptr = (byte *)&localVars[parameter];
- push_ptr(ptr);
- debug(9, "CP_PUSH_LOCAL_ADDR: &localVars[%d] => %p", parameter, ptr);
+ push_ptr(localVars + parameter);
+ debug(9, "CP_PUSH_LOCAL_ADDR: &localVars[%d] => %p", parameter / 4, localVars + parameter);
break;
case CP_PUSH_STRING:
// Push the address of a string on to the stack
@@ -421,7 +458,7 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
Read8ip(parameter);
// ip now points to the string
- ptr = (byte *)(code + ip);
+ ptr = code + ip;
push_ptr(ptr);
debug(9, "CP_PUSH_STRING: \"%s\"", ptr);
ip += (parameter + 1);
@@ -429,17 +466,16 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
case CP_PUSH_DEREFERENCED_STRUCTURE:
// Push the address of a dereferenced structure
Read32ip(parameter);
- ptr = (byte *)(objectData + sizeof(int32) + sizeof(StandardHeader) + sizeof(ObjectHub) + parameter);
+ ptr = objectData + 4 + ResHeader::size() + ObjectHub::size() + parameter;
push_ptr(ptr);
debug(9, "CP_PUSH_DEREFERENCED_STRUCTURE: %d => %p", parameter, ptr);
break;
case CP_POP_LOCAL_VAR32:
// Pop a value into a local word variable
Read16ip(parameter);
- parameter /= 4;
value = pop();
- localVars[parameter] = value;
- debug(9, "CP_POP_LOCAL_VAR32: localVars[%d] = %d", parameter, value);
+ WRITE_LE_UINT32(localVars + parameter, value);
+ debug(9, "CP_POP_LOCAL_VAR32: localVars[%d] = %d", parameter / 4, value);
break;
case CP_POP_GLOBAL_VAR32:
// Pop a global variable
@@ -472,41 +508,39 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
// use that as the signal that Nico's state needs to be
// updated as well.
- if (checkMopBug && parameter == 1017 && _scriptVars[1003] != 2) {
+ if (checkMopBug && parameter == 1017 && readVar(1003) != 2) {
warning("Working around mop bug: Setting Nico's state");
- _scriptVars[1003] = 2;
+ writeVar(1003, 2);
}
- _scriptVars[parameter] = value;
+ writeVar(parameter, value);
debug(9, "CP_POP_GLOBAL_VAR32: scriptsVars[%d] = %d", parameter, value);
break;
case CP_ADDNPOP_LOCAL_VAR32:
Read16ip(parameter);
- parameter /= 4;
- value = pop();
- localVars[parameter] += value;
- debug(9, "CP_ADDNPOP_LOCAL_VAR32: localVars[%d] += %d => %d", parameter, value, localVars[parameter]);
+ value = READ_LE_UINT32(localVars + parameter) + pop();
+ WRITE_LE_UINT32(localVars + parameter, value);
+ debug(9, "CP_ADDNPOP_LOCAL_VAR32: localVars[%d] => %d", parameter / 4, value);
break;
case CP_SUBNPOP_LOCAL_VAR32:
Read16ip(parameter);
- parameter /= 4;
- value = pop();
- localVars[parameter] -= value;
- debug(9, "CP_SUBNPOP_LOCAL_VAR32: localVars[%d] -= %d => %d", parameter, value, localVars[parameter]);
+ value = READ_LE_UINT32(localVars + parameter) - pop();
+ WRITE_LE_UINT32(localVars + parameter, value);
+ debug(9, "CP_SUBNPOP_LOCAL_VAR32: localVars[%d] => %d", parameter / 4, value);
break;
case CP_ADDNPOP_GLOBAL_VAR32:
// Add and pop a global variable
Read16ip(parameter);
- value = pop();
- _scriptVars[parameter] += value;
- debug(9, "CP_ADDNPOP_GLOBAL_VAR32: scriptVars[%d] += %d => %d", parameter, value, _scriptVars[parameter]);
+ value = readVar(parameter) + pop();
+ writeVar(parameter, value);
+ debug(9, "CP_ADDNPOP_GLOBAL_VAR32: scriptVars[%d] => %d", parameter, value);
break;
case CP_SUBNPOP_GLOBAL_VAR32:
// Sub and pop a global variable
Read16ip(parameter);
- value = pop();
- _scriptVars[parameter] -= value;
- debug(9, "CP_SUBNPOP_GLOBAL_VAR32: scriptVars[%d] -= %d => %d", parameter, value, _scriptVars[parameter]);
+ value = readVar(parameter) - pop();
+ writeVar(parameter, value);
+ debug(9, "CP_SUBNPOP_GLOBAL_VAR32: scriptVars[%d] => %d", parameter, value);
break;
// Jump opcodes
@@ -516,7 +550,7 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
Read32ipLeaveip(parameter);
value = pop();
if (!value) {
- ip += sizeof(int32);
+ ip += 4;
debug(9, "CP_SKIPONTRUE: %d (IS FALSE (NOT SKIPPED))", parameter);
} else {
ip += parameter;
@@ -528,7 +562,7 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
Read32ipLeaveip(parameter);
value = pop();
if (value) {
- ip += sizeof(int32);
+ ip += 4;
debug(9, "CP_SKIPONFALSE: %d (IS TRUE (NOT SKIPPED))", parameter);
} else {
ip += parameter;
@@ -549,13 +583,13 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
// Search the cases
foundCase = false;
for (i = 0; i < caseCount && !foundCase; i++) {
- if (value == (int32) READ_LE_UINT32(code + ip)) {
+ if (value == (int32)READ_LE_UINT32(code + ip)) {
// We have found the case, so lets
// jump to it
foundCase = true;
- ip += READ_LE_UINT32(code + ip + sizeof(int32));
+ ip += READ_LE_UINT32(code + ip + 4);
} else
- ip += sizeof(int32) * 2;
+ ip += 4 * 2;
}
// If we found no matching case then use the default
@@ -585,7 +619,7 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
switch (retVal & 7) {
case IR_STOP:
// Quit out for a cycle
- *offset = ip;
+ WRITE_LE_UINT32(offsetPtr, ip);
return 0;
case IR_CONT:
// Continue as normal
@@ -596,11 +630,11 @@ int Logic::runScript(char *scriptData, char *objectData, uint32 *offset) {
case IR_REPEAT:
// Return setting offset to start of this
// function call
- *offset = savedStartOfMcode;
+ WRITE_LE_UINT32(offsetPtr, savedStartOfMcode);
return 0;
case IR_GOSUB:
// that's really neat
- *offset = ip;
+ WRITE_LE_UINT32(offsetPtr, ip);
return 2;
default:
error("Bad return code (%d) from '%s'", retVal & 7, opcodes[parameter].desc);
diff --git a/sword2/interpreter.h b/sword2/interpreter.h
index e42e1c1647..c3c05119df 100644
--- a/sword2/interpreter.h
+++ b/sword2/interpreter.h
@@ -36,10 +36,10 @@ enum {
// Get parameter fix so that the playstation version can handle words not on
// word boundaries
-#define Read8ip(var) { var = *((const int8 *)(code + ip)); ip++; }
-#define Read16ip(var) { var = (int16) READ_LE_UINT16(code + ip); ip += sizeof(int16); }
-#define Read32ip(var) { var = (int32) READ_LE_UINT32(code + ip); ip += sizeof(int32); }
-#define Read32ipLeaveip(var) { var = (int32) READ_LE_UINT32(code + ip); }
+#define Read8ip(var) { var = code[ip]; ip++; }
+#define Read16ip(var) { var = (int16)READ_LE_UINT16(code + ip); ip += 2; }
+#define Read32ip(var) { var = (int32)READ_LE_UINT32(code + ip); ip += 4; }
+#define Read32ipLeaveip(var) { var = (int32)READ_LE_UINT32(code + ip); }
enum {
// Compiled tokens
diff --git a/sword2/layers.cpp b/sword2/layers.cpp
index 968ee8f621..623eecec14 100644
--- a/sword2/layers.cpp
+++ b/sword2/layers.cpp
@@ -52,7 +52,7 @@ void Screen::initBackground(int32 res, int32 new_palette) {
_vm->_sound->clearFxQueue();
waitForFade();
- debug(1, "CHANGED TO LOCATION \"%s\"", _vm->fetchObjectName(res, buf));
+ debug(1, "CHANGED TO LOCATION \"%s\"", _vm->_resman->fetchName(res, buf));
// if last screen was using a shading mask (see below)
if (_thisScreen.mask_flag) {
@@ -72,36 +72,40 @@ void Screen::initBackground(int32 res, int32 new_palette) {
// each cycle
byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id);
- ScreenHeader *screen_head = _vm->fetchScreenHeader(file);
+ ScreenHeader screen_head;
+
+ screen_head.read(_vm->fetchScreenHeader(file));
// set number of special sort layers
- _thisScreen.number_of_layers = screen_head->noLayers;
- _thisScreen.screen_wide = screen_head->width;
- _thisScreen.screen_deep = screen_head->height;
+ _thisScreen.number_of_layers = screen_head.noLayers;
+ _thisScreen.screen_wide = screen_head.width;
+ _thisScreen.screen_deep = screen_head.height;
- debug(2, "layers=%d width=%d depth=%d", screen_head->noLayers, screen_head->width, screen_head->height);
+ debug(2, "layers=%d width=%d depth=%d", screen_head.noLayers, screen_head.width, screen_head.height);
// initialise the driver back buffer
- setLocationMetrics(screen_head->width, screen_head->height);
+ setLocationMetrics(screen_head.width, screen_head.height);
- for (i = 0; i < screen_head->noLayers; i++) {
+ for (i = 0; i < screen_head.noLayers; i++) {
debug(3, "init layer %d", i);
- LayerHeader *layer = _vm->fetchLayerHeader(file, i);
+ LayerHeader layer;
+
+ layer.read(_vm->fetchLayerHeader(file, i));
// Add the layer to the sort list. We only provide just enough
// information so that it's clear that it's a layer, and where
// to sort it in relation to other things in the list.
_sortList[i].layer_number = i + 1;
- _sortList[i].sort_y = layer->y + layer->height;
+ _sortList[i].sort_y = layer.y + layer.height;
}
// reset scroll offsets
_thisScreen.scroll_offset_x = 0;
_thisScreen.scroll_offset_y = 0;
- if (screen_head->width > _screenWide || screen_head->height > _screenDeep) {
+ if (screen_head.width > _screenWide || screen_head.height > _screenDeep) {
// The layer is larger than the physical screen. Switch on
// scrolling. (2 means first time on screen)
_thisScreen.scroll_flag = 2;
@@ -112,8 +116,8 @@ void Screen::initBackground(int32 res, int32 new_palette) {
// Calculate the maximum scroll offsets to prevent scrolling
// off the edge. The minimum offsets are both 0.
- _thisScreen.max_scroll_offset_x = screen_head->width - _screenWide;
- _thisScreen.max_scroll_offset_y = screen_head->height - (_screenDeep - (MENUDEEP * 2));
+ _thisScreen.max_scroll_offset_x = screen_head.width - _screenWide;
+ _thisScreen.max_scroll_offset_y = screen_head.height - (_screenDeep - (MENUDEEP * 2));
} else {
// The later fits on the phyiscal screen. Switch off scrolling.
_thisScreen.scroll_flag = 0;
@@ -129,15 +133,17 @@ void Screen::initBackground(int32 res, int32 new_palette) {
// shading mask
- MultiScreenHeader *screenLayerTable = (MultiScreenHeader *)(file + sizeof(StandardHeader));
+ MultiScreenHeader screenLayerTable;
+
+ screenLayerTable.read(file + ResHeader::size());
- if (screenLayerTable->maskOffset) {
+ if (screenLayerTable.maskOffset) {
SpriteInfo spriteInfo;
spriteInfo.x = 0;
spriteInfo.y = 0;
- spriteInfo.w = screen_head->width;
- spriteInfo.h = screen_head->height;
+ spriteInfo.w = screen_head.width;
+ spriteInfo.h = screen_head.height;
spriteInfo.scale = 0;
spriteInfo.scaledWidth = 0;
spriteInfo.scaledHeight = 0;
@@ -159,7 +165,7 @@ void Screen::initBackground(int32 res, int32 new_palette) {
// Background parallax layers
for (i = 0; i < 2; i++) {
- if (screenLayerTable->bg_parallax[i])
+ if (screenLayerTable.bg_parallax[i])
initialiseBackgroundLayer(_vm->fetchBackgroundParallaxLayer(file, i));
else
initialiseBackgroundLayer(NULL);
@@ -172,7 +178,7 @@ void Screen::initBackground(int32 res, int32 new_palette) {
// Foreground parallax layers
for (i = 0; i < 2; i++) {
- if (screenLayerTable->fg_parallax[i])
+ if (screenLayerTable.fg_parallax[i])
initialiseBackgroundLayer(_vm->fetchForegroundParallaxLayer(file, i));
else
initialiseBackgroundLayer(NULL);
diff --git a/sword2/logic.cpp b/sword2/logic.cpp
index 51185a5373..c25ef8270f 100644
--- a/sword2/logic.cpp
+++ b/sword2/logic.cpp
@@ -26,8 +26,6 @@
#include "sword2/router.h"
#include "sword2/sound.h"
-#define LEVEL (_curObjectHub->logic_level)
-
namespace Sword2 {
Logic::Logic(Sword2Engine *vm) :
@@ -60,34 +58,37 @@ int Logic::processSession() {
// processing on the current list
while (_pc != 0xffffffff) {
- uint32 ret, script;
- char *raw_script_ad;
+ byte *game_object_list, *head, *raw_script_ad, *raw_data_ad;
+ uint32 level, ret, script, id;
- StandardHeader *head = (StandardHeader *)_vm->_resman->openResource(run_list);
- assert(head->fileType == RUN_LIST);
+ game_object_list = _vm->_resman->openResource(run_list) + ResHeader::size();
- uint32 *game_object_list = (uint32 *)(head + 1);
+ assert(_vm->_resman->fetchType(run_list) == RUN_LIST);
// read the next id
- uint id = game_object_list[_pc++];
- _scriptVars[ID] = id;
+ id = READ_LE_UINT32(game_object_list + 4 * _pc);
+ _pc++;
+
+ writeVar(ID, id);
_vm->_resman->closeResource(run_list);
- if (!_scriptVars[ID]) {
+ if (!id) {
// End of list - end the session naturally
return 0;
}
- head = (StandardHeader *)_vm->_resman->openResource(_scriptVars[ID]);
- assert(head->fileType == GAME_OBJECT);
+ assert(_vm->_resman->fetchType(id) == GAME_OBJECT);
+
+ head = _vm->_resman->openResource(id);
+ _curObjectHub.setAddress(head + ResHeader::size());
- _curObjectHub = (ObjectHub *)(head + 1);
+ level = _curObjectHub.getLogicLevel();
debug(5, "Level %d id(%d) pc(%d)",
- LEVEL,
- _curObjectHub->script_id[LEVEL],
- _curObjectHub->script_pc[LEVEL]);
+ level,
+ _curObjectHub.getScriptId(level),
+ _curObjectHub.getScriptPc(level));
// Do the logic for this object. We keep going until a function
// says to stop - remember, system operations are run via
@@ -97,32 +98,34 @@ int Logic::processSession() {
// There is a distinction between running one of our
// own scripts and that of another object.
- script = _curObjectHub->script_id[LEVEL];
+ level = _curObjectHub.getLogicLevel();
+ script = _curObjectHub.getScriptId(level);
- if (script / SIZE == _scriptVars[ID]) {
+ if (script / SIZE == readVar(ID)) {
// It's our own script
debug(5, "Run script %d pc=%d",
script / SIZE,
- _curObjectHub->script_pc[LEVEL]);
+ _curObjectHub.getScriptPc(level));
// This is the script data. Script and data
// object are the same.
- raw_script_ad = (char *)head;
+ raw_script_ad = head;
- ret = runScript(raw_script_ad, raw_script_ad, &_curObjectHub->script_pc[LEVEL]);
+ ret = runScript2(raw_script_ad, raw_script_ad, _curObjectHub.getScriptPcPtr(level));
} else {
// We're running the script of another game
// object - get our data object address.
- StandardHeader *far_head = (StandardHeader *)_vm->_resman->openResource(script / SIZE);
- assert(far_head->fileType == GAME_OBJECT || far_head->fileType == SCREEN_MANAGER);
+ uint8 type = _vm->_resman->fetchType(script / SIZE);
- raw_script_ad = (char *)far_head;
- char *raw_data_ad = (char *)head;
+ assert(type == GAME_OBJECT || type == SCREEN_MANAGER);
- ret = runScript(raw_script_ad, raw_data_ad, &_curObjectHub->script_pc[LEVEL]);
+ raw_script_ad = _vm->_resman->openResource(script / SIZE);
+ raw_data_ad = head;
+
+ ret = runScript2(raw_script_ad, raw_data_ad, _curObjectHub.getScriptPcPtr(level));
_vm->_resman->closeResource(script / SIZE);
@@ -131,10 +134,12 @@ int Logic::processSession() {
}
if (ret == 1) {
+ level = _curObjectHub.getLogicLevel();
+
// The script finished - drop down a level
- if (LEVEL)
- LEVEL--;
- else {
+ if (level) {
+ _curObjectHub.setLogicLevel(level - 1);
+ } else {
// Hmmm, level 0 terminated :-| Let's
// be different this time and simply
// let it restart next go :-)
@@ -145,7 +150,7 @@ int Logic::processSession() {
debug(5, "object %d script 0 terminated!", id);
// reset to rerun, drop out for a cycle
- _curObjectHub->script_pc[LEVEL] = _curObjectHub->script_id[LEVEL] & 0xffff;
+ _curObjectHub.setScriptPc(level, _curObjectHub.getScriptId(level) & 0xffff);
ret = 0;
}
} else if (ret > 2) {
@@ -163,18 +168,17 @@ int Logic::processSession() {
// Clear any syncs that were waiting for this character - it
// has used them or now looses them
- clearSyncs(_scriptVars[ID]);
+ clearSyncs(readVar(ID));
if (_pc != 0xffffffff) {
// The session is still valid so run the graphics/mouse
// service script
- uint32 null_pc = 0;
- runScript(raw_script_ad, raw_script_ad, &null_pc);
+ runScript(raw_script_ad, raw_script_ad, 0);
}
// and that's it so close the object resource
- _vm->_resman->closeResource(_scriptVars[ID]);
+ _vm->_resman->closeResource(readVar(ID));
}
// Leaving a room so remove all ids that must reboot correctly. Then
@@ -198,7 +202,7 @@ void Logic::expressChangeSession(uint32 sesh_id) {
_pc = 0xffffffff;
// Reset now in case we double-clicked an exit prior to changing screen
- _scriptVars[EXIT_FADING] = 0;
+ writeVar(EXIT_FADING, 0);
// We're trashing the list - presumably to change room. In theory,
// sync waiting in the list could be left behind and never removed -
@@ -228,9 +232,9 @@ void Logic::logicUp(uint32 new_script) {
debug(5, "new pc = %d", new_script & 0xffff);
// going up a level - and we'll keep going this cycle
- LEVEL++;
+ _curObjectHub.setLogicLevel(_curObjectHub.getLogicLevel() + 1);
- assert(LEVEL < 3); // Can be 0, 1, 2
+ assert(_curObjectHub.getLogicLevel() < 3); // Can be 0, 1, 2
logicReplace(new_script);
}
@@ -239,7 +243,7 @@ void Logic::logicUp(uint32 new_script) {
*/
void Logic::logicOne(uint32 new_script) {
- LEVEL = 1;
+ _curObjectHub.setLogicLevel(1);
logicReplace(new_script);
}
@@ -249,8 +253,10 @@ void Logic::logicOne(uint32 new_script) {
*/
void Logic::logicReplace(uint32 new_script) {
- _curObjectHub->script_id[LEVEL] = new_script;
- _curObjectHub->script_pc[LEVEL] = new_script & 0xffff;
+ uint32 level = _curObjectHub.getLogicLevel();
+
+ _curObjectHub.setScriptId(level, new_script);
+ _curObjectHub.setScriptPc(level, new_script & 0xffff);
}
void Logic::resetKillList() {
diff --git a/sword2/logic.h b/sword2/logic.h
index 8f5a01b1f4..f41932b188 100644
--- a/sword2/logic.h
+++ b/sword2/logic.h
@@ -69,7 +69,7 @@ private:
uint32 _pc;
// each object has one of these tacked onto the beginning
- ObjectHub *_curObjectHub;
+ ObjectHub _curObjectHub;
EventUnit _eventList[MAX_events];
@@ -119,18 +119,21 @@ private:
bool wantSpeechForLine(uint32 wavId);
// Set by fnPassMega()
- ObjectMega _engineMega;
+ byte _engineMega[56];
public:
Logic(Sword2Engine *vm);
~Logic();
EventUnit *getEventList() { return _eventList; }
+ byte *getEngineMega() { return _engineMega; }
- ObjectMega *getEngineMega() { return &_engineMega; }
+ byte _saveLogic[8];
+ byte _saveGraphic[12];
+ byte _saveMega[56];
// Point to the global variable data
- static uint32 *_scriptVars;
+ byte *_scriptVars;
// "TEXT" - current official text line number - will match the wav
// filenames
@@ -140,7 +143,18 @@ public:
// so speech text cleared when running a new start-script
uint32 _speechTextBlocNo;
- int runScript(char *scriptData, char *objectData, uint32 *offset);
+ uint32 readVar(int n) {
+ return READ_LE_UINT32(_scriptVars + 4 * n);
+ }
+
+ void writeVar(int n, uint32 value) {
+ WRITE_LE_UINT32(_scriptVars + 4 * n, value);
+ }
+
+ int runResScript(uint32 scriptRes, uint32 offset);
+ int runResObjScript(uint32 scriptRes, uint32 objRes, uint32 offset);
+ int runScript(byte *scriptData, byte *objectData, uint32 offset);
+ int runScript2(byte *scriptData, byte *objectData, byte *offset);
void sendEvent(uint32 id, uint32 interact_id);
void setPlayerActionEvent(uint32 id, uint32 interact_id);
diff --git a/sword2/maketext.cpp b/sword2/maketext.cpp
index 98932b6d2a..c9c4090a83 100644
--- a/sword2/maketext.cpp
+++ b/sword2/maketext.cpp
@@ -213,22 +213,24 @@ byte *FontRenderer::buildTextSprite(byte *sentence, uint32 fontRes, uint8 pen, L
// Allocate memory for the text sprite
uint32 sizeOfSprite = spriteWidth * spriteHeight;
- byte *textSprite = (byte *)malloc(sizeof(FrameHeader) + sizeOfSprite);
+ byte *textSprite = (byte *)malloc(FrameHeader::size() + sizeOfSprite);
// At this stage, textSprite points to an unmovable memory block. Set
// up the frame header.
- FrameHeader *frameHeadPtr = (FrameHeader *)textSprite;
+ FrameHeader frame_head;
- frameHeadPtr->compSize = 0;
- frameHeadPtr->width = spriteWidth;
- frameHeadPtr->height = spriteHeight;
+ frame_head.compSize = 0;
+ frame_head.width = spriteWidth;
+ frame_head.height = spriteHeight;
+
+ frame_head.write(textSprite);
debug(4, "Text sprite size: %ux%u", spriteWidth, spriteHeight);
// Clear the entire sprite to make it transparent.
- byte *linePtr = textSprite + sizeof(FrameHeader);
+ byte *linePtr = textSprite + FrameHeader::size();
memset(linePtr, 0, sizeOfSprite);
byte *charSet = _vm->_resman->openResource(fontRes);
@@ -246,11 +248,13 @@ byte *FontRenderer::buildTextSprite(byte *sentence, uint32 fontRes, uint8 pen, L
// width minus the 'overlap'
for (uint j = 0; j < line[i].length; j++) {
- FrameHeader *charPtr = findChar(sentence[pos++], charSet);
+ byte *charPtr = findChar(sentence[pos++], charSet);
+
+ frame_head.read(charPtr);
- assert(charPtr->height == char_height);
+ assert(frame_head.height == char_height);
copyChar(charPtr, spritePtr, spriteWidth, pen);
- spritePtr += charPtr->width + _charSpacing;
+ spritePtr += frame_head.width + _charSpacing;
}
// Skip space at end of last word in this line
@@ -273,11 +277,12 @@ byte *FontRenderer::buildTextSprite(byte *sentence, uint32 fontRes, uint8 pen, L
uint16 FontRenderer::charWidth(byte ch, uint32 fontRes) {
byte *charSet = _vm->_resman->openResource(fontRes);
- FrameHeader *charFrame = findChar(ch, charSet);
- uint16 width = charFrame->width;
+ FrameHeader frame_head;
+ frame_head.read(findChar(ch, charSet));
_vm->_resman->closeResource(fontRes);
- return width;
+
+ return frame_head.width;
}
/**
@@ -293,11 +298,12 @@ uint16 FontRenderer::charWidth(byte ch, uint32 fontRes) {
uint16 FontRenderer::charHeight(uint32 fontRes) {
byte *charSet = _vm->_resman->openResource(fontRes);
- FrameHeader *charFrame = findChar(FIRST_CHAR, charSet);
- uint16 height = charFrame->height;
+ FrameHeader frame_head;
+ frame_head.read(findChar(FIRST_CHAR, charSet));
_vm->_resman->closeResource(fontRes);
- return height;
+
+ return frame_head.height;
}
/**
@@ -307,7 +313,7 @@ uint16 FontRenderer::charHeight(uint32 fontRes) {
* 'dud' character (chequered flag)
*/
-FrameHeader* FontRenderer::findChar(byte ch, byte *charSet) {
+byte *FontRenderer::findChar(byte ch, byte *charSet) {
if (ch < FIRST_CHAR)
ch = DUD;
return _vm->fetchFrameHeader(charSet, ch - FIRST_CHAR);
@@ -323,16 +329,20 @@ FrameHeader* FontRenderer::findChar(byte ch, byte *charSet) {
* LETTER_COL to pen.
*/
-void FontRenderer::copyChar(FrameHeader *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen) {
- byte *source = (byte *)charPtr + sizeof(FrameHeader);
+void FontRenderer::copyChar(byte *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen) {
+ FrameHeader frame;
+
+ frame.read(charPtr);
+
+ byte *source = charPtr + FrameHeader::size();
byte *rowPtr = spritePtr;
- for (uint i = 0; i < charPtr->height; i++) {
+ for (uint i = 0; i < frame.height; i++) {
byte *dest = rowPtr;
if (pen) {
// Use the specified colours
- for (uint j = 0; j < charPtr->width; j++) {
+ for (uint j = 0; j < frame.width; j++) {
switch (*source++) {
case LETTER_COL:
*dest = pen;
@@ -355,8 +365,8 @@ void FontRenderer::copyChar(FrameHeader *charPtr, byte *spritePtr, uint16 sprite
// Pen is zero, so just copy character sprites
// directly into text sprite without remapping colours.
// Apparently overlapping is never considered here?
- memcpy(dest, source, charPtr->width);
- source += charPtr->width;
+ memcpy(dest, source, frame.width);
+ source += frame.width;
}
rowPtr += spriteWidth;
}
@@ -387,37 +397,39 @@ uint32 FontRenderer::buildNewBloc(byte *ascii, int16 x, int16 y, uint16 width, u
// without margin checking - used for debug text
if (justification != NO_JUSTIFICATION) {
- FrameHeader *frame_head = (FrameHeader *)_blocList[i].text_mem;
+ FrameHeader frame_head;
+
+ frame_head.read(_blocList[i].text_mem);
switch (justification) {
case POSITION_AT_CENTRE_OF_BASE:
// This one is always used for SPEECH TEXT; possibly
// also for pointer text
- x -= (frame_head->width / 2);
- y -= frame_head->height;
+ x -= (frame_head.width / 2);
+ y -= frame_head.height;
break;
case POSITION_AT_CENTRE_OF_TOP:
- x -= (frame_head->width / 2);
+ x -= (frame_head.width / 2);
break;
case POSITION_AT_LEFT_OF_TOP:
// The given coords are already correct for this!
break;
case POSITION_AT_RIGHT_OF_TOP:
- x -= frame_head->width;
+ x -= frame_head.width;
break;
case POSITION_AT_LEFT_OF_BASE:
- y -= frame_head->height;
+ y -= frame_head.height;
break;
case POSITION_AT_RIGHT_OF_BASE:
- x -= frame_head->width;
- y -= frame_head->height;
+ x -= frame_head.width;
+ y -= frame_head.height;
break;
case POSITION_AT_LEFT_OF_CENTRE:
- y -= (frame_head->height / 2);
+ y -= (frame_head.height / 2);
break;
case POSITION_AT_RIGHT_OF_CENTRE:
- x -= frame_head->width;
- y -= (frame_head->height) / 2;
+ x -= frame_head.width;
+ y -= (frame_head.height) / 2;
break;
}
@@ -425,9 +437,9 @@ uint32 FontRenderer::buildNewBloc(byte *ascii, int16 x, int16 y, uint16 width, u
// remember - it's RDSPR_DISPLAYALIGN
uint16 text_left_margin = TEXT_MARGIN;
- uint16 text_right_margin = 640 - TEXT_MARGIN - frame_head->width;
+ uint16 text_right_margin = 640 - TEXT_MARGIN - frame_head.width;
uint16 text_top_margin = TEXT_MARGIN;
- uint16 text_bottom_margin = 400 - TEXT_MARGIN - frame_head->height;
+ uint16 text_bottom_margin = 400 - TEXT_MARGIN - frame_head.height;
// Move if too far left or too far right
@@ -460,19 +472,21 @@ uint32 FontRenderer::buildNewBloc(byte *ascii, int16 x, int16 y, uint16 width, u
void FontRenderer::printTextBlocs() {
for (uint i = 0; i < MAX_text_blocs; i++) {
if (_blocList[i].text_mem) {
- FrameHeader *frame = (FrameHeader *)_blocList[i].text_mem;
+ FrameHeader frame_head;
SpriteInfo spriteInfo;
+ frame_head.read(_blocList[i].text_mem);
+
spriteInfo.x = _blocList[i].x;
spriteInfo.y = _blocList[i].y;
- spriteInfo.w = frame->width;
- spriteInfo.h = frame->height;
+ spriteInfo.w = frame_head.width;
+ spriteInfo.h = frame_head.height;
spriteInfo.scale = 0;
spriteInfo.scaledWidth = 0;
spriteInfo.scaledHeight = 0;
spriteInfo.type = _blocList[i].type;
spriteInfo.blend = 0;
- spriteInfo.data = _blocList[i].text_mem + sizeof(FrameHeader);
+ spriteInfo.data = _blocList[i].text_mem + FrameHeader::size();
spriteInfo.colourTable = 0;
uint32 rv = _vm->_screen->drawSprite(&spriteInfo);
@@ -528,7 +542,7 @@ void Sword2Engine::initialiseFontResourceFlags() {
//
// But we get it from the text resource instead.
- if (Logic::_scriptVars[DEMO])
+ if (_logic->readVar(DEMO))
textLine = (char *)fetchTextLine(textFile, 451) + 2;
else
textLine = (char *)fetchTextLine(textFile, 54) + 2;
diff --git a/sword2/maketext.h b/sword2/maketext.h
index edf57b46e2..c3dc1d4a34 100644
--- a/sword2/maketext.h
+++ b/sword2/maketext.h
@@ -91,8 +91,8 @@ private:
byte *buildTextSprite(byte *sentence, uint32 fontRes, uint8 pen, LineInfo *line, uint16 noOfLines);
uint16 charWidth(byte ch, uint32 fontRes);
uint16 charHeight(uint32 fontRes);
- FrameHeader* findChar(byte ch, byte *charSet);
- void copyChar(FrameHeader *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen);
+ byte *findChar(byte ch, byte *charSet);
+ void copyChar(byte *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen);
public:
FontRenderer(Sword2Engine *vm) : _vm(vm) {
diff --git a/sword2/mouse.cpp b/sword2/mouse.cpp
index 7087b36097..c97cbb9fb1 100644
--- a/sword2/mouse.cpp
+++ b/sword2/mouse.cpp
@@ -74,9 +74,8 @@ Mouse::Mouse(Sword2Engine *vm) {
_playerActivityDelay = 0;
_realLuggageItem = 0;
- _mouseSprite = NULL;
- _mouseAnim = NULL;
- _luggageAnim = NULL;
+ _mouseAnim.data = NULL;
+ _luggageAnim.data = NULL;
// For the menus
_totalTemp = 0;
@@ -103,8 +102,8 @@ Mouse::Mouse(Sword2Engine *vm) {
}
Mouse::~Mouse() {
- free(_mouseAnim);
- free(_luggageAnim);
+ free(_mouseAnim.data);
+ free(_luggageAnim.data);
for (int i = 0; i < 2; i++)
for (int j = 0; j < RDMENU_MAXPOCKETS; j++)
free(_icons[i][j]);
@@ -128,26 +127,30 @@ void Mouse::resetMouseList() {
_curMouse = 0;
}
-void Mouse::registerMouse(ObjectMouse *ob_mouse, BuildUnit *build_unit) {
- if (!ob_mouse->pointer)
- return;
-
+void Mouse::registerMouse(byte *ob_mouse, BuildUnit *build_unit) {
assert(_curMouse < TOTAL_mouse_list);
+ ObjectMouse mouse;
+
+ mouse.read(ob_mouse);
+
+ if (!mouse.pointer)
+ return;
+
if (build_unit) {
_mouseList[_curMouse].rect.left = build_unit->x;
_mouseList[_curMouse].rect.top = build_unit->y;
_mouseList[_curMouse].rect.right = 1 + build_unit->x + build_unit->scaled_width;
_mouseList[_curMouse].rect.bottom = 1 + build_unit->y + build_unit->scaled_height;
} else {
- _mouseList[_curMouse].rect.left = ob_mouse->x1;
- _mouseList[_curMouse].rect.top = ob_mouse->y1;
- _mouseList[_curMouse].rect.right = 1 + ob_mouse->x2;
- _mouseList[_curMouse].rect.bottom = 1 + ob_mouse->y2;
+ _mouseList[_curMouse].rect.left = mouse.x1;
+ _mouseList[_curMouse].rect.top = mouse.y1;
+ _mouseList[_curMouse].rect.right = 1 + mouse.x2;
+ _mouseList[_curMouse].rect.bottom = 1 + mouse.y2;
}
- _mouseList[_curMouse].priority = ob_mouse->priority;
- _mouseList[_curMouse].pointer = ob_mouse->pointer;
+ _mouseList[_curMouse].priority = mouse.priority;
+ _mouseList[_curMouse].pointer = mouse.pointer;
// Change all COGS pointers to CROSHAIR. I'm guessing that this was a
// design decision made in mid-development and they didn't want to go
@@ -162,11 +165,11 @@ void Mouse::registerMouse(ObjectMouse *ob_mouse, BuildUnit *build_unit) {
// If 'pointer_text' field is set, but the 'id' field isn't same is
// current id then we don't want this "left over" pointer text
- if (_mouseList[_curMouse].pointer_text && _mouseList[_curMouse].id != (int32) Logic::_scriptVars[ID])
+ if (_mouseList[_curMouse].pointer_text && _mouseList[_curMouse].id != (int32)_vm->_logic->readVar(ID))
_mouseList[_curMouse].pointer_text = 0;
// Get id from system variable 'id' which is correct for current object
- _mouseList[_curMouse].id = Logic::_scriptVars[ID];
+ _mouseList[_curMouse].id = _vm->_logic->readVar(ID);
_curMouse++;
}
@@ -177,7 +180,7 @@ void Mouse::registerPointerText(int32 text_id) {
// current object id - used for checking pointer_text when mouse area
// registered (in fnRegisterMouse and fnRegisterFrame)
- _mouseList[_curMouse].id = Logic::_scriptVars[ID];
+ _mouseList[_curMouse].id = _vm->_logic->readVar(ID);
_mouseList[_curMouse].pointer_text = text_id;
}
@@ -192,7 +195,7 @@ void Mouse::mouseEngine() {
// If George is dead, the system menu is visible all the time, and is
// the only thing that can be used.
- if (Logic::_scriptVars[DEAD]) {
+ if (_vm->_logic->readVar(DEAD)) {
if (_mouseMode != MOUSE_system_menu) {
_mouseMode = MOUSE_system_menu;
@@ -239,8 +242,10 @@ void Mouse::mouseEngine() {
#if RIGHT_CLICK_CLEARS_LUGGAGE
bool Mouse::heldIsInInventory() {
+ int32 object_held = (int32)_vm->_logic->readVar(OBJECT_HELD);
+
for (uint i = 0; i < _totalMasters; i++) {
- if ((uint32) _masterMenuList[i].icon_resource == Logic::_scriptVars[OBJECT_HELD])
+ if (_masterMenuList[i].icon_resource == object_held)
return true;
}
return false;
@@ -274,7 +279,7 @@ void Mouse::systemMenuMouse() {
// If the mouse is moved off the menu, close it. Unless the player is
// dead, in which case the menu should always be visible.
- if (_pos.y > 0 && !Logic::_scriptVars[DEAD]) {
+ if (_pos.y > 0 && !_vm->_logic->readVar(DEAD)) {
_mouseMode = MOUSE_normal;
hideMenu(RDMENU_TOP);
return;
@@ -297,14 +302,14 @@ void Mouse::systemMenuMouse() {
// No save when dead
- if (icon_list[hit] == SAVE_ICON && Logic::_scriptVars[DEAD])
+ if (icon_list[hit] == SAVE_ICON && _vm->_logic->readVar(DEAD))
return;
// Gray out all he icons, except the one that was clicked
for (int i = 0; i < ARRAYSIZE(icon_list); i++) {
if (i != hit) {
- icon = _vm->_resman->openResource(icon_list[i]) + sizeof(StandardHeader);
+ icon = _vm->_resman->openResource(icon_list[i]) + ResHeader::size();
setMenuIcon(RDMENU_TOP, i, icon);
_vm->_resman->closeResource(icon_list[i]);
}
@@ -364,7 +369,7 @@ void Mouse::systemMenuMouse() {
// Menu stays open on death screen. Otherwise it's closed.
- if (!Logic::_scriptVars[DEAD]) {
+ if (!_vm->_logic->readVar(DEAD)) {
_mouseMode = MOUSE_normal;
hideMenu(RDMENU_TOP);
} else {
@@ -432,7 +437,7 @@ void Mouse::dragMouse() {
#if RIGHT_CLICK_CLEARS_LUGGAGE
if ((me->buttons & RD_RIGHTBUTTONDOWN) && heldIsInInventory()) {
- Logic::_scriptVars[OBJECT_HELD] = 0;
+ _vm->_logic->writeVar(OBJECT_HELD, 0);
_menuSelectedPos = 0;
_mouseMode = MOUSE_menu;
setLuggage(0);
@@ -458,25 +463,25 @@ void Mouse::dragMouse() {
// Set global script variable 'button'. We know that it was the
// left button, not the right one.
- Logic::_scriptVars[LEFT_BUTTON] = 1;
- Logic::_scriptVars[RIGHT_BUTTON] = 0;
+ _vm->_logic->writeVar(LEFT_BUTTON, 1);
+ _vm->_logic->writeVar(RIGHT_BUTTON, 0);
// These might be required by the action script about to be run
ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
- Logic::_scriptVars[MOUSE_X] = _pos.x + screenInfo->scroll_offset_x;
- Logic::_scriptVars[MOUSE_Y] = _pos.y + screenInfo->scroll_offset_y;
+ _vm->_logic->writeVar(MOUSE_X, _pos.x + screenInfo->scroll_offset_x);
+ _vm->_logic->writeVar(MOUSE_Y, _pos.y + screenInfo->scroll_offset_y);
// For scripts to know what's been clicked. First used for
// 'room_13_turning_script' in object 'biscuits_13'
- Logic::_scriptVars[CLICKED_ID] = _mouseTouching;
+ _vm->_logic->writeVar(CLICKED_ID, _mouseTouching);
_vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
debug(2, "Used \"%s\" on \"%s\"",
- _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
- _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
+ _vm->_resman->fetchName(_vm->_logic->readVar(OBJECT_HELD), buf1),
+ _vm->_resman->fetchName(_vm->_logic->readVar(CLICKED_ID), buf2));
// Hide menu - back to normal menu mode
@@ -499,15 +504,15 @@ void Mouse::dragMouse() {
_mouseMode = MOUSE_menu;
setLuggage(0);
- if ((uint) hit == _menuSelectedPos) {
+ if ((uint)hit == _menuSelectedPos) {
// If we clicked on the same icon again, reset the first icon
- Logic::_scriptVars[OBJECT_HELD] = 0;
+ _vm->_logic->writeVar(OBJECT_HELD, 0);
_menuSelectedPos = 0;
} else {
// Otherwise, combine the two icons
- Logic::_scriptVars[COMBINE_BASE] = _masterMenuList[hit].icon_resource;
+ _vm->_logic->writeVar(COMBINE_BASE, _masterMenuList[hit].icon_resource);
_vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
// Turn off mouse now, to prevent player trying to click
@@ -516,8 +521,8 @@ void Mouse::dragMouse() {
hideMouse();
debug(2, "Used \"%s\" on \"%s\"",
- _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
- _vm->fetchObjectName(Logic::_scriptVars[COMBINE_BASE], buf2));
+ _vm->_resman->fetchName(_vm->_logic->readVar(OBJECT_HELD), buf1),
+ _vm->_resman->fetchName(_vm->_logic->readVar(COMBINE_BASE), buf2));
}
// Refresh the menu
@@ -555,12 +560,12 @@ void Mouse::menuMouse() {
// resource id.
_examiningMenuIcon = true;
- Logic::_scriptVars[OBJECT_HELD] = _masterMenuList[hit].icon_resource;
+ _vm->_logic->writeVar(OBJECT_HELD, _masterMenuList[hit].icon_resource);
// Must clear this so next click on exit becomes 1st click
// again
- Logic::_scriptVars[EXIT_CLICK_ID] = 0;
+ _vm->_logic->writeVar(EXIT_CLICK_ID, 0);
_vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
@@ -574,7 +579,7 @@ void Mouse::menuMouse() {
hideMouse();
debug(2, "Right-click on \"%s\" icon",
- _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
+ _vm->_resman->fetchName(_vm->_logic->readVar(OBJECT_HELD), buf));
return;
}
@@ -587,13 +592,13 @@ void Mouse::menuMouse() {
_mouseMode = MOUSE_drag;
_menuSelectedPos = hit;
- Logic::_scriptVars[OBJECT_HELD] = _masterMenuList[hit].icon_resource;
+ _vm->_logic->writeVar(OBJECT_HELD, _masterMenuList[hit].icon_resource);
_currentLuggageResource = _masterMenuList[hit].luggage_resource;
// Must clear this so next click on exit becomes 1st click
// again
- Logic::_scriptVars[EXIT_CLICK_ID] = 0;
+ _vm->_logic->writeVar(EXIT_CLICK_ID, 0);
// Refresh the menu
@@ -602,7 +607,7 @@ void Mouse::menuMouse() {
setLuggage(_masterMenuList[hit].luggage_resource);
debug(2, "Left-clicked on \"%s\" icon - switch to drag mode",
- _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
+ _vm->_resman->fetchName(_vm->_logic->readVar(OBJECT_HELD), buf));
}
}
@@ -616,7 +621,7 @@ void Mouse::normalMouse() {
// big-object menu lock situation, of if the player is dragging an
// object.
- if (_pos.y < 0 && !_mouseModeLocked && !Logic::_scriptVars[OBJECT_HELD]) {
+ if (_pos.y < 0 && !_mouseModeLocked && !_vm->_logic->readVar(OBJECT_HELD)) {
_mouseMode = MOUSE_system_menu;
if (_mouseTouching) {
@@ -644,7 +649,7 @@ void Mouse::normalMouse() {
// object, even if the inventory menu was closed after the
// first object was selected.
- if (!Logic::_scriptVars[OBJECT_HELD])
+ if (!_vm->_logic->readVar(OBJECT_HELD))
_mouseMode = MOUSE_menu;
else
_mouseMode = MOUSE_drag;
@@ -686,8 +691,8 @@ void Mouse::normalMouse() {
if (button_down) {
// set both (x1,y1) and (x2,y2) to this point
- _vm->_debugger->_rectX1 = _vm->_debugger->_rectX2 = (uint32) _pos.x + screenInfo->scroll_offset_x;
- _vm->_debugger->_rectY1 = _vm->_debugger->_rectY2 = (uint32) _pos.y + screenInfo->scroll_offset_y;
+ _vm->_debugger->_rectX1 = _vm->_debugger->_rectX2 = (uint32)_pos.x + screenInfo->scroll_offset_x;
+ _vm->_debugger->_rectY1 = _vm->_debugger->_rectY2 = (uint32)_pos.y + screenInfo->scroll_offset_y;
_vm->_debugger->_draggingRectangle = 1;
}
} else if (_vm->_debugger->_draggingRectangle == 1) {
@@ -699,8 +704,8 @@ void Mouse::normalMouse() {
_vm->_debugger->_draggingRectangle = 2;
} else {
// drag rectangle
- _vm->_debugger->_rectX2 = (uint32) _pos.x + screenInfo->scroll_offset_x;
- _vm->_debugger->_rectY2 = (uint32) _pos.y + screenInfo->scroll_offset_y;
+ _vm->_debugger->_rectX2 = (uint32)_pos.x + screenInfo->scroll_offset_x;
+ _vm->_debugger->_rectY2 = (uint32)_pos.y + screenInfo->scroll_offset_y;
}
} else {
// currently locked to avoid knocking out of place
@@ -716,8 +721,8 @@ void Mouse::normalMouse() {
}
#if RIGHT_CLICK_CLEARS_LUGGAGE
- if (Logic::_scriptVars[OBJECT_HELD] && (me->buttons & RD_RIGHTBUTTONDOWN) && heldIsInInventory()) {
- Logic::_scriptVars[OBJECT_HELD] = 0;
+ if (_vm->_logic->readVar(OBJECT_HELD) && (me->buttons & RD_RIGHTBUTTONDOWN) && heldIsInInventory()) {
+ _vm->_logic->writeVar(OBJECT_HELD, 0);
_menuSelectedPos = 0;
setLuggage(0);
return;
@@ -743,29 +748,29 @@ void Mouse::normalMouse() {
// PLAYER_ACTION script variable - whatever catches this must reset to
// 0 again
- // Logic::_scriptVars[PLAYER_ACTION] = _mouseTouching;
+ // _vm->_logic->writeVar(PLAYER_ACTION, _mouseTouching);
// Idle or router-anim will catch it
// Set global script variable 'button'
if (me->buttons & RD_LEFTBUTTONDOWN) {
- Logic::_scriptVars[LEFT_BUTTON] = 1;
- Logic::_scriptVars[RIGHT_BUTTON] = 0;
+ _vm->_logic->writeVar(LEFT_BUTTON, 1);
+ _vm->_logic->writeVar(RIGHT_BUTTON, 0);
_buttonClick = 0; // for re-click
} else {
- Logic::_scriptVars[LEFT_BUTTON] = 0;
- Logic::_scriptVars[RIGHT_BUTTON] = 1;
+ _vm->_logic->writeVar(LEFT_BUTTON, 0);
+ _vm->_logic->writeVar(RIGHT_BUTTON, 1);
_buttonClick = 1; // for re-click
}
// These might be required by the action script about to be run
ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
- Logic::_scriptVars[MOUSE_X] = _pos.x + screenInfo->scroll_offset_x;
- Logic::_scriptVars[MOUSE_Y] = _pos.y + screenInfo->scroll_offset_y;
+ _vm->_logic->writeVar(MOUSE_X, _pos.x + screenInfo->scroll_offset_x);
+ _vm->_logic->writeVar(MOUSE_Y, _pos.y + screenInfo->scroll_offset_y);
- if (_mouseTouching == Logic::_scriptVars[EXIT_CLICK_ID] && (me->buttons & RD_LEFTBUTTONDOWN)) {
+ if (_mouseTouching == _vm->_logic->readVar(EXIT_CLICK_ID) && (me->buttons & RD_LEFTBUTTONDOWN)) {
// It's the exit double click situation. Let the existing
// interaction continue and start fading down. Switch the human
// off too
@@ -775,8 +780,8 @@ void Mouse::normalMouse() {
// Tell the walker
- Logic::_scriptVars[EXIT_FADING] = 1;
- } else if (_oldButton == _buttonClick && _mouseTouching == Logic::_scriptVars[CLICKED_ID] && _mousePointerRes != NORMAL_MOUSE_ID) {
+ _vm->_logic->writeVar(EXIT_FADING, 1);
+ } else if (_oldButton == _buttonClick && _mouseTouching == _vm->_logic->readVar(CLICKED_ID) && _mousePointerRes != NORMAL_MOUSE_ID) {
// Re-click. Do nothing, except on floors
} else {
// For re-click
@@ -786,28 +791,28 @@ void Mouse::normalMouse() {
// For scripts to know what's been clicked. First used for
// 'room_13_turning_script' in object 'biscuits_13'
- Logic::_scriptVars[CLICKED_ID] = _mouseTouching;
+ _vm->_logic->writeVar(CLICKED_ID, _mouseTouching);
// Must clear these two double-click control flags - do it here
// so reclicks after exit clicks are cleared up
- Logic::_scriptVars[EXIT_CLICK_ID] = 0;
- Logic::_scriptVars[EXIT_FADING] = 0;
+ _vm->_logic->writeVar(EXIT_CLICK_ID, 0);
+ _vm->_logic->writeVar(EXIT_FADING, 0);
_vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
byte buf1[NAME_LEN], buf2[NAME_LEN];
- if (Logic::_scriptVars[OBJECT_HELD])
+ if (_vm->_logic->readVar(OBJECT_HELD))
debug(2, "Used \"%s\" on \"%s\"",
- _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
- _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
- else if (Logic::_scriptVars[LEFT_BUTTON])
+ _vm->_resman->fetchName(_vm->_logic->readVar(OBJECT_HELD), buf1),
+ _vm->_resman->fetchName(_vm->_logic->readVar(CLICKED_ID), buf2));
+ else if (_vm->_logic->readVar(LEFT_BUTTON))
debug(2, "Left-clicked on \"%s\"",
- _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
+ _vm->_resman->fetchName(_vm->_logic->readVar(CLICKED_ID), buf1));
else // RIGHT BUTTON
debug(2, "Right-clicked on \"%s\"",
- _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
+ _vm->_resman->fetchName(_vm->_logic->readVar(CLICKED_ID), buf1));
}
}
@@ -817,9 +822,12 @@ uint32 Mouse::chooseMouse() {
uint i;
- Logic::_scriptVars[AUTO_SELECTED] = 0;
+ _vm->_logic->writeVar(AUTO_SELECTED, 0);
+
+ uint32 in_subject = _vm->_logic->readVar(IN_SUBJECT);
+ uint32 object_held = _vm->_logic->readVar(OBJECT_HELD);
- if (Logic::_scriptVars[OBJECT_HELD]) {
+ if (object_held) {
// The player used an object on a person. In this case it
// triggered a conversation menu. Act as if the user tried to
// talk to the person about that object. If the person doesn't
@@ -827,8 +835,8 @@ uint32 Mouse::chooseMouse() {
uint32 response = _defaultResponseId;
- for (i = 0; i < Logic::_scriptVars[IN_SUBJECT]; i++) {
- if (_subjectList[i].res == Logic::_scriptVars[OBJECT_HELD]) {
+ for (i = 0; i < in_subject; i++) {
+ if (_subjectList[i].res == object_held) {
response = _subjectList[i].ref;
break;
}
@@ -837,12 +845,12 @@ uint32 Mouse::chooseMouse() {
// The user won't be holding the object any more, and the
// conversation menu will be closed.
- Logic::_scriptVars[OBJECT_HELD] = 0;
- Logic::_scriptVars[IN_SUBJECT] = 0;
+ _vm->_logic->writeVar(OBJECT_HELD, 0);
+ _vm->_logic->writeVar(IN_SUBJECT, 0);
return response;
}
- if (Logic::_scriptVars[CHOOSER_COUNT_FLAG] == 0 && Logic::_scriptVars[IN_SUBJECT] == 1 && _subjectList[0].res == EXIT_ICON) {
+ if (_vm->_logic->readVar(CHOOSER_COUNT_FLAG) == 0 && in_subject == 1 && _subjectList[0].res == EXIT_ICON) {
// This is the first time the chooser is coming up in this
// conversation, there is only one subject and that's the
// EXIT icon.
@@ -853,8 +861,8 @@ uint32 Mouse::chooseMouse() {
// The conversation menu will be closed. We set AUTO_SELECTED
// because the speech script depends on it.
- Logic::_scriptVars[AUTO_SELECTED] = 1;
- Logic::_scriptVars[IN_SUBJECT] = 0;
+ _vm->_logic->writeVar(AUTO_SELECTED, 1);
+ _vm->_logic->writeVar(IN_SUBJECT, 0);
return _subjectList[0].ref;
}
@@ -863,11 +871,11 @@ uint32 Mouse::chooseMouse() {
if (!_choosing) {
// This is a new conversation menu.
- if (!Logic::_scriptVars[IN_SUBJECT])
+ if (!in_subject)
error("fnChoose with no subjects");
- for (i = 0; i < Logic::_scriptVars[IN_SUBJECT]; i++) {
- icon = _vm->_resman->openResource(_subjectList[i].res) + sizeof(StandardHeader) + RDMENU_ICONWIDE * RDMENU_ICONDEEP;
+ for (i = 0; i < in_subject; i++) {
+ icon = _vm->_resman->openResource(_subjectList[i].res) + ResHeader::size() + RDMENU_ICONWIDE * RDMENU_ICONDEEP;
setMenuIcon(RDMENU_BOTTOM, i, icon);
_vm->_resman->closeResource(_subjectList[i].res);
}
@@ -878,7 +886,7 @@ uint32 Mouse::chooseMouse() {
showMenu(RDMENU_BOTTOM);
setMouse(NORMAL_MOUSE_ID);
_choosing = true;
- return (uint32) -1;
+ return (uint32)-1;
}
// The menu is there - we're just waiting for a click. We only care
@@ -890,33 +898,33 @@ uint32 Mouse::chooseMouse() {
getPos(mouseX, mouseY);
if (!me || !(me->buttons & RD_LEFTBUTTONDOWN) || mouseY < 400)
- return (uint32) -1;
+ return (uint32)-1;
// Check for click on a menu.
- int hit = _vm->_mouse->menuClick(Logic::_scriptVars[IN_SUBJECT]);
+ int hit = _vm->_mouse->menuClick(in_subject);
if (hit < 0)
- return (uint32) -1;
+ return (uint32)-1;
// Hilight the clicked icon by greying the others. This can look a bit
// odd when you click on the exit icon, but there are also cases when
// it looks strange if you don't do it.
- for (i = 0; i < Logic::_scriptVars[IN_SUBJECT]; i++) {
- if ((int) i != hit) {
- icon = _vm->_resman->openResource(_subjectList[i].res) + sizeof(StandardHeader);
+ for (i = 0; i < in_subject; i++) {
+ if ((int)i != hit) {
+ icon = _vm->_resman->openResource(_subjectList[i].res) + ResHeader::size();
_vm->_mouse->setMenuIcon(RDMENU_BOTTOM, i, icon);
_vm->_resman->closeResource(_subjectList[i].res);
}
}
// For non-speech scripts that manually call the chooser
- Logic::_scriptVars[RESULT] = _subjectList[hit].res;
+ _vm->_logic->writeVar(RESULT, _subjectList[hit].res);
// The conversation menu will be closed
_choosing = false;
- Logic::_scriptVars[IN_SUBJECT] = 0;
+ _vm->_logic->writeVar(IN_SUBJECT, 0);
setMouse(0);
return _subjectList[hit].ref;
@@ -973,13 +981,13 @@ void Mouse::mouseOnOff() {
setMouse(pointer_type);
// setup luggage icon
- if (Logic::_scriptVars[OBJECT_HELD]) {
+ if (_vm->_logic->readVar(OBJECT_HELD)) {
setLuggage(_currentLuggageResource);
}
} else {
byte buf[NAME_LEN];
- error("ERROR: mouse.pointer==0 for object %d (%s) - update logic script!", _mouseTouching, _vm->fetchObjectName(_mouseTouching, buf));
+ error("ERROR: mouse.pointer==0 for object %d (%s) - update logic script!", _mouseTouching, _vm->_resman->fetchName(_mouseTouching, buf));
}
} else if (_oldMouseTouching && !_mouseTouching) {
// the cursor has moved off something - reset cursor to
@@ -1024,8 +1032,8 @@ void Mouse::setMouse(uint32 res) {
_mousePointerRes = res;
if (res) {
- byte *icon = _vm->_resman->openResource(res) + sizeof(StandardHeader);
- uint32 len = _vm->_resman->fetchLen(res) - sizeof(StandardHeader);
+ byte *icon = _vm->_resman->openResource(res) + ResHeader::size();
+ uint32 len = _vm->_resman->fetchLen(res) - ResHeader::size();
// don't pulse the normal pointer - just do the regular anim
// loop
@@ -1046,8 +1054,8 @@ void Mouse::setLuggage(uint32 res) {
_realLuggageItem = res;
if (res) {
- byte *icon = _vm->_resman->openResource(res) + sizeof(StandardHeader);
- uint32 len = _vm->_resman->fetchLen(res) - sizeof(StandardHeader);
+ byte *icon = _vm->_resman->openResource(res) + ResHeader::size();
+ uint32 len = _vm->_resman->fetchLen(res) - ResHeader::size();
setLuggageAnim(icon, len);
_vm->_resman->closeResource(res);
@@ -1058,7 +1066,7 @@ void Mouse::setLuggage(uint32 res) {
void Mouse::setObjectHeld(uint32 res) {
setLuggage(res);
- Logic::_scriptVars[OBJECT_HELD] = res;
+ _vm->_logic->writeVar(OBJECT_HELD, res);
_currentLuggageResource = res;
// mode locked - no menu available
@@ -1263,7 +1271,7 @@ void Mouse::hideMouse() {
// it and when combining objects
// for logic scripts
- Logic::_scriptVars[MOUSE_AVAILABLE] = 0;
+ _vm->_logic->writeVar(MOUSE_AVAILABLE, 0);
// human/mouse off
_mouseStatus = true;
@@ -1280,7 +1288,7 @@ void Mouse::noHuman() {
// special menus use hideMouse()
// Don't hide menu in conversations
- if (Logic::_scriptVars[TALK_FLAG] == 0)
+ if (_vm->_logic->readVar(TALK_FLAG) == 0)
hideMenu(RDMENU_BOTTOM);
if (_mouseMode == MOUSE_system_menu) {
@@ -1292,7 +1300,7 @@ void Mouse::noHuman() {
void Mouse::addHuman() {
// For logic scripts
- Logic::_scriptVars[MOUSE_AVAILABLE] = 1;
+ _vm->_logic->writeVar(MOUSE_AVAILABLE, 1);
if (_mouseStatus) {
// Force engine to choose a cursor
@@ -1301,7 +1309,7 @@ void Mouse::addHuman() {
}
// Clear this to reset no-second-click system
- Logic::_scriptVars[CLICKED_ID] = 0;
+ _vm->_logic->writeVar(CLICKED_ID, 0);
// This is now done outside the OBJECT_HELD check in case it's set to
// zero before now!
@@ -1311,13 +1319,13 @@ void Mouse::addHuman() {
_mouseModeLocked = false;
- if (Logic::_scriptVars[OBJECT_HELD]) {
+ if (_vm->_logic->readVar(OBJECT_HELD)) {
// Was dragging something around - need to clear this again
- Logic::_scriptVars[OBJECT_HELD] = 0;
+ _vm->_logic->writeVar(OBJECT_HELD, 0);
// And these may also need clearing, just in case
_examiningMenuIcon = false;
- Logic::_scriptVars[COMBINE_BASE] = 0;
+ _vm->_logic->writeVar(COMBINE_BASE, 0);
setLuggage(0);
}
@@ -1356,7 +1364,7 @@ void Mouse::addHuman() {
void Mouse::refreshInventory() {
// Can reset this now
- Logic::_scriptVars[COMBINE_BASE] = 0;
+ _vm->_logic->writeVar(COMBINE_BASE, 0);
// Cause 'object_held' icon to be greyed. The rest are coloured.
_examiningMenuIcon = true;
@@ -1365,9 +1373,9 @@ void Mouse::refreshInventory() {
}
void Mouse::startConversation() {
- if (Logic::_scriptVars[TALK_FLAG] == 0) {
+ if (_vm->_logic->readVar(TALK_FLAG) == 0) {
// See fnChooser & speech scripts
- Logic::_scriptVars[CHOOSER_COUNT_FLAG] = 0;
+ _vm->_logic->writeVar(CHOOSER_COUNT_FLAG, 0);
}
noHuman();
@@ -1382,7 +1390,7 @@ void Mouse::endConversation() {
}
// In case DC forgets
- Logic::_scriptVars[TALK_FLAG] = 0;
+ _vm->_logic->writeVar(TALK_FLAG, 0);
}
void Mouse::monitorPlayerActivity() {
@@ -1405,9 +1413,9 @@ void Mouse::checkPlayerActivity(uint32 seconds) {
if (_playerActivityDelay >= threshold) {
_playerActivityDelay = 0;
- Logic::_scriptVars[RESULT] = 1;
+ _vm->_logic->writeVar(RESULT, 1);
} else
- Logic::_scriptVars[RESULT] = 0;
+ _vm->_logic->writeVar(RESULT, 0);
}
void Mouse::pauseGame() {
@@ -1421,7 +1429,7 @@ void Mouse::pauseGame() {
}
void Mouse::unpauseGame() {
- if (Logic::_scriptVars[OBJECT_HELD] && _realLuggageItem)
+ if (_vm->_logic->readVar(OBJECT_HELD) && _realLuggageItem)
setLuggage(_realLuggageItem);
}
diff --git a/sword2/mouse.h b/sword2/mouse.h
index a1b8268eeb..b8e94afa0c 100644
--- a/sword2/mouse.h
+++ b/sword2/mouse.h
@@ -27,7 +27,6 @@
namespace Sword2 {
-struct ObjectMouse;
struct BuildUnit;
// Menubar defines.
@@ -62,10 +61,8 @@ enum {
#define RDMENU_ICONSPACING 5
#define RDMENU_MAXPOCKETS 15
-#if !defined(__GNUC__)
- #pragma START_PACK_STRUCTS
-#endif
-
+#define MOUSE_ANIM_HEADER_SIZE 6
+
struct MouseAnim {
uint8 runTimeComp; // type of runtime compression used for the
// frame data
@@ -74,11 +71,9 @@ struct MouseAnim {
int8 yHotSpot;
uint8 mousew;
uint8 mouseh;
-} GCC_PACK;
-#if !defined(__GNUC__)
- #pragma END_PACK_STRUCTS
-#endif
+ byte *data;
+};
// The MOUSE_holding mode is entered when the conversation menu is closed, and
// exited when the mouse cursor moves off that menu area. I don't know why yet.
@@ -145,13 +140,10 @@ private:
uint32 _mousePointerRes;
- struct MouseAnim *_mouseAnim;
- struct MouseAnim *_luggageAnim;
+ MouseAnim _mouseAnim;
+ MouseAnim _luggageAnim;
uint8 _mouseFrame;
- byte *_mouseSprite;
- int32 *_mouseOffsets;
- int32 *_luggageOffset;
uint32 _mouseMode;
@@ -177,7 +169,7 @@ private:
uint32 _menuSelectedPos;
- void decompressMouse(byte *decomp, byte *comp, int width, int height, int pitch, int xOff = 0, int yOff = 0);
+ void decompressMouse(byte *decomp, byte *comp, uint8 frame, int width, int height, int pitch, int xOff = 0, int yOff = 0);
int32 setMouseAnim(byte *ma, int32 size, int32 mouseFlash);
int32 setLuggageAnim(byte *la, int32 size);
@@ -208,7 +200,7 @@ public:
void resetMouseList();
- void registerMouse(ObjectMouse *ob_mouse, BuildUnit *build_unit);
+ void registerMouse(byte *ob_mouse, BuildUnit *build_unit);
void registerPointerText(int32 text_id);
void createPointerText(uint32 text_id, uint32 pointer_res);
@@ -219,7 +211,7 @@ public:
void processMenu();
- void addMenuObject(MenuObject *obj);
+ void addMenuObject(byte *ptr);
void addSubject(int32 id, int32 ref);
void buildMenu();
diff --git a/sword2/object.h b/sword2/object.h
index 6f33ae80d8..19c1ddc1b5 100644
--- a/sword2/object.h
+++ b/sword2/object.h
@@ -21,11 +21,9 @@
#ifndef _SCRIPT_STRUCTURES
#define _SCRIPT_STRUCTURES
-namespace Sword2 {
+#include "common/stream.h"
-#if !defined(__GNUC__)
- #pragma START_PACK_STRUCTS
-#endif
+namespace Sword2 {
// these structures represent the broken up compact components
// these here declared to the system must be the same as those declared to
@@ -41,15 +39,64 @@ struct ObjectMouse {
int32 y2;
int32 priority;
int32 pointer; // type (or resource id?) of pointer used over this area
-} GCC_PACK;
+
+ static const int size() {
+ return 24;
+ }
+
+ void read(byte *addr) {
+ Common::MemoryReadStream readS(addr, size());
+
+ x1 = readS.readSint32LE();
+ y1 = readS.readSint32LE();
+ x2 = readS.readSint32LE();
+ y2 = readS.readSint32LE();
+ priority = readS.readSint32LE();
+ pointer = readS.readSint32LE();
+ }
+
+ void write(byte *addr) {
+ Common::MemoryWriteStream writeS(addr, size());
+
+ writeS.writeSint32LE(x1);
+ writeS.writeSint32LE(y1);
+ writeS.writeSint32LE(x2);
+ writeS.writeSint32LE(y2);
+ writeS.writeSint32LE(priority);
+ writeS.writeSint32LE(pointer);
+ }
+};
// logic structure - contains fields used in logic script processing
-struct ObjectLogic {
- int32 looping; // 0 when first calling fn<function>;
- // 1 when calling subsequent times in same loop
- int32 pause; // pause count, used by fnPause()
-} GCC_PACK;
+class ObjectLogic {
+ // int32 looping; // 0 when first calling fn<function>;
+ // 1 when calling subsequent times in
+ // same loop
+ // int32 pause; // pause count, used by fnPause()
+
+private:
+ byte *_addr;
+
+public:
+ ObjectLogic(byte *addr) {
+ _addr = addr;
+ }
+
+ static const int size() {
+ return 8;
+ }
+
+ byte *data() {
+ return _addr;
+ }
+
+ int32 getLooping() { return READ_LE_UINT32(_addr); }
+ int32 getPause() { return READ_LE_UINT32(_addr + 4); }
+
+ void setLooping(int32 x) { WRITE_LE_UINT32(_addr, x); }
+ void setPause(int32 x) { WRITE_LE_UINT32(_addr + 4, x); }
+};
// status bits for 'type' field of ObjectGraphic)
@@ -71,50 +118,161 @@ struct ObjectLogic {
// graphic structure - contains fields appropriate to sprite output
-struct ObjectGraphic {
- int32 type; // see above
- int32 anim_resource; // resource id of animation file
- int32 anim_pc; // current frame number of animation
-} GCC_PACK;
+class ObjectGraphic {
+ // int32 type; // see above
+ // int32 anim_resource; // resource id of animation file
+ // int32 anim_pc; // current frame number of animation
+
+private:
+ byte *_addr;
+
+public:
+ ObjectGraphic(byte *addr) {
+ _addr = addr;
+ }
+
+ static const int size() {
+ return 12;
+ }
+
+ byte *data() {
+ return _addr;
+ }
+
+ int32 getType() { return READ_LE_UINT32(_addr); }
+ int32 getAnimResource() { return READ_LE_UINT32(_addr + 4); }
+ int32 getAnimPc() { return READ_LE_UINT32(_addr + 8); }
+
+ void setType(int32 x) { WRITE_LE_UINT32(_addr, x); }
+ void setAnimResource(int32 x) { WRITE_LE_UINT32(_addr + 4, x); }
+ void setAnimPc(int32 x) { WRITE_LE_UINT32(_addr + 8, x); }
+};
// speech structure - contains fields used by speech scripts & text output
-struct ObjectSpeech {
- int32 pen; // colour to use for body of characters
- int32 width; // max width of text sprite
- int32 command; // speech script command id
- int32 ins1; // speech script instruction parameters (may need more now?)
- int32 ins2;
- int32 ins3;
- int32 ins4;
- int32 ins5;
- int32 wait_state; // 0 not waiting, 1 waiting for next speech command
-} GCC_PACK;
+class ObjectSpeech {
+ // int32 pen; // colour to use for body of characters
+ // int32 width; // max width of text sprite
+ // int32 command; // speech script command id
+ // int32 ins1; // speech script instruction parameters
+ // int32 ins2;
+ // int32 ins3;
+ // int32 ins4;
+ // int32 ins5;
+ // int32 wait_state; // 0 not waiting,
+ // 1 waiting for next speech command
+
+private:
+ byte *_addr;
+
+public:
+ ObjectSpeech(byte *addr) {
+ _addr = addr;
+ }
+
+ static const int size() {
+ return 36;
+ }
+
+ byte *data() {
+ return _addr;
+ }
+
+ int32 getPen() { return READ_LE_UINT32(_addr); }
+ int32 getWidth() { return READ_LE_UINT32(_addr + 4); }
+ int32 getCommand() { return READ_LE_UINT32(_addr + 8); }
+ int32 getIns1() { return READ_LE_UINT32(_addr + 12); }
+ int32 getIns2() { return READ_LE_UINT32(_addr + 16); }
+ int32 getIns3() { return READ_LE_UINT32(_addr + 20); }
+ int32 getIns4() { return READ_LE_UINT32(_addr + 24); }
+ int32 getIns5() { return READ_LE_UINT32(_addr + 28); }
+ int32 getWaitState() { return READ_LE_UINT32(_addr + 32); }
+
+ void setPen(int32 x) { WRITE_LE_UINT32(_addr, x); }
+ void setWidth(int32 x) { WRITE_LE_UINT32(_addr + 4, x); }
+ void setCommand(int32 x) { WRITE_LE_UINT32(_addr + 8, x); }
+ void setIns1(int32 x) { WRITE_LE_UINT32(_addr + 12, x); }
+ void setIns2(int32 x) { WRITE_LE_UINT32(_addr + 16, x); }
+ void setIns3(int32 x) { WRITE_LE_UINT32(_addr + 20, x); }
+ void setIns4(int32 x) { WRITE_LE_UINT32(_addr + 24, x); }
+ void setIns5(int32 x) { WRITE_LE_UINT32(_addr + 28, x); }
+ void setWaitState(int32 x) { WRITE_LE_UINT32(_addr + 32, x); }
+};
// mega structure - contains fields used for mega-character & mega-set
// processing
-struct ObjectMega {
- int32 NOT_USED_1; // only free roaming megas need to check this before registering their graphics for drawing
- int32 NOT_USED_2; // id of floor on which we are standing
- int32 NOT_USED_3; // id of object which we are getting to
- int32 NOT_USED_4; // pixel distance to stand from player character when in conversation
- int32 currently_walking; // number given us by the auto router
- int32 walk_pc; // current frame number of walk-anim
- int32 scale_a; // current scale factors, taken from floor data
- int32 scale_b;
- int32 feet_x; // mega feet coords - frame-offsets are added to these position mega frames
- int32 feet_y;
- int32 current_dir; // current dirction faced by mega; used by autorouter to determine turns required
- int32 NOT_USED_5; // means were currently avoiding a collision (see fnWalk)
- int32 megaset_res; // resource id of mega-set file
- int32 NOT_USED_6; // NOT USED
-} GCC_PACK;
+class ObjectMega {
+ // int32 NOT_USED_1; // only free roaming megas need to
+ // check this before registering their
+ // graphics for drawing
+ // int32 NOT_USED_2; // id of floor on which we are standing
+ // int32 NOT_USED_3; // id of object which we are getting to
+ // int32 NOT_USED_4; // pixel distance to stand from player
+ // character when in conversation
+ // int32 currently_walking; // number given us by the auto router
+ // int32 walk_pc; // current frame number of walk-anim
+ // int32 scale_a; // current scale factors, taken from
+ // int32 scale_b; // floor data
+ // int32 feet_x; // mega feet coords - frame-offsets are
+ // int32 feet_y; // added to these position mega frames
+ // int32 current_dir; // current dirction faced by mega; used
+ // by autorouter to determine turns
+ // required
+ // int32 NOT_USED_5; // means were currently avoiding a
+ // collision (see fnWalk)
+ // int32 megaset_res; // resource id of mega-set file
+ // int32 NOT_USED_6; // NOT USED
+
+private:
+ byte *_addr;
+
+public:
+ ObjectMega(byte *addr) {
+ _addr = addr;
+ }
+
+ static const int size() {
+ return 56;
+ }
+
+ byte *data() {
+ return _addr;
+ }
+
+ int32 getIsWalking() { return READ_LE_UINT32(_addr + 16); }
+ int32 getWalkPc() { return READ_LE_UINT32(_addr + 20); }
+ int32 getScaleA() { return READ_LE_UINT32(_addr + 24); }
+ int32 getScaleB() { return READ_LE_UINT32(_addr + 28); }
+ int32 getFeetX() { return READ_LE_UINT32(_addr + 32); }
+ int32 getFeetY() { return READ_LE_UINT32(_addr + 36); }
+ int32 getCurDir() { return READ_LE_UINT32(_addr + 40); }
+ int32 getMegasetRes() { return READ_LE_UINT32(_addr + 48); }
+
+ void setIsWalking(int32 x) { WRITE_LE_UINT32(_addr + 16, x); }
+ void setWalkPc(int32 x) { WRITE_LE_UINT32(_addr + 20, x); }
+ void setScaleA(int32 x) { WRITE_LE_UINT32(_addr + 24, x); }
+ void setScaleB(int32 x) { WRITE_LE_UINT32(_addr + 28, x); }
+ void setFeetX(int32 x) { WRITE_LE_UINT32(_addr + 32, x); }
+ void setFeetY(int32 x) { WRITE_LE_UINT32(_addr + 36, x); }
+ void setCurDir(int32 x) { WRITE_LE_UINT32(_addr + 40, x); }
+ void setMegasetRes(int32 x) { WRITE_LE_UINT32(_addr + 48, x); }
+
+ int32 calcScale() {
+ // Calc scale at which to print the sprite, based on feet
+ // y-coord & scaling constants (NB. 'scale' is actually
+ // 256 * true_scale, to maintain accuracy)
+
+ // Ay+B gives 256 * scale ie. 256 * 256 * true_scale for even
+ // better accuracy, ie. scale = (Ay + B) / 256
+ return (getScaleA() * getFeetY() + getScaleB()) / 256;
+ }
+};
// walk-data structure - contains details of layout of frames in the
// mega-set, and how they are to be used
-struct ObjectWalkdata {
+struct ObjectWalkdata {
int32 nWalkFrames; // no. of frames per walk-cycle
int32 usingStandingTurnFrames; // 0 = no 1 = yes
int32 usingWalkingTurnFrames; // 0 = no 1 = yes
@@ -124,11 +282,59 @@ struct ObjectWalkdata {
int32 leadingLeg[8]; // leading leg for walk in each direction (0 = left 1 = right)
int32 dx[8 * (12 + 1)]; // walk step distances in x direction
int32 dy[8 * (12 + 1)]; // walk step distances in y direction
-} GCC_PACK;
-#if !defined(__GNUC__)
- #pragma END_PACK_STRUCTS
-#endif
+ static const int size() {
+ return 916;
+ }
+
+ void read(byte *addr) {
+ Common::MemoryReadStream readS(addr, size());
+
+ nWalkFrames = readS.readUint32LE();
+ usingStandingTurnFrames = readS.readUint32LE();
+ usingWalkingTurnFrames = readS.readUint32LE();
+ usingSlowInFrames = readS.readUint32LE();
+ usingSlowOutFrames = readS.readUint32LE();
+
+ int i;
+
+ for (i = 0; i < ARRAYSIZE(nSlowInFrames); i++)
+ nSlowInFrames[i] = readS.readUint32LE();
+
+ for (i = 0; i < ARRAYSIZE(leadingLeg); i++)
+ leadingLeg[i] = readS.readUint32LE();
+
+ for (i = 0; i < ARRAYSIZE(dx); i++)
+ dx[i] = readS.readUint32LE();
+
+ for (i = 0; i < ARRAYSIZE(dy); i++)
+ dy[i] = readS.readUint32LE();
+ }
+
+ void write(byte *addr) {
+ Common::MemoryWriteStream writeS(addr, size());
+
+ writeS.writeUint32LE(nWalkFrames);
+ writeS.writeUint32LE(usingStandingTurnFrames);
+ writeS.writeUint32LE(usingWalkingTurnFrames);
+ writeS.writeUint32LE(usingSlowInFrames);
+ writeS.writeUint32LE(usingSlowOutFrames);
+
+ int i;
+
+ for (i = 0; i < ARRAYSIZE(nSlowInFrames); i++)
+ writeS.writeUint32LE(nSlowInFrames[i]);
+
+ for (i = 0; i < ARRAYSIZE(leadingLeg); i++)
+ writeS.writeUint32LE(leadingLeg[i]);
+
+ for (i = 0; i < ARRAYSIZE(dx); i++)
+ writeS.writeUint32LE(dx[i]);
+
+ for (i = 0; i < ARRAYSIZE(dy); i++)
+ writeS.writeUint32LE(dy[i]);
+ }
+};
} // End of namespace Sword2
diff --git a/sword2/protocol.cpp b/sword2/protocol.cpp
index 872b7d8063..f93f1f0b3c 100644
--- a/sword2/protocol.cpp
+++ b/sword2/protocol.cpp
@@ -30,9 +30,11 @@ namespace Sword2 {
*/
byte *Sword2Engine::fetchPalette(byte *screenFile) {
- MultiScreenHeader *mscreenHeader = (MultiScreenHeader *)(screenFile + sizeof(StandardHeader));
+ MultiScreenHeader mscreenHeader;
- byte *palette = (byte *)mscreenHeader + mscreenHeader->palette;
+ mscreenHeader.read(screenFile + ResHeader::size());
+
+ byte *palette = screenFile + ResHeader::size() + mscreenHeader.palette;
// Always set colour 0 to black, because while most background screen
// palettes have a bright colour 0 it should come out as black in the
@@ -52,9 +54,11 @@ byte *Sword2Engine::fetchPalette(byte *screenFile) {
*/
byte *Sword2Engine::fetchPaletteMatchTable(byte *screenFile) {
- MultiScreenHeader *mscreenHeader = (MultiScreenHeader *)(screenFile + sizeof(StandardHeader));
+ MultiScreenHeader mscreenHeader;
+
+ mscreenHeader.read(screenFile + ResHeader::size());
- return (byte *)mscreenHeader + mscreenHeader->paletteTable;
+ return screenFile + ResHeader::size() + mscreenHeader.paletteTable;
}
/**
@@ -62,11 +66,12 @@ byte *Sword2Engine::fetchPaletteMatchTable(byte *screenFile) {
* the screen file.
*/
-ScreenHeader *Sword2Engine::fetchScreenHeader(byte *screenFile) {
- MultiScreenHeader *mscreenHeader = (MultiScreenHeader *)(screenFile + sizeof(StandardHeader));
- ScreenHeader *screenHeader = (ScreenHeader *)((byte *)mscreenHeader + mscreenHeader->screen);
+byte *Sword2Engine::fetchScreenHeader(byte *screenFile) {
+ MultiScreenHeader mscreenHeader;
+
+ mscreenHeader.read(screenFile + ResHeader::size());
- return screenHeader;
+ return screenFile + ResHeader::size() + mscreenHeader.screen;
}
/**
@@ -75,19 +80,19 @@ ScreenHeader *Sword2Engine::fetchScreenHeader(byte *screenFile) {
* the number of layers on this screen.
*/
-LayerHeader *Sword2Engine::fetchLayerHeader(byte *screenFile, uint16 layerNo) {
+byte *Sword2Engine::fetchLayerHeader(byte *screenFile, uint16 layerNo) {
#ifdef SWORD2_DEBUG
- ScreenHeader *screenHead = fetchScreenHeader(screenFile);
+ ScreenHeader screenHead;
- if (layerNo > screenHead->noLayers - 1)
- error("fetchLayerHeader(%d) invalid layer number!", layerNo);
+ screenHead.read(fetchScreenHeader(screenFile));
+ assert(layerNo < screenHead.noLayers);
#endif
- MultiScreenHeader *mscreenHeader = (MultiScreenHeader *)(screenFile + sizeof(StandardHeader));
+ MultiScreenHeader mscreenHeader;
- LayerHeader *layerHeader = (LayerHeader *)((byte *)mscreenHeader + mscreenHeader->layers + (layerNo * sizeof(LayerHeader)));
+ mscreenHeader.read(screenFile + ResHeader::size());
- return layerHeader;
+ return screenFile + ResHeader::size() + mscreenHeader.layers + layerNo * LayerHeader::size();
}
/**
@@ -96,9 +101,11 @@ LayerHeader *Sword2Engine::fetchLayerHeader(byte *screenFile, uint16 layerNo) {
*/
byte *Sword2Engine::fetchShadingMask(byte *screenFile) {
- MultiScreenHeader *mscreenHeader = (MultiScreenHeader *)(screenFile + sizeof(StandardHeader));
+ MultiScreenHeader mscreenHeader;
- return (byte *)mscreenHeader + mscreenHeader->maskOffset;
+ mscreenHeader.read(screenFile + ResHeader::size());
+
+ return screenFile + ResHeader::size() + mscreenHeader.maskOffset;
}
/**
@@ -106,8 +113,8 @@ byte *Sword2Engine::fetchShadingMask(byte *screenFile) {
* anim file.
*/
-AnimHeader *Sword2Engine::fetchAnimHeader(byte *animFile) {
- return (AnimHeader *)(animFile + sizeof(StandardHeader));
+byte *Sword2Engine::fetchAnimHeader(byte *animFile) {
+ return animFile + ResHeader::size();
}
/**
@@ -116,15 +123,17 @@ AnimHeader *Sword2Engine::fetchAnimHeader(byte *animFile) {
* number exceeds the number of frames in this anim.
*/
-CdtEntry *Sword2Engine::fetchCdtEntry(byte *animFile, uint16 frameNo) {
- AnimHeader *animHead = fetchAnimHeader(animFile);
-
+byte *Sword2Engine::fetchCdtEntry(byte *animFile, uint16 frameNo) {
#ifdef SWORD2_DEBUG
+ AnimHeader animHead;
+
+ animHead.read(fetchAnimHeader(animFile));
+
if (frameNo > animHead->noAnimFrames - 1)
- error("fetchCdtEntry(animFile,%d) - anim only %d frames", frameNo, animHead->noAnimFrames);
+ error("fetchCdtEntry(animFile,%d) - anim only %d frames", frameNo, animHead.noAnimFrames);
#endif
- return (CdtEntry *)((byte *)animHead + sizeof(AnimHeader) + frameNo * sizeof(CdtEntry));
+ return fetchAnimHeader(animFile) + AnimHeader::size() + frameNo * CdtEntry::size();
}
/**
@@ -133,60 +142,54 @@ CdtEntry *Sword2Engine::fetchCdtEntry(byte *animFile, uint16 frameNo) {
* exceeds the number of frames in this anim
*/
-FrameHeader *Sword2Engine::fetchFrameHeader(byte *animFile, uint16 frameNo) {
+byte *Sword2Engine::fetchFrameHeader(byte *animFile, uint16 frameNo) {
// required address = (address of the start of the anim header) + frameOffset
- return (FrameHeader *)(animFile + sizeof(StandardHeader) + fetchCdtEntry(animFile, frameNo)->frameOffset);
+ CdtEntry cdt;
+
+ cdt.read(fetchCdtEntry(animFile, frameNo));
+
+ return animFile + ResHeader::size() + cdt.frameOffset;
}
/**
* Returns a pointer to the requested parallax layer data.
*/
-Parallax *Sword2Engine::fetchBackgroundParallaxLayer(byte *screenFile, int layer) {
- MultiScreenHeader *mscreenHeader = (MultiScreenHeader *)(screenFile + sizeof(StandardHeader));
+byte *Sword2Engine::fetchBackgroundParallaxLayer(byte *screenFile, int layer) {
+ MultiScreenHeader mscreenHeader;
-#ifdef SWORD2_DEBUG
- if (mscreenHeader->bg_parallax[layer] == 0)
- error("fetchBackgroundParallaxLayer(%d) - No parallax layer exists", layer);
-#endif
+ mscreenHeader.read(screenFile + ResHeader::size());
+ assert(mscreenHeader.bg_parallax[layer]);
- return (Parallax *)((byte *)mscreenHeader + mscreenHeader->bg_parallax[layer]);
+ return screenFile + ResHeader::size() + mscreenHeader.bg_parallax[layer];
}
-Parallax *Sword2Engine::fetchBackgroundLayer(byte *screenFile) {
- MultiScreenHeader *mscreenHeader = (MultiScreenHeader *)(screenFile + sizeof(StandardHeader));
+byte *Sword2Engine::fetchBackgroundLayer(byte *screenFile) {
+ MultiScreenHeader mscreenHeader;
-#ifdef SWORD2_DEBUG
- if (mscreenHeader->screen == 0)
- error("fetchBackgroundLayer (%d) - No background layer exists");
-#endif
+ mscreenHeader.read(screenFile + ResHeader::size());
+ assert(mscreenHeader.screen);
- return (Parallax *)((byte *)mscreenHeader + mscreenHeader->screen + sizeof(ScreenHeader));
+ return screenFile + ResHeader::size() + mscreenHeader.screen + ScreenHeader::size();
}
-Parallax *Sword2Engine::fetchForegroundParallaxLayer(byte *screenFile, int layer) {
- MultiScreenHeader *mscreenHeader = (MultiScreenHeader *)(screenFile + sizeof(StandardHeader));
+byte *Sword2Engine::fetchForegroundParallaxLayer(byte *screenFile, int layer) {
+ MultiScreenHeader mscreenHeader;
-#ifdef SWORD2_DEBUG
- if (mscreenHeader->fg_parallax[layer] == 0)
- error("fetchForegroundParallaxLayer(%d) - No parallax layer exists", layer);
-#endif
+ mscreenHeader.read(screenFile + ResHeader::size());
+ assert(mscreenHeader.fg_parallax[layer]);
- return (Parallax *)((byte *)mscreenHeader + mscreenHeader->fg_parallax[layer]);
+ return screenFile + ResHeader::size() + mscreenHeader.fg_parallax[layer];
}
-static byte errorLine[128];
-
byte *Sword2Engine::fetchTextLine(byte *file, uint32 text_line) {
- StandardHeader *fileHeader;
- uint32 *point;
-
- TextHeader *text_header = (TextHeader *)(file + sizeof(StandardHeader));
+ TextHeader text_header;
+ static byte errorLine[128];
- if (text_line >= text_header->noOfLines) {
- fileHeader = (StandardHeader *)file;
- sprintf((char *)errorLine, "xxMissing line %d of %s (only 0..%d)", text_line, fileHeader->name, text_header->noOfLines - 1);
+ text_header.read(file + ResHeader::size());
+ if (text_line >= text_header.noOfLines) {
+ sprintf((char *)errorLine, "xxMissing line %d of %s (only 0..%d)", text_line, _resman->fetchName(file), text_header.noOfLines - 1);
// first 2 chars are NULL so that actor-number comes out as '0'
errorLine[0] = 0;
@@ -194,27 +197,19 @@ byte *Sword2Engine::fetchTextLine(byte *file, uint32 text_line) {
return errorLine;
}
- // point to the lookup table
- point = (uint32 *)text_header + 1;
+ // The "number of lines" field is followed by a lookup table
- return (byte *)(file + READ_LE_UINT32(point + text_line));
+ return file + READ_LE_UINT32(file + ResHeader::size() + 4 + 4 * text_line);
}
-
// Used for testing text & speech (see fnISpeak in speech.cpp)
bool Sword2Engine::checkTextLine(byte *file, uint32 text_line) {
- TextHeader *text_header = (TextHeader *)(file + sizeof(StandardHeader));
-
- return text_line < text_header->noOfLines;
-}
+ TextHeader text_header;
-byte *Sword2Engine::fetchObjectName(int32 resourceId, byte *buf) {
- StandardHeader *header = (StandardHeader *)_resman->openResource(resourceId);
+ text_header.read(file + ResHeader::size());
- memcpy(buf, header->name, NAME_LEN);
- _resman->closeResource(resourceId);
- return buf;
+ return text_line < text_header.noOfLines;
}
} // End of namespace Sword2
diff --git a/sword2/resman.cpp b/sword2/resman.cpp
index 70bc5cf7df..dfb6d1690e 100644
--- a/sword2/resman.cpp
+++ b/sword2/resman.cpp
@@ -43,18 +43,10 @@ namespace Sword2 {
// resource.tab which is a table which tells us which cluster a resource
// is located in and the number within the cluster
-#if !defined(__GNUC__)
- #pragma START_PACK_STRUCTS
-#endif
-
struct CdInf {
uint8 clusterName[20]; // Null terminated cluster name.
uint8 cd; // Cd cluster is on and whether it is on the local drive or not.
-} GCC_PACK;
-
-#if !defined(__GNUC__)
- #pragma END_PACK_STRUCTS
-#endif
+};
ResourceManager::ResourceManager(Sword2Engine *vm) {
_vm = vm;
@@ -201,192 +193,6 @@ ResourceManager::~ResourceManager() {
free(_resConvTable);
}
-// Quick macro to make swapping in-place easier to write
-
-#define SWAP16(x) x = SWAP_BYTES_16(x)
-#define SWAP32(x) x = SWAP_BYTES_32(x)
-
-void convertEndian(byte *file, uint32 len) {
- int i;
- StandardHeader *hdr = (StandardHeader *)file;
-
- file += sizeof(StandardHeader);
-
- SWAP32(hdr->compSize);
- SWAP32(hdr->decompSize);
-
- switch (hdr->fileType) {
- case ANIMATION_FILE: {
- AnimHeader *animHead = (AnimHeader *)file;
-
- SWAP16(animHead->noAnimFrames);
- SWAP16(animHead->feetStartX);
- SWAP16(animHead->feetStartY);
- SWAP16(animHead->feetEndX);
- SWAP16(animHead->feetEndY);
- SWAP16(animHead->blend);
-
- CdtEntry *cdtEntry = (CdtEntry *)(file + sizeof(AnimHeader));
- for (i = 0; i < animHead->noAnimFrames; i++, cdtEntry++) {
- SWAP16(cdtEntry->x);
- SWAP16(cdtEntry->y);
- SWAP32(cdtEntry->frameOffset);
-
- FrameHeader *frameHeader = (FrameHeader *)(file + cdtEntry->frameOffset);
- // Quick trick to prevent us from incorrectly applying the endian
- // fixes multiple times. This assumes that frames are less than 1 MB
- // and have height/width less than 4096.
- if ((frameHeader->compSize & 0xFFF00000) ||
- (frameHeader->width & 0xF000) ||
- (frameHeader->height & 0xF000)) {
- SWAP32(frameHeader->compSize);
- SWAP16(frameHeader->width);
- SWAP16(frameHeader->height);
- }
- }
- break;
- }
- case SCREEN_FILE: {
- MultiScreenHeader *mscreenHeader = (MultiScreenHeader *)file;
-
- SWAP32(mscreenHeader->palette);
- SWAP32(mscreenHeader->bg_parallax[0]);
- SWAP32(mscreenHeader->bg_parallax[1]);
- SWAP32(mscreenHeader->screen);
- SWAP32(mscreenHeader->fg_parallax[0]);
- SWAP32(mscreenHeader->fg_parallax[1]);
- SWAP32(mscreenHeader->layers);
- SWAP32(mscreenHeader->paletteTable);
- SWAP32(mscreenHeader->maskOffset);
-
- // screenHeader
- ScreenHeader *screenHeader = (ScreenHeader *)(file + mscreenHeader->screen);
-
- SWAP16(screenHeader->width);
- SWAP16(screenHeader->height);
- SWAP16(screenHeader->noLayers);
-
- // layerHeader
- LayerHeader *layerHeader = (LayerHeader *)(file + mscreenHeader->layers);
- for (i = 0; i < screenHeader->noLayers; i++, layerHeader++) {
- SWAP16(layerHeader->x);
- SWAP16(layerHeader->y);
- SWAP16(layerHeader->width);
- SWAP16(layerHeader->height);
- SWAP32(layerHeader->maskSize);
- SWAP32(layerHeader->offset);
- }
-
- // backgroundParallaxLayer
- Parallax *parallax;
- int offset;
- offset = mscreenHeader->bg_parallax[0];
- if (offset > 0) {
- parallax = (Parallax *)(file + offset);
- SWAP16(parallax->w);
- SWAP16(parallax->h);
- }
-
- offset = mscreenHeader->bg_parallax[1];
- if (offset > 0) {
- parallax = (Parallax *)(file + offset);
- SWAP16(parallax->w);
- SWAP16(parallax->h);
- }
-
- // backgroundLayer
- offset = mscreenHeader->screen + sizeof(ScreenHeader);
- if (offset > 0) {
- parallax = (Parallax *)(file + offset);
- SWAP16(parallax->w);
- SWAP16(parallax->h);
- }
-
- // foregroundParallaxLayer
- offset = mscreenHeader->fg_parallax[0];
- if (offset > 0) {
- parallax = (Parallax *)(file + offset);
- SWAP16(parallax->w);
- SWAP16(parallax->h);
- }
-
- offset = mscreenHeader->fg_parallax[1];
- if (offset > 0) {
- parallax = (Parallax *)(file + offset);
- SWAP16(parallax->w);
- SWAP16(parallax->h);
- }
- break;
- }
- case GAME_OBJECT: {
- ObjectHub *objectHub = (ObjectHub *)file;
-
- objectHub->type = (int) SWAP_BYTES_32(objectHub->type);
- SWAP32(objectHub->logic_level);
-
- for (i = 0; i < TREE_SIZE; i++) {
- SWAP32(objectHub->logic[i]);
- SWAP32(objectHub->script_id[i]);
- SWAP32(objectHub->script_pc[i]);
- }
- break;
- }
- case WALK_GRID_FILE: {
- WalkGridHeader *walkGridHeader = (WalkGridHeader *)file;
-
- SWAP32(walkGridHeader->numBars);
- SWAP32(walkGridHeader->numNodes);
-
- BarData *barData = (BarData *)(file + sizeof(WalkGridHeader));
- for (i = 0; i < walkGridHeader->numBars; i++) {
- SWAP16(barData->x1);
- SWAP16(barData->y1);
- SWAP16(barData->x2);
- SWAP16(barData->y2);
- SWAP16(barData->xmin);
- SWAP16(barData->ymin);
- SWAP16(barData->xmax);
- SWAP16(barData->ymax);
- SWAP16(barData->dx);
- SWAP16(barData->dy);
- SWAP32(barData->co);
- barData++;
- }
-
- uint16 *node = (uint16 *)(file + sizeof(WalkGridHeader) + walkGridHeader->numBars * sizeof(BarData));
- for (i = 0; i < walkGridHeader->numNodes * 2; i++) {
- SWAP16(*node);
- node++;
- }
-
- break;
- }
- case GLOBAL_VAR_FILE:
- break;
- case PARALLAX_FILE_null:
- break;
- case RUN_LIST: {
- uint32 *list = (uint32 *)file;
- while (*list) {
- SWAP32(*list);
- list++;
- }
- break;
- }
- case TEXT_FILE: {
- TextHeader *textHeader = (TextHeader *)file;
- SWAP32(textHeader->noOfLines);
- break;
- }
- case SCREEN_MANAGER:
- break;
- case MOUSE_FILE:
- break;
- case ICON_FILE:
- break;
- }
-}
-
/**
* Returns the address of a resource. Loads if not in memory. Retains a count.
*/
@@ -440,12 +246,11 @@ byte *ResourceManager::openResource(uint32 res, bool dump) {
file->read(_resList[res].ptr, len);
if (dump) {
- StandardHeader *header = (StandardHeader *)_resList[res].ptr;
char buf[256];
const char *tag;
Common::File out;
- switch (header->fileType) {
+ switch (fetchType(_resList[res].ptr)) {
case ANIMATION_FILE:
tag = "anim";
break;
@@ -508,10 +313,6 @@ byte *ResourceManager::openResource(uint32 res, bool dump) {
_usedMem += len;
checkMemUsage();
-
-#ifdef SCUMM_BIG_ENDIAN
- convertEndian(_resList[res].ptr, len);
-#endif
} else if (_resList[res].refCount == 0)
removeFromCacheList(_resList + res);
@@ -732,10 +533,8 @@ void ResourceManager::killAll(bool wantInfo) {
continue;
if (_resList[i].ptr) {
- StandardHeader *header = (StandardHeader *)_resList[i].ptr;
-
if (wantInfo)
- Debug_Printf("Nuked %5d: %s\n", i, header->name);
+ Debug_Printf("Nuked %5d: %s\n", i, fetchName(_resList[i].ptr));
remove(i);
nuked++;
@@ -764,11 +563,9 @@ void ResourceManager::killAllObjects(bool wantInfo) {
continue;
if (_resList[i].ptr) {
- StandardHeader *header = (StandardHeader *)_resList[i].ptr;
-
- if (header->fileType == GAME_OBJECT) {
+ if (fetchType(_resList[i].ptr) == GAME_OBJECT) {
if (wantInfo)
- Debug_Printf("Nuked %5d: %s\n", i, header->name);
+ Debug_Printf("Nuked %5d: %s\n", i, fetchName(_resList[i].ptr));
remove(i);
nuked++;
diff --git a/sword2/resman.h b/sword2/resman.h
index e9d1e40c4b..7fabf907c7 100644
--- a/sword2/resman.h
+++ b/sword2/resman.h
@@ -91,6 +91,29 @@ public:
bool checkValid(uint32 res);
uint32 fetchLen(uint32 res);
+ uint8 fetchType(uint32 res) {
+ byte *ptr = openResource(res);
+ uint8 type = ptr[0];
+ closeResource(res);
+
+ return type;
+ }
+
+ uint8 fetchType(byte *ptr) {
+ return ptr[0];
+ }
+
+ byte *fetchName(uint32 res, byte *buf) {
+ byte *ptr = openResource(res);
+ memcpy(buf, ptr + 10, NAME_LEN);
+ closeResource(res);
+
+ return buf;
+ }
+
+ byte *fetchName(byte *ptr) {
+ return ptr + 10;
+ }
// Prompts the user for the specified CD.
void getCd(int cd);
diff --git a/sword2/router.cpp b/sword2/router.cpp
index 663001e557..ab3c2a9f66 100644
--- a/sword2/router.cpp
+++ b/sword2/router.cpp
@@ -74,6 +74,7 @@
****************************************************************************/
#include "common/stdafx.h"
+#include "common/stream.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
#include "sword2/logic.h"
@@ -82,8 +83,24 @@
namespace Sword2 {
+//----------------------------------------------------------
+// (4) WALK-GRID FILES
+//----------------------------------------------------------
+// a walk-grid file consists of:
+//
+// standard file header
+// walk-grid file header
+// walk-grid data
+
+// Walk-Grid Header - taken directly from old "header.h" in STD_INC
+
+struct WalkGridHeader {
+ int32 numBars; // number of bars on the floor
+ int32 numNodes; // number of nodes
+};
+
uint8 Router::returnSlotNo(uint32 megaId) {
- if (Logic::_scriptVars[ID] == CUR_PLAYER_ID) {
+ if (_vm->_logic->readVar(ID) == CUR_PLAYER_ID) {
// George (8)
return 0;
} else {
@@ -101,7 +118,7 @@ void Router::allocateRouteMem() {
// in middle of route, the old route will be safely cleared from
// memory just before they create a new one
- slotNo = returnSlotNo(Logic::_scriptVars[ID]);
+ slotNo = returnSlotNo(_vm->_logic->readVar(ID));
// if this slot is already used, then it can't be needed any more
// because this id is creating a new route!
@@ -125,13 +142,13 @@ void Router::allocateRouteMem() {
}
WalkData *Router::getRouteMem() {
- uint8 slotNo = returnSlotNo(Logic::_scriptVars[ID]);
+ uint8 slotNo = returnSlotNo(_vm->_logic->readVar(ID));
return (WalkData *)_routeSlots[slotNo];
}
void Router::freeRouteMem() {
- uint8 slotNo = returnSlotNo(Logic::_scriptVars[ID]);
+ uint8 slotNo = returnSlotNo(_vm->_logic->readVar(ID));
free(_routeSlots[slotNo]);
_routeSlots[slotNo] = NULL;
@@ -144,7 +161,7 @@ void Router::freeAllRouteMem() {
}
}
-int32 Router::routeFinder(ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, int32 x, int32 y, int32 dir) {
+int32 Router::routeFinder(byte *ob_mega, byte *ob_walkdata, int32 x, int32 y, int32 dir) {
/*********************************************************************
* RouteFinder.C polygon router with modular walks
* 21 august 94
@@ -677,8 +694,8 @@ void Router::slidyPath() {
// SLOW IN
bool Router::addSlowInFrames(WalkData *walkAnim) {
- if (_usingSlowInFrames && _modularPath[1].num > 0) {
- for (uint slowInFrameNo = 0; slowInFrameNo < _numberOfSlowInFrames[_currentDir]; slowInFrameNo++) {
+ if (_walkData.usingSlowInFrames && _modularPath[1].num > 0) {
+ for (int slowInFrameNo = 0; slowInFrameNo < _walkData.nSlowInFrames[_currentDir]; slowInFrameNo++) {
walkAnim[_stepCount].frame = _firstSlowInFrame[_currentDir] + slowInFrameNo;
walkAnim[_stepCount].step = 0;
walkAnim[_stepCount].dir = _currentDir;
@@ -692,11 +709,13 @@ bool Router::addSlowInFrames(WalkData *walkAnim) {
return false;
}
-void Router::earlySlowOut(ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata) {
+void Router::earlySlowOut(byte *ob_mega, byte *ob_walkdata) {
int32 slowOutFrameNo;
int32 walk_pc;
WalkData *walkAnim;
+ ObjectMega obMega(ob_mega);
+
debug(5, "EARLY SLOW-OUT");
loadWalkData(ob_walkdata);
@@ -709,12 +728,12 @@ void Router::earlySlowOut(ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata) {
debug(5, "_firstSlowOutFrame = %d", _firstSlowOutFrame);
debug(5, "********************************");
- walk_pc = ob_mega->walk_pc;
+ walk_pc = obMega.getWalkPc();
walkAnim = getRouteMem();
// if this mega does actually have slow-out frames
- if (_usingSlowOutFrames) {
+ if (_walkData.usingSlowOutFrames) {
// overwrite the next step (half a cycle) of the walk
// (ie .step - 0..5)
@@ -787,7 +806,7 @@ void Router::addSlowOutFrames(WalkData *walkAnim) {
// if the mega did actually walk, we overwrite the last step (half a
// cycle) with slow-out frames + add any necessary stationary frames
- if (_usingSlowOutFrames && _lastCount >= _framesPerStep) {
+ if (_walkData.usingSlowOutFrames && _lastCount >= _framesPerStep) {
// place stop frames here
// slowdown at the end of the last walk
@@ -904,7 +923,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
// rotate to new walk direction
// for george and nico put in a head turn at the start
- if (_usingStandingTurnFrames) {
+ if (_walkData.usingStandingTurnFrames) {
// new frames for turn frames 29oct95jps
if (turnDir < 0)
module = _firstStandingTurnLeftFrame + lastDir;
@@ -964,7 +983,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
// (0 = left; 1 = right)
- if (_leadingLeg[_currentDir] == 0) {
+ if (_walkData.leadingLeg[_currentDir] == 0) {
// start the walk on the left leg (ie. at beginning of the
// first step of the walk cycle)
left = 0;
@@ -1010,8 +1029,8 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
scale = (_scaleA * _moduleY + _scaleB);
do {
- module16X += _dx[module] * scale;
- module16Y += _dy[module] * scale;
+ module16X += _walkData.dx[module] * scale;
+ module16Y += _walkData.dy[module] * scale;
_moduleX = module16X >> 16;
_moduleY = module16Y >> 16;
walkAnim[_stepCount].frame = module;
@@ -1109,7 +1128,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
// check each turn condition in turn
// only for george
- if (lastDir != 99 && _currentDir != 99 && _usingWalkingTurnFrames) {
+ if (lastDir != 99 && _currentDir != 99 && _walkData.usingWalkingTurnFrames) {
// 1 and -7 going right -1 and 7 going
// left
lastDir = _currentDir - lastDir;
@@ -1199,7 +1218,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
// rotate to target direction
// for george and nico put in a head turn at the start
- if (_usingStandingTurnFrames) {
+ if (_walkData.usingStandingTurnFrames) {
// new frames for turn frames 29oct95jps
if (turnDir < 0)
module = _firstStandingTurnLeftFrame + lastDir;
@@ -1410,7 +1429,7 @@ int32 Router::solidWalkAnimator(WalkData *walkAnim) {
// rotate to new walk direction
// for george and nico put in a head turn at the start
- if (_usingStandingTurnFrames) {
+ if (_walkData.usingStandingTurnFrames) {
// new frames for turn frames 29oct95jps
if (turnDir < 0)
module = _firstStandingTurnLeftFrame + lastDir;
@@ -1468,7 +1487,7 @@ int32 Router::solidWalkAnimator(WalkData *walkAnim) {
// slow-in frames were drawn
// (0 = left; 1 = right)
- if (_leadingLeg[_currentDir] == 0) {
+ if (_walkData.leadingLeg[_currentDir] == 0) {
// start the walk on the left leg (ie. at beginning of the
// first step of the walk cycle)
left = 0;
@@ -1504,8 +1523,8 @@ int32 Router::solidWalkAnimator(WalkData *walkAnim) {
scale = (_scaleA * _moduleY + _scaleB);
do {
- module16X += _dx[module] * scale;
- module16Y += _dy[module] * scale;
+ module16X += _walkData.dx[module] * scale;
+ module16Y += _walkData.dy[module] * scale;
_moduleX = module16X >> 16;
_moduleY = module16Y >> 16;
walkAnim[_stepCount].frame = module;
@@ -1551,8 +1570,8 @@ int32 Router::solidWalkAnimator(WalkData *walkAnim) {
// walk
if (slowStart) {
- _stepCount -= _numberOfSlowInFrames[_currentDir];
- _lastCount -= _numberOfSlowInFrames[_currentDir];
+ _stepCount -= _walkData.nSlowInFrames[_currentDir];
+ _lastCount -= _walkData.nSlowInFrames[_currentDir];
slowStart = false;
}
@@ -1564,7 +1583,7 @@ int32 Router::solidWalkAnimator(WalkData *walkAnim) {
}
// check each turn condition in turn
- if (lastDir != 99 && _currentDir != 99 && _usingWalkingTurnFrames) {
+ if (lastDir != 99 && _currentDir != 99 && _walkData.usingWalkingTurnFrames) {
// only for george
// 1 and -7 going right -1 and
// 7 going left
@@ -2091,38 +2110,30 @@ int32 Router::checkTarget(int32 x, int32 y) {
// THE SETUP ROUTINES
-void Router::loadWalkData(ObjectWalkdata *ob_walkdata) {
+void Router::loadWalkData(byte *ob_walkdata) {
uint16 firstFrameOfDirection;
uint16 walkFrameNo;
uint32 frameCounter = 0; // starts at frame 0 of mega set
+ int i;
- _nWalkFrames = ob_walkdata->nWalkFrames;
- _usingStandingTurnFrames = ob_walkdata->usingStandingTurnFrames;
- _usingWalkingTurnFrames = ob_walkdata->usingWalkingTurnFrames;
- _usingSlowInFrames = ob_walkdata->usingSlowInFrames;
- _usingSlowOutFrames = ob_walkdata->usingSlowOutFrames;
+ _walkData.read(ob_walkdata);
// 0 = not using slow out frames; non-zero = using that many frames
// for each leading leg for each direction
- _numberOfSlowOutFrames = _usingSlowOutFrames;
+ _numberOfSlowOutFrames = _walkData.usingSlowOutFrames;
- memcpy(&_numberOfSlowInFrames[0], ob_walkdata->nSlowInFrames, NO_DIRECTIONS * sizeof(_numberOfSlowInFrames[0]));
- memcpy(&_leadingLeg[0], ob_walkdata->leadingLeg, NO_DIRECTIONS * sizeof(_leadingLeg[0]));
- memcpy(&_dx[0], ob_walkdata->dx, NO_DIRECTIONS * (_nWalkFrames + 1) * sizeof(_dx[0]));
- memcpy(&_dy[0], ob_walkdata->dy, NO_DIRECTIONS * (_nWalkFrames + 1) * sizeof(_dy[0]));
-
- for (int i = 0; i < NO_DIRECTIONS; i++) {
- firstFrameOfDirection = i * _nWalkFrames;
+ for (i = 0; i < NO_DIRECTIONS; i++) {
+ firstFrameOfDirection = i * _walkData.nWalkFrames;
_modX[i] = 0;
_modY[i] = 0;
- for (walkFrameNo = firstFrameOfDirection; walkFrameNo < firstFrameOfDirection + _nWalkFrames / 2; walkFrameNo++) {
+ for (walkFrameNo = firstFrameOfDirection; walkFrameNo < firstFrameOfDirection + _walkData.nWalkFrames / 2; walkFrameNo++) {
// eg. _modX[0] is the sum of the x-step sizes for the
// first half of the walk cycle for direction 0
- _modX[i] += _dx[walkFrameNo];
- _modY[i] += _dy[walkFrameNo];
+ _modX[i] += _walkData.dx[walkFrameNo];
+ _modY[i] += _walkData.dy[walkFrameNo];
}
}
@@ -2131,8 +2142,8 @@ void Router::loadWalkData(ObjectWalkdata *ob_walkdata) {
// interpret the walk data
- _framesPerStep = _nWalkFrames / 2;
- _framesPerChar = _nWalkFrames * NO_DIRECTIONS;
+ _framesPerStep = _walkData.nWalkFrames / 2;
+ _framesPerChar = _walkData.nWalkFrames * NO_DIRECTIONS;
// offset pointers added Oct 30 95 JPS
// mega id references removed 16sep96 by JEL
@@ -2155,7 +2166,7 @@ void Router::loadWalkData(ObjectWalkdata *ob_walkdata) {
// standing turn-left frames come after the standing turn-right frames
// one for each direction
- if (_usingStandingTurnFrames) {
+ if (_walkData.usingStandingTurnFrames) {
_firstStandingTurnLeftFrame = frameCounter;
frameCounter += NO_DIRECTIONS;
@@ -2171,7 +2182,7 @@ void Router::loadWalkData(ObjectWalkdata *ob_walkdata) {
// walking left-turn frames come after the stand frames
// walking right-turn frames come after the walking left-turn frames
- if (_usingWalkingTurnFrames) {
+ if (_walkData.usingWalkingTurnFrames) {
_firstWalkingTurnLeftFrame = frameCounter;
frameCounter += _framesPerChar;
@@ -2185,21 +2196,21 @@ void Router::loadWalkData(ObjectWalkdata *ob_walkdata) {
// SLOW-IN FRAMES - OPTIONAL!
// slow-in frames come after the walking right-turn frames
- if (_usingSlowInFrames) {
+ if (_walkData.usingSlowInFrames) {
// Make note of frame number of first slow-in frame for each
// direction. There may be a different number of slow-in
// frames in each direction
- for (int i = 0; i < NO_DIRECTIONS; i++) {
+ for (i = 0; i < NO_DIRECTIONS; i++) {
_firstSlowInFrame[i] = frameCounter;
- frameCounter += _numberOfSlowInFrames[i];
+ frameCounter += _walkData.nSlowInFrames[i];
}
}
// SLOW-OUT FRAMES - OPTIONAL!
// slow-out frames come after the slow-in frames
- if (_usingSlowOutFrames)
+ if (_walkData.usingSlowOutFrames)
_firstSlowOutFrame = frameCounter;
}
@@ -2316,22 +2327,24 @@ void Router::extractRoute() {
return;
}
-void Router::setUpWalkGrid(ObjectMega *ob_mega, int32 x, int32 y, int32 dir) {
+void Router::setUpWalkGrid(byte *ob_mega, int32 x, int32 y, int32 dir) {
+ ObjectMega obMega(ob_mega);
+
// get walk grid file + extra grid into 'bars' & 'node' arrays
loadWalkGrid();
// copy the mega structure into the local variables for use in all
// subroutines
- _startX = ob_mega->feet_x;
- _startY = ob_mega->feet_y;
- _startDir = ob_mega->current_dir;
+ _startX = obMega.getFeetX();
+ _startY = obMega.getFeetY();
+ _startDir = obMega.getCurDir();
_targetX = x;
_targetY = y;
_targetDir = dir;
- _scaleA = ob_mega->scale_a;
- _scaleB = ob_mega->scale_b;
+ _scaleA = obMega.getScaleA();
+ _scaleB = obMega.getScaleB();
// mega's current position goes into first node
@@ -2383,8 +2396,7 @@ void Router::plotCross(int16 x, int16 y, uint8 colour) {
void Router::loadWalkGrid() {
WalkGridHeader floorHeader;
byte *fPolygrid;
- uint32 theseBars;
- uint32 theseNodes;
+ uint16 fPolygridLen;
_nBars = 0; // reset counts
_nNodes = 1; // leave node 0 for start-node
@@ -2394,37 +2406,47 @@ void Router::loadWalkGrid() {
// go through walkgrid list
for (int i = 0; i < MAX_WALKGRIDS; i++) {
if (_walkGridList[i]) {
+ int j;
+
// open walk grid file
fPolygrid = _vm->_resman->openResource(_walkGridList[i]);
- fPolygrid += sizeof(StandardHeader);
- memcpy((byte *)&floorHeader, fPolygrid, sizeof(WalkGridHeader));
- fPolygrid += sizeof(WalkGridHeader);
+ fPolygridLen = _vm->_resman->fetchLen(_walkGridList[i]);
- // how many bars & nodes are we getting from this
- // walkgrid file
+ Common::MemoryReadStream readS(fPolygrid, fPolygridLen);
- theseBars = floorHeader.numBars;
- theseNodes = floorHeader.numNodes;
+ readS.seek(ResHeader::size());
+
+ floorHeader.numBars = readS.readSint32LE();
+ floorHeader.numNodes = readS.readSint32LE();
// check that we're not going to exceed the max
// allowed in the complete walkgrid arrays
- assert(_nBars + theseBars < O_GRID_SIZE);
- assert(_nNodes + theseNodes < O_GRID_SIZE);
+ assert(_nBars + floorHeader.numBars < O_GRID_SIZE);
+ assert(_nNodes + floorHeader.numNodes < O_GRID_SIZE);
// lines
- memcpy((byte *)&_bars[_nBars], fPolygrid, theseBars * sizeof(BarData));
-
- // move pointer to start of node data
- fPolygrid += theseBars * sizeof(BarData);
+ for (j = 0; j < floorHeader.numBars; j++) {
+ _bars[_nBars + j].x1 = readS.readSint16LE();
+ _bars[_nBars + j].y1 = readS.readSint16LE();
+ _bars[_nBars + j].x2 = readS.readSint16LE();
+ _bars[_nBars + j].y2 = readS.readSint16LE();
+ _bars[_nBars + j].xmin = readS.readSint16LE();
+ _bars[_nBars + j].ymin = readS.readSint16LE();
+ _bars[_nBars + j].xmax = readS.readSint16LE();
+ _bars[_nBars + j].ymax = readS.readSint16LE();
+ _bars[_nBars + j].dx = readS.readSint16LE();
+ _bars[_nBars + j].dy = readS.readSint16LE();
+ _bars[_nBars + j].co = readS.readSint32LE();
+ }
// nodes
// leave node 0 for start node
- for (uint j = 0; j < theseNodes; j++) {
- memcpy((byte *)&_node[_nNodes + j].x, fPolygrid, 2 * sizeof(int16));
- fPolygrid += 2 * sizeof(int16);
+ for (j = 0; j < floorHeader.numNodes; j++) {
+ _node[_nNodes + j].x = readS.readSint16LE();
+ _node[_nNodes + j].y = readS.readSint16LE();
}
// close walk grid file
@@ -2433,8 +2455,8 @@ void Router::loadWalkGrid() {
// increment counts of total bars & nodes in whole
// walkgrid
- _nBars += theseBars;
- _nNodes += theseNodes;
+ _nBars += floorHeader.numBars;
+ _nNodes += floorHeader.numNodes;
}
}
}
diff --git a/sword2/router.h b/sword2/router.h
index e48a4ce22f..c7fd8dd6e3 100644
--- a/sword2/router.h
+++ b/sword2/router.h
@@ -33,17 +33,13 @@
namespace Sword2 {
-#if !defined(__GNUC__)
- #pragma START_PACK_STRUCTS
-#endif
-
struct WalkData {
uint16 frame;
int16 x;
int16 y;
uint8 step;
uint8 dir;
-} GCC_PACK;
+};
struct BarData {
int16 x1;
@@ -58,7 +54,7 @@ struct BarData {
int16 dy; // y2 - y1
int32 co; // co = (y1 * dx) - (x1 * dy) from an equation for a
// line y * dx = x * dy + co
-} GCC_PACK;
+};
struct NodeData {
int16 x;
@@ -66,11 +62,7 @@ struct NodeData {
int16 level;
int16 prev;
int16 dist;
-} GCC_PACK;
-
-#if !defined(__GNUC__)
- #pragma END_PACK_STRUCTS
-#endif
+};
// because we only have 2 megas in the game!
#define TOTAL_ROUTE_SLOTS 2
@@ -137,13 +129,8 @@ private:
int32 _framesPerStep;
int32 _framesPerChar;
- uint8 _nWalkFrames; // no. of frames per walk cycle
- uint8 _usingStandingTurnFrames; // any standing turn frames?
- uint8 _usingWalkingTurnFrames; // any walking turn frames?
- uint8 _usingSlowInFrames; // any slow-in frames?
- uint8 _usingSlowOutFrames; // any slow-out frames?
- int32 _dx[NO_DIRECTIONS + MAX_FRAMES_PER_CHAR];
- int32 _dy[NO_DIRECTIONS + MAX_FRAMES_PER_CHAR];
+ ObjectWalkdata _walkData;
+
int8 _modX[NO_DIRECTIONS];
int8 _modY[NO_DIRECTIONS];
int32 _diagonalx;
@@ -158,9 +145,6 @@ private:
int32 _firstWalkingTurnRightFrame; // right walking turn
uint32 _firstSlowInFrame[NO_DIRECTIONS];
- uint32 _numberOfSlowInFrames[NO_DIRECTIONS];
-
- uint32 _leadingLeg[NO_DIRECTIONS];
int32 _firstSlowOutFrame;
@@ -183,8 +167,8 @@ private:
int32 getRoute();
void extractRoute();
void loadWalkGrid();
- void setUpWalkGrid(ObjectMega *ob_mega, int32 x, int32 y, int32 dir);
- void loadWalkData(ObjectWalkdata *ob_walkdata);
+ void setUpWalkGrid(byte *ob_mega, int32 x, int32 y, int32 dir);
+ void loadWalkData(byte *ob_walkdata);
bool scan(int32 level);
int32 newCheck(int32 status, int32 x1, int32 y1, int32 x2, int32 y2);
@@ -219,44 +203,40 @@ public:
memset(_route, 0, sizeof(_route));
memset(_smoothPath, 0, sizeof(_smoothPath));
memset(_modularPath, 0, sizeof(_modularPath));
- memset(_dx, 0, sizeof(_dx));
- memset(_dy, 0, sizeof(_dy));
memset(_modX, 0, sizeof(_modX));
memset(_modY, 0, sizeof(_modY));
memset(_firstSlowInFrame, 0, sizeof(_firstSlowInFrame));
- memset(_numberOfSlowInFrames, 0, sizeof(_numberOfSlowInFrames));
- memset(_leadingLeg, 0, sizeof(_leadingLeg));
}
void setStandbyCoords(int16 x, int16 y, uint8 dir);
int whatTarget(int startX, int startY, int destX, int destY);
// Sprites
- void setSpriteStatus(ObjectGraphic *ob_graph, uint32 type);
- void setSpriteShading(ObjectGraphic *ob_graph, uint32 type);
+ void setSpriteStatus(byte *ob_graph, uint32 type);
+ void setSpriteShading(byte *ob_graph, uint32 type);
// Animation
- int doAnimate(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, int32 animRes, bool reverse);
- int megaTableAnimate(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, uint32 *animTable, bool reverse);
+ int doAnimate(byte *ob_logic, byte *ob_graph, int32 animRes, bool reverse);
+ int megaTableAnimate(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *animTable, bool reverse);
// Walking
- int doWalk(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, int16 target_x, int16 target_y, uint8 target_dir);
- int walkToAnim(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint32 animRes);
- int walkToTalkToMega(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint32 megaId, uint32 separation);
+ int doWalk(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, int16 target_x, int16 target_y, uint8 target_dir);
+ int walkToAnim(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 animRes);
+ int walkToTalkToMega(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 megaId, uint32 separation);
// Turning
- int doFace(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint8 target_dir);
- int faceXY(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, int16 target_x, int16 target_y);
- int faceMega(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint32 megaId);
+ int doFace(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint8 target_dir);
+ int faceXY(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, int16 target_x, int16 target_y);
+ int faceMega(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 megaId);
// Standing
- void standAt(ObjectGraphic *ob_graph, ObjectMega *ob_mega, int32 x, int32 y, int32 dir);
- void standAfterAnim(ObjectGraphic *ob_graph, ObjectMega *ob_mega, uint32 animRes);
- void standAtAnim(ObjectGraphic *ob_graph, ObjectMega *ob_mega, uint32 animRes);
+ void standAt(byte *ob_graph, byte *ob_mega, int32 x, int32 y, int32 dir);
+ void standAfterAnim(byte *ob_graph, byte *ob_mega, uint32 animRes);
+ void standAtAnim(byte *ob_graph, byte *ob_mega, uint32 animRes);
- int32 routeFinder(ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, int32 x, int32 y, int32 dir);
+ int32 routeFinder(byte *ob_mega, byte *ob_walkdata, int32 x, int32 y, int32 dir);
- void earlySlowOut(ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata);
+ void earlySlowOut(byte *ob_mega, byte *ob_walkdata);
void allocateRouteMem();
WalkData *getRouteMem();
diff --git a/sword2/save_rest.cpp b/sword2/save_rest.cpp
index 0332fa2f6a..cf948b7c14 100644
--- a/sword2/save_rest.cpp
+++ b/sword2/save_rest.cpp
@@ -43,63 +43,58 @@ namespace Sword2 {
// Max length of a savegame filename
#define MAX_FILENAME_LEN 128
-#ifdef SCUMM_BIG_ENDIAN
-// Quick macro to make swapping in-place easier to write
-#define SWAP32(x) x = SWAP_BYTES_32(x)
-
-static void convertHeaderEndian(Sword2Engine::SaveGameHeader &header) {
- // SaveGameHeader
- SWAP32(header.checksum);
- SWAP32(header.varLength);
- SWAP32(header.screenId);
- SWAP32(header.runListId);
- SWAP32(header.feet_x);
- SWAP32(header.feet_y);
- SWAP32(header.music_id);
-
- // ObjectHub
- SWAP32(header.player_hub.type);
- SWAP32(header.player_hub.logic_level);
- for (int i = 0; i < TREE_SIZE; i++) {
- SWAP32(header.player_hub.logic[i]);
- SWAP32(header.player_hub.script_id[i]);
- SWAP32(header.player_hub.script_pc[i]);
- }
+/**
+ * Calculate size of required savegame buffer
+ */
- // ObjectLogic
- SWAP32(header.logic.looping);
- SWAP32(header.logic.pause);
-
- // ObjectGraphic
- SWAP32(header.graphic.type);
- SWAP32(header.graphic.anim_resource);
- SWAP32(header.graphic.anim_pc);
-
- // ObjectMega
- SWAP32(header.mega.currently_walking);
- SWAP32(header.mega.walk_pc);
- SWAP32(header.mega.scale_a);
- SWAP32(header.mega.scale_b);
- SWAP32(header.mega.feet_x);
- SWAP32(header.mega.feet_y);
- SWAP32(header.mega.current_dir);
- SWAP32(header.mega.megaset_res);
+uint32 Sword2Engine::findBufferSize() {
+ // Size of savegame header + size of global variables
+ return 212 + _resman->fetchLen(1);
}
-#endif
/**
* Save the game.
*/
uint32 Sword2Engine::saveGame(uint16 slotNo, byte *desc) {
+ char description[SAVE_DESCRIPTION_LEN];
uint32 bufferSize = findBufferSize();
- byte *saveBufferMem = (byte *)malloc(bufferSize);
+ byte *saveBuffer = (byte *)malloc(bufferSize);
+ ScreenInfo *screenInfo = _screen->getScreenInfo();
+
+ memset(description, 0, sizeof(description));
+ strncpy(description, (char *)desc, SAVE_DESCRIPTION_LEN - 1);
+
+ Common::MemoryWriteStream writeS(saveBuffer, bufferSize);
+
+ byte *globalVars = _resman->openResource(1);
+ byte *objectHub = _resman->openResource(CUR_PLAYER_ID) + ResHeader::size();
- fillSaveBuffer(saveBufferMem, bufferSize, desc);
+ // Script no. 7 - 'george_savedata_request' calls fnPassPlayerSaveData
+ _logic->runResScript(CUR_PLAYER_ID, 7);
+
+ writeS.writeUint32LE(0); // Checksum
+ writeS.write(description, SAVE_DESCRIPTION_LEN);
+ writeS.writeUint32LE(_resman->fetchLen(1));
+ writeS.writeUint32LE(screenInfo->background_layer_id);
+ writeS.writeUint32LE(_logic->getRunList());
+ writeS.writeUint32LE(screenInfo->feet_x);
+ writeS.writeUint32LE(screenInfo->feet_y);
+ writeS.writeUint32LE(_sound->getLoopingMusicId());
+ writeS.write(objectHub, ObjectHub::size());
+ writeS.write(_logic->_saveLogic, ObjectLogic::size());
+ writeS.write(_logic->_saveGraphic, ObjectGraphic::size());
+ writeS.write(_logic->_saveMega, ObjectMega::size());
+ writeS.write(globalVars, _resman->fetchLen(1));
+
+ WRITE_LE_UINT32(saveBuffer, calcChecksum(saveBuffer + 4, bufferSize - 4));
+
+ _resman->closeResource(CUR_PLAYER_ID);
+ _resman->closeResource(1);
- uint32 errorCode = saveData(slotNo, saveBufferMem, bufferSize);
+ uint32 errorCode = saveData(slotNo, saveBuffer, bufferSize);
- free(saveBufferMem);
+ free(saveBuffer);
if (errorCode != SR_OK) {
uint32 textId;
@@ -119,65 +114,6 @@ uint32 Sword2Engine::saveGame(uint16 slotNo, byte *desc) {
return errorCode;
}
-/**
- * Calculate size of required savegame buffer
- */
-
-uint32 Sword2Engine::findBufferSize() {
- // Size of savegame header + size of global variables
- return sizeof(_saveGameHeader) + _resman->fetchLen(1);
-}
-
-void Sword2Engine::fillSaveBuffer(byte *buffer, uint32 size, byte *desc) {
- // Set up the _saveGameHeader. Checksum gets filled in last of all.
- ScreenInfo *screenInfo = _screen->getScreenInfo();
-
- strcpy(_saveGameHeader.description, (char *)desc);
- _saveGameHeader.varLength = _resman->fetchLen(1);
- _saveGameHeader.screenId = screenInfo->background_layer_id;
- _saveGameHeader.runListId = _logic->getRunList();
- _saveGameHeader.feet_x = screenInfo->feet_x;
- _saveGameHeader.feet_y = screenInfo->feet_y;
- _saveGameHeader.music_id = _sound->getLoopingMusicId();
-
- memcpy(&_saveGameHeader.player_hub, _resman->openResource(CUR_PLAYER_ID) + sizeof(StandardHeader), sizeof(ObjectHub));
-
- _resman->closeResource(CUR_PLAYER_ID);
-
- // Get the logic, graphic and mega structures
- getPlayerStructures();
-
-#ifdef SCUMM_BIG_ENDIAN
- convertHeaderEndian(_saveGameHeader);
-#endif
-
- // Copy the header to the buffer, even though it isn't quite complete
- memcpy(buffer, &_saveGameHeader, sizeof(_saveGameHeader));
-
- // Get the global variables
-
- byte *varsRes = _resman->openResource(1);
- memcpy(buffer + sizeof(_saveGameHeader), varsRes, FROM_LE_32(_saveGameHeader.varLength));
-
-#ifdef SCUMM_BIG_ENDIAN
- uint32 *globalVars = (uint32 *)(buffer + sizeof(_saveGameHeader) + sizeof(StandardHeader));
- const uint numVars = (FROM_LE_32(_saveGameHeader.varLength) - sizeof(StandardHeader)) / 4;
-
- for (uint i = 0; i < numVars; i++)
- globalVars[i] = SWAP_BYTES_32(globalVars[i]);
-#endif
-
- _resman->closeResource(1);
-
- // Finally, get the checksum
-
- _saveGameHeader.checksum = TO_LE_32(calcChecksum(buffer + sizeof(_saveGameHeader.checksum), size - sizeof(_saveGameHeader.checksum)));
-
- // All done
-
- memcpy(buffer, &_saveGameHeader.checksum, sizeof(_saveGameHeader.checksum));
-}
-
uint32 Sword2Engine::saveData(uint16 slotNo, byte *buffer, uint32 bufferSize) {
char saveFileName[MAX_FILENAME_LEN];
@@ -284,20 +220,17 @@ uint32 Sword2Engine::restoreData(uint16 slotNo, byte *buffer, uint32 bufferSize)
}
uint32 Sword2Engine::restoreFromBuffer(byte *buffer, uint32 size) {
- // Get a copy of the header from the savegame buffer
- memcpy(&_saveGameHeader, buffer, sizeof(_saveGameHeader));
-
-#ifdef SCUMM_BIG_ENDIAN
- convertHeaderEndian(_saveGameHeader);
-#endif
+ Common::MemoryReadStream readS(buffer, size);
// Calc checksum & check that aginst the value stored in the header
- if (_saveGameHeader.checksum != calcChecksum(buffer + sizeof(_saveGameHeader.checksum), size - sizeof(_saveGameHeader.checksum))) {
+ if (readS.readUint32LE() != calcChecksum(buffer + 4, size - 4)) {
free(buffer);
return SR_ERR_INCOMPATIBLE;
}
+ readS.seek(SAVE_DESCRIPTION_LEN, SEEK_CUR);
+
// Check savegame against length of current global variables resource
// This would most probably be trapped by the checksum test anyway,
// but it doesn't do any harm to check this as well.
@@ -305,49 +238,75 @@ uint32 Sword2Engine::restoreFromBuffer(byte *buffer, uint32 size) {
// Historical note: During development, earlier savegames would often
// be shorter than the current expected length.
- if (_saveGameHeader.varLength != _resman->fetchLen(1)) {
+ if (readS.readUint32LE() != _resman->fetchLen(1)) {
free(buffer);
return SR_ERR_INCOMPATIBLE;
}
- // Clean out system
+ byte *globalVars = _resman->openResource(1);
+ byte *objectHub = _resman->openResource(CUR_PLAYER_ID) + ResHeader::size();
+
+ uint32 screenId = readS.readUint32LE();
+ uint32 runListId = readS.readUint32LE();
+ uint32 feetX = readS.readUint32LE();
+ uint32 feetY = readS.readUint32LE();
+ uint32 musicId = readS.readUint32LE();
// Trash all resources from memory except player object & global vars
_resman->killAll(false);
-
- // Clean out the system kill list (no more objects to kill)
_logic->resetKillList();
- // Object hub is just after the standard header
- memcpy(_resman->openResource(CUR_PLAYER_ID) + sizeof(StandardHeader), &_saveGameHeader.player_hub, sizeof(ObjectHub));
+ readS.read(objectHub, ObjectHub::size());
+ readS.read(_logic->_saveLogic, ObjectLogic::size());
+ readS.read(_logic->_saveGraphic, ObjectGraphic::size());
+ readS.read(_logic->_saveMega, ObjectMega::size());
- _resman->closeResource(CUR_PLAYER_ID);
+ // Fill out the player object structures from the savegame structures.
+ // Also run the appropriate scripts to set up George's anim tables and
+ // walkdata, and Nico's anim tables.
- // Fill in the player object structures from the header
- putPlayerStructures();
+ // Script no. 8 - 'george_savedata_return' calls fnGetPlayerSaveData
+ _logic->runResScript(CUR_PLAYER_ID, 8);
- // Copy variables from savegame buffer to memory
- byte *varsRes = _resman->openResource(1);
+ // Script no. 14 - 'set_up_nico_anim_tables'
+ _logic->runResScript(CUR_PLAYER_ID, 14);
- memcpy(varsRes, buffer + sizeof(_saveGameHeader), _saveGameHeader.varLength);
+ // Which megaset was the player at the time of saving?
+ ObjectMega obMega(_logic->_saveMega);
-#ifdef SCUMM_BIG_ENDIAN
- uint32 *globalVars = (uint32 *)(varsRes + sizeof(StandardHeader));
- const uint numVars = (_saveGameHeader.varLength - sizeof(StandardHeader)) / 4;
+ uint32 scriptNo = 0;
- for (uint i = 0; i < numVars; i++)
- globalVars[i] = SWAP_BYTES_32(globalVars[i]);
-#endif
+ switch (obMega.getMegasetRes()) {
+ case 36: // GeoMega:
+ scriptNo = 9; // script no.9 - 'player_is_george'
+ break;
+ case 2003: // GeoMegaB:
+ scriptNo = 13; // script no.13 - 'player_is_georgeB'
+ break;
+ case 1366: // NicMegaA:
+ scriptNo = 11; // script no.11 - 'player_is_nicoA'
+ break;
+ case 1437: // NicMegaB:
+ scriptNo = 12; // script no.12 - 'player_is_nicoB'
+ break;
+ case 1575: // NicMegaC:
+ scriptNo = 10; // script no.10 - 'player_is_nicoC'
+ break;
+ }
+
+ _logic->runResScript(CUR_PLAYER_ID, scriptNo);
+
+ // Copy variables from savegame buffer to memory
+ readS.read(globalVars, _resman->fetchLen(1));
+ _resman->closeResource(CUR_PLAYER_ID);
_resman->closeResource(1);
- // Free it now, rather than in RestoreGame, to unblock memory before
- // new screen & runlist loaded
free(buffer);
int32 pars[2];
- pars[0] = _saveGameHeader.screenId;
+ pars[0] = screenId;
pars[1] = 1;
_logic->fnInitBackground(pars);
@@ -361,19 +320,19 @@ uint32 Sword2Engine::restoreFromBuffer(byte *buffer, uint32 size) {
// Remember that these can change through the game, so need saving &
// restoring too.
- screenInfo->feet_x = _saveGameHeader.feet_x;
- screenInfo->feet_y = _saveGameHeader.feet_y;
+ screenInfo->feet_x = feetX;
+ screenInfo->feet_y = feetY;
// Start the new run list
- _logic->expressChangeSession(_saveGameHeader.runListId);
+ _logic->expressChangeSession(runListId);
// Force in the new scroll position, so unsightly scroll-catch-up does
// not occur when screen first draws after returning from restore panel
// Set the screen record of player position - ready for setScrolling()
- screenInfo->player_feet_x = _saveGameHeader.mega.feet_x;
- screenInfo->player_feet_y = _saveGameHeader.mega.feet_y;
+ screenInfo->player_feet_x = obMega.getFeetX();
+ screenInfo->player_feet_y = obMega.getFeetY();
// if this screen is wide, recompute the scroll offsets now
if (screenInfo->scroll_flag)
@@ -386,8 +345,8 @@ uint32 Sword2Engine::restoreFromBuffer(byte *buffer, uint32 size) {
// in systemMenuMouse(), but with ScummVM we have other ways of
// restoring savegames so it's easier to put it here as well.
- if (_saveGameHeader.music_id) {
- pars[0] = _saveGameHeader.music_id;
+ if (musicId) {
+ pars[0] = musicId;
pars[1] = FX_LOOP;
_logic->fnPlayMusic(pars);
} else
@@ -411,12 +370,10 @@ uint32 Sword2Engine::getSaveDescription(uint16 slotNo, byte *description) {
return SR_ERR_FILEOPEN;
}
- SaveGameHeader dummy;
+ in->readUint32LE();
+ in->read(description, SAVE_DESCRIPTION_LEN);
- in->read(&dummy, sizeof(dummy));
delete in;
-
- strcpy((char *)description, dummy.description);
return SR_OK;
}
@@ -442,71 +399,6 @@ bool Sword2Engine::saveExists(uint16 slotNo) {
return true;
}
-/**
- * Request the player object structures which need saving.
- */
-
-void Sword2Engine::getPlayerStructures() {
- StandardHeader *head = (StandardHeader *)_resman->openResource(CUR_PLAYER_ID);
-
- assert(head->fileType == GAME_OBJECT);
-
- char *raw_script_ad = (char *)head;
-
- // Script no. 7 - 'george_savedata_request' calls fnPassPlayerSaveData
- uint32 null_pc = 7;
-
- _logic->runScript(raw_script_ad, raw_script_ad, &null_pc);
- _resman->closeResource(CUR_PLAYER_ID);
-}
-
-/**
- * Fill out the player object structures from the savegame structures also run
- * the appropriate scripts to set up george's anim tables and walkdata, and
- * Nico's anim tables.
- */
-
-void Sword2Engine::putPlayerStructures() {
- StandardHeader *head = (StandardHeader *)_resman->openResource(CUR_PLAYER_ID);
-
- assert(head->fileType == GAME_OBJECT);
-
- char *raw_script_ad = (char *)head;
-
- // Script no. 8 - 'george_savedata_return' calls fnGetPlayerSaveData
-
- uint32 null_pc = 8;
- _logic->runScript(raw_script_ad, raw_script_ad, &null_pc);
-
- // Script no. 14 - 'set_up_nico_anim_tables'
-
- null_pc = 14;
- _logic->runScript(raw_script_ad, raw_script_ad, &null_pc);
-
- // Which megaset was the player at the time of saving?
-
- switch (_saveGameHeader.mega.megaset_res) {
- case 36: // GeoMega:
- null_pc = 9; // script no.9 - 'player_is_george'
- break;
- case 2003: // GeoMegaB:
- null_pc = 13; // script no.13 - 'player_is_georgeB'
- break;
- case 1366: // NicMegaA:
- null_pc = 11; // script no.11 - 'player_is_nicoA'
- break;
- case 1437: // NicMegaB:
- null_pc = 12; // script no.12 - 'player_is_nicoB'
- break;
- case 1575: // NicMegaC:
- null_pc = 10; // script no.10 - 'player_is_nicoC'
- break;
- }
-
- _logic->runScript(raw_script_ad, raw_script_ad, &null_pc);
- _resman->closeResource(CUR_PLAYER_ID);
-}
-
uint32 Sword2Engine::calcChecksum(byte *buffer, uint32 size) {
uint32 total = 0;
diff --git a/sword2/scroll.cpp b/sword2/scroll.cpp
index bc999de926..fd960caa2b 100644
--- a/sword2/scroll.cpp
+++ b/sword2/scroll.cpp
@@ -54,10 +54,12 @@ void Screen::setScrolling() {
// If the scroll offsets are being forced in script, ensure that they
// are neither too far to the right nor too far down.
+ uint32 scrollX = _vm->_logic->readVar(SCROLL_X);
+ uint32 scrollY = _vm->_logic->readVar(SCROLL_Y);
- if (Logic::_scriptVars[SCROLL_X] || Logic::_scriptVars[SCROLL_Y]) {
- _thisScreen.scroll_offset_x = MIN((uint16) Logic::_scriptVars[SCROLL_X], _thisScreen.max_scroll_offset_x);
- _thisScreen.scroll_offset_y = MIN((uint16) Logic::_scriptVars[SCROLL_Y], _thisScreen.max_scroll_offset_y);
+ if (scrollX || scrollY) {
+ _thisScreen.scroll_offset_x = MIN((uint16)scrollX, _thisScreen.max_scroll_offset_x);
+ _thisScreen.scroll_offset_y = MIN((uint16)scrollY, _thisScreen.max_scroll_offset_y);
return;
}
diff --git a/sword2/sound.cpp b/sword2/sound.cpp
index d8ac958f08..3b8a4ff354 100644
--- a/sword2/sound.cpp
+++ b/sword2/sound.cpp
@@ -199,17 +199,16 @@ void Sound::queueFx(int32 res, int32 type, int32 delay, int32 volume, int32 pan)
byte buf[NAME_LEN];
- debug(0, "SFX (sample=\"%s\", vol=%d, pan=%d, delay=%d, type=%s)", _vm->fetchObjectName(res, buf), volume, pan, delay, typeStr);
+ debug(0, "SFX (sample=\"%s\", vol=%d, pan=%d, delay=%d, type=%s)", _vm->_resman->fetchName(res, buf), volume, pan, delay, typeStr);
}
for (int i = 0; i < FXQ_LENGTH; i++) {
if (!_fxQueue[i].resource) {
byte *data = _vm->_resman->openResource(res);
- StandardHeader *header = (StandardHeader *)data;
- assert(header->fileType == WAV_FILE);
+ assert(_vm->_resman->fetchType(data) == WAV_FILE);
- uint32 len = _vm->_resman->fetchLen(res) - sizeof(StandardHeader);
+ uint32 len = _vm->_resman->fetchLen(res) - ResHeader::size();
if (type == FX_RANDOM) {
// For spot effects and loops the delay is the
@@ -227,7 +226,7 @@ void Sound::queueFx(int32 res, int32 type, int32 delay, int32 volume, int32 pan)
pan = -pan;
_fxQueue[i].resource = res;
- _fxQueue[i].data = data + sizeof(StandardHeader);
+ _fxQueue[i].data = data + ResHeader::size();
_fxQueue[i].len = len;
_fxQueue[i].delay = delay;
_fxQueue[i].volume = volume;
@@ -238,7 +237,7 @@ void Sound::queueFx(int32 res, int32 type, int32 delay, int32 volume, int32 pan)
// fnStopFx() can be used later to kill this sound.
// Mainly for FX_LOOP and FX_RANDOM.
- Logic::_scriptVars[RESULT] = i;
+ _vm->_logic->writeVar(RESULT, i);
return;
}
}
diff --git a/sword2/speech.cpp b/sword2/speech.cpp
index 25d8c841c2..21516210a5 100644
--- a/sword2/speech.cpp
+++ b/sword2/speech.cpp
@@ -80,39 +80,35 @@ void Logic::locateTalker(int32 *params) {
// '0' means 1st frame
- CdtEntry *cdt_entry = _vm->fetchCdtEntry(file, 0);
- FrameHeader *frame_head = _vm->fetchFrameHeader(file, 0);
+ CdtEntry cdt_entry;
+ FrameHeader frame_head;
+
+ cdt_entry.read(_vm->fetchCdtEntry(file, 0));
+ frame_head.read(_vm->fetchFrameHeader(file, 0));
// Note: This part of the code is quite similar to registerFrame().
- if (cdt_entry->frameType & FRAME_OFFSET) {
+ if (cdt_entry.frameType & FRAME_OFFSET) {
// The frame has offsets, i.e. it's a scalable mega frame
- ObjectMega *ob_mega = (ObjectMega *)decodePtr(params[S_OB_MEGA]);
-
- // Calculate scale at which to print the sprite, based on feet
- // y-coord and scaling constants (NB. 'scale' is actually
- // 256 * true_scale, to maintain accuracy)
+ ObjectMega obMega(decodePtr(params[S_OB_MEGA]));
- // Ay+B gives 256 * scale ie. 256 * 256 * true_scale for even
- // better accuracy, ie. scale = (Ay + B) / 256
-
- uint16 scale = (uint16) ((ob_mega->scale_a * ob_mega->feet_y + ob_mega->scale_b) / 256);
+ uint16 scale = obMega.calcScale();
// Calc suitable centre point above the head, based on scaled
// height
// just use 'feet_x' as centre
- _textX = (int16) ob_mega->feet_x;
+ _textX = obMega.getFeetX();
// Add scaled y-offset to feet_y coord to get top of sprite
- _textY = (int16) (ob_mega->feet_y + (cdt_entry->y * scale) / 256);
+ _textY = obMega.getFeetY() + (cdt_entry.y * scale) / 256;
} else {
// It's a non-scaling anim - calc suitable centre point above
// the head, based on scaled width
// x-coord + half of width
- _textX = cdt_entry->x + (frame_head->width) / 2;
- _textY = cdt_entry->y;
+ _textX = cdt_entry.x + frame_head.width / 2;
+ _textY = cdt_entry.y;
}
_vm->_resman->closeResource(_animId);
@@ -158,10 +154,13 @@ void Logic::formText(int32 *params) {
return;
}
- ObjectSpeech *ob_speech = (ObjectSpeech *)decodePtr(params[S_OB_SPEECH]);
+ ObjectSpeech obSpeech(decodePtr(params[S_OB_SPEECH]));
// Establish the max width allowed for this text sprite.
- uint32 textWidth = ob_speech->width ? ob_speech->width : 400;
+ uint32 textWidth = obSpeech.getWidth();
+
+ if (!textWidth)
+ textWidth = 400;
// Pull out the text line, and make the sprite and text block
@@ -174,7 +173,7 @@ void Logic::formText(int32 *params) {
_speechTextBlocNo = _vm->_fontRenderer->buildNewBloc(
text + 2, _textX, _textY,
- textWidth, ob_speech->pen,
+ textWidth, obSpeech.getPen(),
RDSPR_TRANS | RDSPR_DISPLAYALIGN,
_vm->_speechFontId, POSITION_AT_CENTRE_OF_BASE);
diff --git a/sword2/startup.cpp b/sword2/startup.cpp
index a03e624338..f64111c23a 100644
--- a/sword2/startup.cpp
+++ b/sword2/startup.cpp
@@ -117,11 +117,7 @@ bool Sword2Engine::initStartMenu() {
// start list
if (_resman->checkValid(_startRes)) {
- char *raw_script = (char *)_resman->openResource(_startRes);
- uint32 null_pc = 0;
-
- _logic->runScript(raw_script, raw_script, &null_pc);
- _resman->closeResource(_startRes);
+ _logic->runResScript(_startRes, 0);
} else
warning("Start menu resource %d invalid", _startRes);
}
@@ -166,17 +162,7 @@ void Sword2Engine::runStart(int start) {
_logic->_speechTextBlocNo = 0;
}
- // Open George
- char *raw_data_ad = (char *)_resman->openResource(CUR_PLAYER_ID);
- char *raw_script = (char *)_resman->openResource(_startList[start].start_res_id);
-
- // Denotes script to run
- uint32 null_pc = _startList[start].key & 0xffff;
-
- _logic->runScript(raw_script, raw_data_ad, &null_pc);
-
- _resman->closeResource(_startList[start].start_res_id);
- _resman->closeResource(CUR_PLAYER_ID);
+ _logic->runResObjScript(_startList[start].start_res_id, CUR_PLAYER_ID, _startList[start].key & 0xffff);
// Make sure there's a mouse, in case restarting while mouse not
// available
diff --git a/sword2/sword2.cpp b/sword2/sword2.cpp
index 846885216f..f413f95a5a 100644
--- a/sword2/sword2.cpp
+++ b/sword2/sword2.cpp
@@ -222,7 +222,7 @@ void Sword2Engine::writeSettings() {
*/
void Sword2Engine::setupPersistentResources() {
- Logic::_scriptVars = (uint32 *)(_resman->openResource(1) + sizeof(StandardHeader));
+ _logic->_scriptVars = _resman->openResource(1) + ResHeader::size();
_resman->openResource(CUR_PLAYER_ID);
}
@@ -266,9 +266,9 @@ int Sword2Engine::init(GameDetector &detector) {
initialiseFontResourceFlags();
if (_features & GF_DEMO)
- Logic::_scriptVars[DEMO] = 1;
+ _logic->writeVar(DEMO, 1);
else
- Logic::_scriptVars[DEMO] = 0;
+ _logic->writeVar(DEMO, 0);
if (_saveSlot != -1) {
if (saveExists(_saveSlot))
@@ -332,7 +332,7 @@ int Sword2Engine::go() {
pauseGame();
break;
case 'c':
- if (!Logic::_scriptVars[DEMO] && !_mouse->isChoosing()) {
+ if (!_logic->readVar(DEMO) && !_mouse->isChoosing()) {
ScreenInfo *screenInfo = _screen->getScreenInfo();
_logic->fnPlayCredits(NULL);
screenInfo->new_palette = 99;
@@ -401,10 +401,10 @@ void Sword2Engine::restartGame() {
_sound->stopMusic(true);
// In case we were dead - well we're not anymore!
- Logic::_scriptVars[DEAD] = 0;
+ _logic->writeVar(DEAD, 0);
// Restart the game. Clear all memory and reset the globals
- temp_demo_flag = Logic::_scriptVars[DEMO];
+ temp_demo_flag = _logic->readVar(DEMO);
// Remove all resources from memory, including player object and
// global variables
@@ -413,7 +413,7 @@ void Sword2Engine::restartGame() {
// Reopen global variables resource and player object
setupPersistentResources();
- Logic::_scriptVars[DEMO] = temp_demo_flag;
+ _logic->writeVar(DEMO, temp_demo_flag);
// Free all the route memory blocks from previous game
_logic->_router->freeAllRouteMem();
@@ -605,7 +605,7 @@ void Sword2Engine::startGame() {
debug(5, "startGame() STARTING:");
if (!_bootParam) {
- if (Logic::_scriptVars[DEMO])
+ if (_logic->readVar(DEMO))
screen_manager_id = 19; // DOCKS SECTION START
else
screen_manager_id = 949; // INTRO & PARIS START
@@ -617,15 +617,7 @@ void Sword2Engine::startGame() {
screen_manager_id = _bootParam;
}
- uint32 null_pc = 1;
-
- char *raw_data_ad = (char *)_resman->openResource(CUR_PLAYER_ID);
- char *raw_script = (char *)_resman->openResource(screen_manager_id);
-
- _logic->runScript(raw_script, raw_data_ad, &null_pc);
-
- _resman->closeResource(screen_manager_id);
- _resman->closeResource(CUR_PLAYER_ID);
+ _logic->runResObjScript(screen_manager_id, CUR_PLAYER_ID, 1);
}
// FIXME: Move this to some better place?
diff --git a/sword2/sword2.h b/sword2/sword2.h
index 48031be064..5145e3d060 100644
--- a/sword2/sword2.h
+++ b/sword2/sword2.h
@@ -184,58 +184,25 @@ public:
#endif
byte *fetchPalette(byte *screenFile);
- ScreenHeader *fetchScreenHeader(byte *screenFile);
- LayerHeader *fetchLayerHeader(byte *screenFile, uint16 layerNo);
+ byte *fetchScreenHeader(byte *screenFile);
+ byte *fetchLayerHeader(byte *screenFile, uint16 layerNo);
byte *fetchShadingMask(byte *screenFile);
- AnimHeader *fetchAnimHeader(byte *animFile);
- CdtEntry *fetchCdtEntry(byte *animFile, uint16 frameNo);
- FrameHeader *fetchFrameHeader(byte *animFile, uint16 frameNo);
- Parallax *fetchBackgroundParallaxLayer(byte *screenFile, int layer);
- Parallax *fetchBackgroundLayer(byte *screenFile);
- Parallax *fetchForegroundParallaxLayer(byte *screenFile, int layer);
+ byte *fetchAnimHeader(byte *animFile);
+ byte *fetchCdtEntry(byte *animFile, uint16 frameNo);
+ byte *fetchFrameHeader(byte *animFile, uint16 frameNo);
+ byte *fetchBackgroundParallaxLayer(byte *screenFile, int layer);
+ byte *fetchBackgroundLayer(byte *screenFile);
+ byte *fetchForegroundParallaxLayer(byte *screenFile, int layer);
byte *fetchTextLine(byte *file, uint32 text_line);
bool checkTextLine(byte *file, uint32 text_line);
byte *fetchPaletteMatchTable(byte *screenFile);
- byte *fetchObjectName(int32 resourceId, byte *buf);
-
- // savegame file header
-
-#if !defined(__GNUC__)
- #pragma START_PACK_STRUCTS
-#endif
-
- struct SaveGameHeader {
- // sum of all bytes in file, excluding this uint32
- uint32 checksum;
-
- // player's description of savegame
- char description[SAVE_DESCRIPTION_LEN];
-
- uint32 varLength; // length of global variables resource
- uint32 screenId; // resource id of screen file
- uint32 runListId; // resource id of run list
- uint32 feet_x; // copy of _thisScreen.feet_x
- uint32 feet_y; // copy of _thisScreen.feet_y
- uint32 music_id; // copy of 'looping_music_id'
- ObjectHub player_hub; // copy of player object's object_hub structure
- ObjectLogic logic; // copy of player character logic structure
- ObjectGraphic graphic; // copy of player character graphic structure
- ObjectMega mega; // copy of player character mega structure
- } GCC_PACK;
-
-#if !defined(__GNUC__)
- #pragma END_PACK_STRUCTS
-#endif
-
- SaveGameHeader _saveGameHeader;
uint32 saveGame(uint16 slotNo, byte *description);
uint32 restoreGame(uint16 slotNo);
uint32 getSaveDescription(uint16 slotNo, byte *description);
bool saveExists();
bool saveExists(uint16 slotNo);
- void fillSaveBuffer(byte *buffer, uint32 size, byte *desc);
uint32 restoreFromBuffer(byte *buffer, uint32 size);
uint32 findBufferSize();
diff --git a/sword2/sync.cpp b/sword2/sync.cpp
index d5fb75105f..256ecf5097 100644
--- a/sword2/sync.cpp
+++ b/sword2/sync.cpp
@@ -46,8 +46,10 @@ void Logic::clearSyncs(uint32 id) {
*/
int Logic::getSync() {
+ uint32 id = readVar(ID);
+
for (int i = 0; i < MAX_syncs; i++) {
- if (_syncList[i].id == _scriptVars[ID])
+ if (_syncList[i].id == id)
return i;
}
diff --git a/sword2/walker.cpp b/sword2/walker.cpp
index 1bc65146c6..7312c51ddd 100644
--- a/sword2/walker.cpp
+++ b/sword2/walker.cpp
@@ -79,10 +79,14 @@ int Router::whatTarget(int startX, int startY, int destX, int destY) {
* RESULT to 1. Return true if the mega has finished walking.
*/
-int Router::doWalk(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, int16 target_x, int16 target_y, uint8 target_dir) {
+int Router::doWalk(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, int16 target_x, int16 target_y, uint8 target_dir) {
+ ObjectLogic obLogic(ob_logic);
+ ObjectGraphic obGraph(ob_graph);
+ ObjectMega obMega(ob_mega);
+
// If this is the start of the walk, calculate the route.
- if (!ob_logic->looping) {
+ if (obLogic.getLooping() == 0) {
// If we're already there, don't even bother allocating
// memory and calling the router, just quit back & continue
// the script! This avoids an embarassing mega stand frame
@@ -91,14 +95,14 @@ int Router::doWalk(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *o
// an anim - no mega frame will appear in between runs of the
// anim.
- if (ob_mega->feet_x == target_x && ob_mega->feet_y == target_y && ob_mega->current_dir == target_dir) {
- Logic::_scriptVars[RESULT] = 0;
+ if (obMega.getFeetX() == target_x && obMega.getFeetY() == target_y && obMega.getCurDir() == target_dir) {
+ _vm->_logic->writeVar(RESULT, 0);
return IR_CONT;
}
assert(target_dir <= 8);
- ob_mega->walk_pc = 0;
+ obMega.setWalkPc(0);
// Set up mem for _walkData in route_slots[] & set mega's
// 'route_slot_id' accordingly
@@ -112,16 +116,16 @@ int Router::doWalk(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *o
if (route != 1 && route != 2) {
freeRouteMem();
- Logic::_scriptVars[RESULT] = 1;
+ _vm->_logic->writeVar(RESULT, 1);
return IR_CONT;
}
// Walk is about to start
- ob_mega->currently_walking = 1;
- ob_logic->looping = 1;
- ob_graph->anim_resource = ob_mega->megaset_res;
- } else if (Logic::_scriptVars[EXIT_FADING] && _vm->_screen->getFadeStatus() == RDFADE_BLACK) {
+ obMega.setIsWalking(1);
+ obLogic.setLooping(1);
+ obGraph.setAnimResource(obMega.getMegasetRes());
+ } else if (_vm->_logic->readVar(EXIT_FADING) && _vm->_screen->getFadeStatus() == RDFADE_BLACK) {
// Double clicked an exit, and the screen has faded down to
// black. Ok, that's it. Back to script and change screen.
@@ -130,10 +134,10 @@ int Router::doWalk(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *o
freeRouteMem();
- ob_logic->looping = 0;
- ob_mega->currently_walking = 0;
- Logic::_scriptVars[EXIT_CLICK_ID] = 0;
- Logic::_scriptVars[RESULT] = 0;
+ obLogic.setLooping(0);
+ obMega.setIsWalking(0);
+ _vm->_logic->writeVar(EXIT_CLICK_ID, 0);
+ _vm->_logic->writeVar(RESULT, 0);
return IR_CONT;
}
@@ -141,7 +145,7 @@ int Router::doWalk(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *o
// Get pointer to walkanim & current frame position
WalkData *walkAnim = getRouteMem();
- int32 walk_pc = ob_mega->walk_pc;
+ int32 walk_pc = obMega.getWalkPc();
// If stopping the walk early, overwrite the next step with a
// slow-out, then finish
@@ -153,17 +157,17 @@ int Router::doWalk(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *o
// Get new frame of walk
- ob_graph->anim_pc = walkAnim[walk_pc].frame;
- ob_mega->current_dir = walkAnim[walk_pc].dir;
- ob_mega->feet_x = walkAnim[walk_pc].x;
- ob_mega->feet_y = walkAnim[walk_pc].y;
+ obGraph.setAnimPc(walkAnim[walk_pc].frame);
+ obMega.setCurDir(walkAnim[walk_pc].dir);
+ obMega.setFeetX(walkAnim[walk_pc].x);
+ obMega.setFeetY(walkAnim[walk_pc].y);
// Is the NEXT frame is the end-marker (512) of the walk sequence?
if (walkAnim[walk_pc + 1].frame != 512) {
// No, it wasn't. Increment the walk-anim frame number and
// come back next cycle.
- ob_mega->walk_pc++;
+ obMega.setWalkPc(obMega.getWalkPc() + 1);
return IR_REPEAT;
}
@@ -171,8 +175,8 @@ int Router::doWalk(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *o
// script just as the final (stand) frame of the walk is set.
freeRouteMem();
- ob_logic->looping = 0;
- ob_mega->currently_walking = 0;
+ obLogic.setLooping(0);
+ obMega.setIsWalking(0);
// If George's walk has been interrupted to run a new action script for
// instance or Nico's walk has been interrupted by player clicking on
@@ -184,11 +188,11 @@ int Router::doWalk(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *o
if (_vm->_logic->checkEventWaiting()) {
_vm->_logic->startEvent();
- Logic::_scriptVars[RESULT] = 1;
+ _vm->_logic->writeVar(RESULT, 1);
return IR_TERMINATE;
}
- Logic::_scriptVars[RESULT] = 0;
+ _vm->_logic->writeVar(RESULT, 0);
// CONTINUE the script so that RESULT can be checked! Also, if an anim
// command follows the fnWalk command, the 1st frame of the anim (which
@@ -203,7 +207,7 @@ int Router::doWalk(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *o
* Walk mega to start position of anim
*/
-int Router::walkToAnim(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint32 animRes) {
+int Router::walkToAnim(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 animRes) {
int16 target_x = 0;
int16 target_y = 0;
uint8 target_dir = 0;
@@ -213,13 +217,17 @@ int Router::walkToAnim(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMeg
// If this is the start of the walk, read anim file to get start coords
- if (!ob_logic->looping) {
+ ObjectLogic obLogic(ob_logic);
+
+ if (obLogic.getLooping() == 0) {
byte *anim_file = _vm->_resman->openResource(animRes);
- AnimHeader *anim_head = _vm->fetchAnimHeader(anim_file);
+ AnimHeader anim_head;
- target_x = anim_head->feetStartX;
- target_y = anim_head->feetStartY;
- target_dir = anim_head->feetStartDir;
+ anim_head.read(_vm->fetchAnimHeader(anim_file));
+
+ target_x = anim_head.feetStartX;
+ target_y = anim_head.feetStartY;
+ target_dir = anim_head.feetStartDir;
_vm->_resman->closeResource(animRes);
@@ -242,53 +250,47 @@ int Router::walkToAnim(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMeg
* Route to the left or right hand side of target id, if possible.
*/
-int Router::walkToTalkToMega(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint32 megaId, uint32 separation) {
+int Router::walkToTalkToMega(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 megaId, uint32 separation) {
+ ObjectMega obMega(ob_mega);
+
int16 target_x = 0;
int16 target_y = 0;
uint8 target_dir = 0;
// If this is the start of the walk, calculate the route.
- if (!ob_logic->looping) {
- StandardHeader *head = (StandardHeader *)_vm->_resman->openResource(megaId);
+ ObjectLogic obLogic(ob_logic);
- assert(head->fileType == GAME_OBJECT);
+ if (obLogic.getLooping() == 0) {
+ assert(_vm->_resman->fetchType(megaId) == GAME_OBJECT);
// Call the base script. This is the graphic/mouse service
// call, and will set _engineMega to the ObjectMega of mega we
// want to route to.
- char *raw_script_ad = (char *)head;
- uint32 null_pc = 3;
+ _vm->_logic->runResScript(megaId, 3);
- _vm->_logic->runScript(raw_script_ad, raw_script_ad, &null_pc);
- _vm->_resman->closeResource(megaId);
-
- ObjectMega *targetMega = _vm->_logic->getEngineMega();
+ ObjectMega targetMega(_vm->_logic->getEngineMega());
// Stand exactly beside the mega, ie. at same y-coord
- target_y = targetMega->feet_y;
-
- // Apply scale factor to walk distance. Ay+B gives 256 * scale
- // ie. 256 * 256 * true_scale for even better accuracy, ie.
- // scale = (Ay + B) / 256
+ target_y = targetMega.getFeetY();
- int scale = (ob_mega->scale_a * ob_mega->feet_y + ob_mega->scale_b) / 256;
+ int scale = obMega.calcScale();
int mega_separation = (separation * scale) / 256;
- debug(4, "Target is at (%d, %d), separation %d", targetMega->feet_x, targetMega->feet_y, mega_separation);
+ debug(4, "Target is at (%d, %d), separation %d", targetMega.getFeetX(), targetMega.getFeetY(), mega_separation);
- if (targetMega->feet_x < ob_mega->feet_x) {
+ if (targetMega.getFeetX() < obMega.getFeetX()) {
// Target is left of us, so aim to stand to their
// right. Face down_left
- target_x = targetMega->feet_x + mega_separation;
+ target_x = targetMega.getFeetX() + mega_separation;
target_dir = 5;
} else {
// Ok, must be right of us so aim to stand to their
// left. Face down_right.
- target_x = targetMega->feet_x - mega_separation;
+ target_x = targetMega.getFeetX() - mega_separation;
target_dir = 3;
}
}
@@ -300,18 +302,22 @@ int Router::walkToTalkToMega(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, Obj
* current feet coords, so router can produce anim of turn frames.
*/
-int Router::doFace(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint8 target_dir) {
+int Router::doFace(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint8 target_dir) {
int16 target_x = 0;
int16 target_y = 0;
// If this is the start of the turn, get the mega's current feet
// coords + the required direction
- if (!ob_logic->looping) {
+ ObjectLogic obLogic(ob_logic);
+
+ if (obLogic.getLooping() == 0) {
assert(target_dir <= 7);
- target_x = ob_mega->feet_x;
- target_y = ob_mega->feet_y;
+ ObjectMega obMega(ob_mega);
+
+ target_x = obMega.getFeetX();
+ target_y = obMega.getFeetY();
}
return doWalk(ob_logic, ob_graph, ob_mega, ob_walkdata, target_x, target_y, target_dir);
@@ -321,14 +327,18 @@ int Router::doFace(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *o
* Turn mega to face point (x,y) on the floor
*/
-int Router::faceXY(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, int16 target_x, int16 target_y) {
+int Router::faceXY(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, int16 target_x, int16 target_y) {
uint8 target_dir = 0;
// If this is the start of the turn, get the mega's current feet
// coords + the required direction
- if (!ob_logic->looping) {
- target_dir = whatTarget(ob_mega->feet_x, ob_mega->feet_y, target_x, target_y);
+ ObjectLogic obLogic(ob_logic);
+
+ if (obLogic.getLooping() == 0) {
+ ObjectMega obMega(ob_mega);
+
+ target_dir = whatTarget(obMega.getFeetX(), obMega.getFeetY(), target_x, target_y);
}
return doFace(ob_logic, ob_graph, ob_mega, ob_walkdata, target_dir);
@@ -338,29 +348,26 @@ int Router::faceXY(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *o
* Turn mega to face another mega.
*/
-int Router::faceMega(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega *ob_mega, ObjectWalkdata *ob_walkdata, uint32 megaId) {
+int Router::faceMega(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 megaId) {
uint8 target_dir = 0;
// If this is the start of the walk, decide where to walk to.
- if (!ob_logic->looping) {
- StandardHeader *head = (StandardHeader *)_vm->_resman->openResource(megaId);
+ ObjectLogic obLogic(ob_logic);
- assert(head->fileType == GAME_OBJECT);
+ if (obLogic.getLooping() == 0) {
+ assert(_vm->_resman->fetchType(megaId) == GAME_OBJECT);
// Call the base script. This is the graphic/mouse service
// call, and will set _engineMega to the ObjectMega of mega we
// want to turn to face.
- char *raw_script_ad = (char *)head;
- uint32 null_pc = 3;
-
- _vm->_logic->runScript(raw_script_ad, raw_script_ad, &null_pc);
- _vm->_resman->closeResource(megaId);
+ _vm->_logic->runResScript(megaId, 3);
- ObjectMega *targetMega = _vm->_logic->getEngineMega();
+ ObjectMega obMega(ob_mega);
+ ObjectMega targetMega(_vm->_logic->getEngineMega());
- target_dir = whatTarget(ob_mega->feet_x, ob_mega->feet_y, targetMega->feet_x, targetMega->feet_y);
+ target_dir = whatTarget(obMega.getFeetX(), obMega.getFeetY(), targetMega.getFeetX(), targetMega.getFeetY());
}
return doFace(ob_logic, ob_graph, ob_mega, ob_walkdata, target_dir);
@@ -372,33 +379,38 @@ int Router::faceMega(ObjectLogic *ob_logic, ObjectGraphic *ob_graph, ObjectMega
* the mega object, so the router knows in future
*/
-void Router::standAt(ObjectGraphic *ob_graph, ObjectMega *ob_mega, int32 x, int32 y, int32 dir) {
+void Router::standAt(byte *ob_graph, byte *ob_mega, int32 x, int32 y, int32 dir) {
assert(dir >= 0 && dir <= 7);
+ ObjectGraphic obGraph(ob_graph);
+ ObjectMega obMega(ob_mega);
+
// Set up the stand frame & set the mega's new direction
- ob_mega->feet_x = x;
- ob_mega->feet_y = y;
- ob_mega->current_dir = dir;
+ obMega.setFeetX(x);
+ obMega.setFeetY(y);
+ obMega.setCurDir(dir);
// Mega-set animation file
- ob_graph->anim_resource = ob_mega->megaset_res;
+ obGraph.setAnimResource(obMega.getMegasetRes());
// Dir + first stand frame (always frame 96)
- ob_graph->anim_pc = dir + 96;
+ obGraph.setAnimPc(dir + 96);
}
/**
- * stand mega at end position of anim
+ * Stand mega at end position of anim
*/
-void Router::standAfterAnim(ObjectGraphic *ob_graph, ObjectMega *ob_mega, uint32 animRes) {
+void Router::standAfterAnim(byte *ob_graph, byte *ob_mega, uint32 animRes) {
byte *anim_file = _vm->_resman->openResource(animRes);
- AnimHeader *anim_head = _vm->fetchAnimHeader(anim_file);
+ AnimHeader anim_head;
+
+ anim_head.read(_vm->fetchAnimHeader(anim_file));
- int32 x = anim_head->feetEndX;
- int32 y = anim_head->feetEndY;
- int32 dir = anim_head->feetEndDir;
+ int32 x = anim_head.feetEndX;
+ int32 y = anim_head.feetEndY;
+ int32 dir = anim_head.feetEndDir;
_vm->_resman->closeResource(animRes);
@@ -414,13 +426,15 @@ void Router::standAfterAnim(ObjectGraphic *ob_graph, ObjectMega *ob_mega, uint32
standAt(ob_graph, ob_mega, x, y, dir);
}
-void Router::standAtAnim(ObjectGraphic *ob_graph, ObjectMega *ob_mega, uint32 animRes) {
+void Router::standAtAnim(byte *ob_graph, byte *ob_mega, uint32 animRes) {
byte *anim_file = _vm->_resman->openResource(animRes);
- AnimHeader *anim_head = _vm->fetchAnimHeader(anim_file);
+ AnimHeader anim_head;
+
+ anim_head.read(_vm->fetchAnimHeader(anim_file));
- int32 x = anim_head->feetStartX;
- int32 y = anim_head->feetStartY;
- int32 dir = anim_head->feetStartDir;
+ int32 x = anim_head.feetStartX;
+ int32 y = anim_head.feetStartY;
+ int32 dir = anim_head.feetStartDir;
_vm->_resman->closeResource(animRes);