From eb9726c4974111ac56bbc256658785f06d4df531 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 13 Jan 2003 01:29:45 +0000 Subject: added V8 scaling code svn-id: r6440 --- scumm/actor.cpp | 30 +++++++++++------------------ scumm/boxes.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++- scumm/saveload.cpp | 13 +++++++++++++ scumm/saveload.h | 19 ++++++++++-------- scumm/script_v8.cpp | 1 + scumm/scumm.h | 14 +++++++++++++- scumm/scummvm.cpp | 23 ++++++++++++++-------- 7 files changed, 118 insertions(+), 37 deletions(-) (limited to 'scumm') diff --git a/scumm/actor.cpp b/scumm/actor.cpp index 18e7d32f80..2066f01500 100644 --- a/scumm/actor.cpp +++ b/scumm/actor.cpp @@ -354,7 +354,6 @@ int Actor::actorWalkStep() void Actor::setupActorScale() { uint16 scale; - byte *resptr; if (_vm->_features & GF_NO_SCALLING) { scalex = 0xFF; @@ -368,20 +367,7 @@ void Actor::setupActorScale() if (_vm->getBoxFlags(walkbox) & kBoxPlayerOnly) return; - scale = _vm->getBoxScale(walkbox); - - if (scale & 0x8000) { - scale = (scale & 0x7FFF) + 1; - resptr = _vm->getResourceAddress(rtScaleTable, scale); - if (resptr == NULL) - error("Scale table %d not defined", scale); - int theY = y; - if (theY >= _vm->_realHeight) - theY = _vm->_realHeight - 1; - else if (theY < 0) - theY = 0; - scale = resptr[theY]; - } + scale = _vm->getScale(walkbox, x, y); // FIXME - Hack for The Dig 'Tomb' (room 88) // Otherwise walking to the far-left door causes the actor @@ -400,15 +386,21 @@ void Actor::setupActorScale() // When standing at the bottom of the ladder, Ben's Y position is // 356, and by the looks of it he ought to be unscaled there. - if (scale == 1 && _vm->_currentRoom == 76) { + if (_vm->_gameId == GID_FT && scale == 1 && _vm->_currentRoom == 76) { scale = 0xff; if (y < 356) scale -= 2 * (356 - y); } - if (scale > 255) - warning("Actor %d at %d, scale %d out of range", number, y, scale); - + if (scale > 255) { + if (_vm->_features & GF_AFTER_V8) { + // In COMI, the scale values often are bigger than 255; + // however, the original engine seems to just cap them at 255, + // hence we do the same (the result looks correct, too); + scale = 255; + } else + warning("Actor %d at %d, scale %d out of range", number, y, scale); + } scalex = (byte)scale; scaley = (byte)scale; } diff --git a/scumm/boxes.cpp b/scumm/boxes.cpp index a22d5c5ee0..c57ca1e27e 100644 --- a/scumm/boxes.cpp +++ b/scumm/boxes.cpp @@ -50,7 +50,7 @@ struct Box { /* Internal walkbox file format */ int32 llx, lly; uint32 mask; // FIXME - is 'mask' really here? uint32 flags; // FIXME - is 'flags' really here? - uint32 unk1; + uint32 scaleSlot; uint32 scale; uint32 unk2; uint32 unk3; @@ -128,6 +128,59 @@ void Scumm::setBoxScale(int box, int scale) b->old.scale = TO_LE_16(scale); } +int Scumm::getScale(int box, int x, int y) +{ + Box *ptr = getBoxBaseAddr(box); + assert(ptr); + + if (_features & GF_AFTER_V8) { + int slot = FROM_LE_32(ptr->v8.scaleSlot); + if (slot) { + assert(0 <= slot && slot < 20); + int scaleX = 0, scaleY = 0; + ScaleSlot &s = _scaleSlots[slot]; + + if (s.y1 == s.y2 && s.x1 == s.x2) + error("Invalid scale slot %d", slot); + + if (s.y1 != s.y2) { + if (y < 0) + y = 0; + + scaleY = (s.scale2 - s.scale1) * (y - s.y1) / (s.y2 - s.y1) + s.scale1; + if (s.x1 == s.x2) { + return scaleY; + } + } + + scaleX = (s.scale2 - s.scale1) * (x - s.x1) / (s.x2 - s.x1) + s.scale1; + + if (s.y1 == s.y2) { + return scaleX; + } else { + return (scaleX + scaleY - s.x1) / 2; + } + } else + return FROM_LE_32(ptr->v8.scale); + } else { + uint16 scale = FROM_LE_16(ptr->old.scale); + + if (scale & 0x8000) { + scale = (scale & 0x7FFF) + 1; + byte *resptr = getResourceAddress(rtScaleTable, scale); + if (resptr == NULL) + error("Scale table %d not defined", scale); + if (y >= _realHeight) + y = _realHeight - 1; + else if (y < 0) + y = 0; + scale = resptr[y]; + } + + return scale; + } +} + int Scumm::getBoxScale(int box) { if (_features & GF_NO_SCALLING) diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp index bf9ea4427c..d5520e828a 100644 --- a/scumm/saveload.cpp +++ b/scumm/saveload.cpp @@ -532,6 +532,16 @@ void Scumm::saveOrLoad(Serializer *s, uint32 savegameVersion) MKEND() }; + const SaveLoadEntry scaleSlotsEntries[] = { + MKLINE(ScaleSlot, x1, sleUint16, VER_V13), + MKLINE(ScaleSlot, y1, sleUint16, VER_V13), + MKLINE(ScaleSlot, scale1, sleUint16, VER_V13), + MKLINE(ScaleSlot, x2, sleUint16, VER_V13), + MKLINE(ScaleSlot, y2, sleUint16, VER_V13), + MKLINE(ScaleSlot, scale2, sleUint16, VER_V13), + MKEND() + }; + int i, j; int var120Backup; int var98Backup; @@ -564,6 +574,9 @@ void Scumm::saveOrLoad(Serializer *s, uint32 savegameVersion) s->saveLoadArrayOf(_string, 6, sizeof(_string[0]), stringTabEntries); s->saveLoadArrayOf(_colorCycle, 16, sizeof(_colorCycle[0]), colorCycleEntries); + if (savegameVersion >= VER_V13) + s->saveLoadArrayOf(_scaleSlots, 20, sizeof(_scaleSlots[0]), scaleSlotsEntries); + for (i = rtFirst; i <= rtLast; i++) if (res.mode[i] == 0) for (j = 1; j < res.num[i]; j++) diff --git a/scumm/saveload.h b/scumm/saveload.h index 9ac60b4eff..5934c8e154 100644 --- a/scumm/saveload.h +++ b/scumm/saveload.h @@ -25,14 +25,17 @@ // Support for "old" savegames (made with 2501 CVS build) // Can be useful for other ports too :) -#define VER_V12 12 -#define VER_V11 11 -#define VER_V10 10 -#define VER_V9 9 -#define VER_V8 8 -#define VER_V7 7 - -#define CURRENT_VER VER_V12 +enum { + VER_V7 = 7, + VER_V8, + VER_V9, + VER_V10, + VER_V11, + VER_V12, + VER_V13 +}; + +#define CURRENT_VER VER_V13 // To work around a warning in GCC 3.2 (and 3.1 ?) regarding non-POD types, diff --git a/scumm/script_v8.cpp b/scumm/script_v8.cpp index 2bf668a240..b0fcb34ac3 100644 --- a/scumm/script_v8.cpp +++ b/scumm/script_v8.cpp @@ -1378,6 +1378,7 @@ void Scumm_v8::o8_kernelSetFunctions() break; case 21: // setScaleSlot warning("o8_kernelSetFunctions: setScaleSlot(%d, %d, %d, %d, %d, %d, %d)", args[1], args[2], args[3], args[4], args[5], args[6], args[7]); + setScaleSlot(args[1], args[2], args[3], args[4], args[5], args[6], args[7]); break; case 22: // setBannerColors // warning("o8_kernelSetFunctions: setBannerColors(%d, %d, %d, %d)", args[1], args[2], args[3], args[4]); diff --git a/scumm/scumm.h b/scumm/scumm.h index e7b6524b30..7c32b8ff99 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -378,7 +378,6 @@ public: byte _numObjectsInRoom; int8 _userPut; int _resourceHeaderSize; - void setScaleItem(int slot, int a, int b, int c, int d); void clearClickedStatus(); void startManiac(); @@ -854,6 +853,19 @@ public: Box *getBoxBaseAddr(int box); byte getBoxFlags(int box); int getBoxScale(int box); + + int getScale(int box, int x, int y); + void setScaleItem(int slot, int a, int b, int c, int d); + + // V8 scaling stuff: should be in V8 class + struct ScaleSlot { + int x1, y1, scale1; + int x2, y2, scale2; + }; + ScaleSlot _scaleSlots[20]; // FIXME - not sure if this limit is right, but based on my observations it is + void setScaleSlot(int slot, int x1, int y1, int scale1, int x2, int y2, int scale2); + + byte getNumBoxes(); byte *getBoxMatrixBaseAddr(); int getPathToDestBox(byte from, byte to); diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp index cb8f1d8cb7..63afbc2286 100644 --- a/scumm/scummvm.cpp +++ b/scumm/scummvm.cpp @@ -835,14 +835,11 @@ void Scumm::initRoomSubBlocks() offs = ptr - roomptr; if (_features & GF_AFTER_V8) { for (i = 1; i < _maxScaleTable; i++, offs += 16) { - int a = READ_LE_UINT32(roomptr + offs); - int b = READ_LE_UINT32(roomptr + offs + 4); - int c = READ_LE_UINT32(roomptr + offs + 8); - int d = READ_LE_UINT32(roomptr + offs + 12); - if (a || b || c || d) { - setScaleItem(i, b, a, d, c); - roomptr = getResourceAddress(rtRoom, _roomResource); - } + int scale1 = READ_LE_UINT32(roomptr + offs); + int y1 = READ_LE_UINT32(roomptr + offs + 4); + int scale2 = READ_LE_UINT32(roomptr + offs + 8); + int y2 = READ_LE_UINT32(roomptr + offs + 12); + setScaleSlot(i, 0, y1, scale1, 0, y2, scale2); } } else { for (i = 1; i < _maxScaleTable; i++, offs += 8) { @@ -981,6 +978,16 @@ void Scumm::setScaleItem(int slot, int a, int b, int c, int d) } } +void Scumm::setScaleSlot(int slot, int x1, int y1, int scale1, int x2, int y2, int scale2) +{ + _scaleSlots[slot].x2 = x2; + _scaleSlots[slot].y2 = y2; + _scaleSlots[slot].scale2 = scale2; + _scaleSlots[slot].x1 = x1; + _scaleSlots[slot].y1 = y1; + _scaleSlots[slot].scale1 = scale1; +} + void Scumm::dumpResource(char *tag, int idx, byte *ptr) { char buf[256]; -- cgit v1.2.3