aboutsummaryrefslogtreecommitdiff
path: root/sword2
diff options
context:
space:
mode:
authorTorbjörn Andersson2005-10-29 21:24:54 +0000
committerTorbjörn Andersson2005-10-29 21:24:54 +0000
commit7f4cda6622990b7aa26e433ecdc8f17b8a3b237d (patch)
tree5a7e7f9613ff2601a7bf70477b34b30b8c0a21dc /sword2
parentbcccd3f558bbbdab07d355dabfb072298e4f5cf2 (diff)
downloadscummvm-rg350-7f4cda6622990b7aa26e433ecdc8f17b8a3b237d.tar.gz
scummvm-rg350-7f4cda6622990b7aa26e433ecdc8f17b8a3b237d.tar.bz2
scummvm-rg350-7f4cda6622990b7aa26e433ecdc8f17b8a3b237d.zip
Applied my own patch #1341495, in an attempt to fix alignment issues
reported by Crilith. To elaborate a bit, the engine no longer accesses resource data through packed structs. Instead it uses memory streams and the READ/WRITE functions. If data is mainly read, not written, I have replaced the old struct with a new one with a read() function to read the whole thing from memory into the struct's variables, and a write() function to dump the struct's variables to memory. In fact, most of these write() functions remain unused. If data is both read and written, I have replaced the struct with a class with individual get/set functions to replace the old variables. This manipulates memory directly. Since I'm fairly sure that these structs are frequently stored as local variables for a script, all script variables (both local and global) are stored as little-endian and accessed through the READ/WRITE functions, rather than being treated as arrays of 32-bit integers. On a positive note, the functions for doing endian conversion of resources and save games have been removed, and some general cleanups have been made to assist in the rewrite. Initial reports indicate that this patch indeed fixes alignment issues, and that I have not - surprisingly - broken the game on big-endian platforms. At least not in any immediately obvious way. And there's still plenty of time to fix regressions before 0.9.0, too. svn-id: r19366
Diffstat (limited to 'sword2')
-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);