aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2003-09-09 17:29:22 +0000
committerMax Horn2003-09-09 17:29:22 +0000
commit07e8084eee1b0397b78aa6ee300855d1a1963503 (patch)
treeabe08649eb0c43447e68a28c186a618d57f2b9c5
parent163ecdc05406edd90dd4b336f23a8853a4b518d8 (diff)
downloadscummvm-rg350-07e8084eee1b0397b78aa6ee300855d1a1963503.tar.gz
scummvm-rg350-07e8084eee1b0397b78aa6ee300855d1a1963503.tar.bz2
scummvm-rg350-07e8084eee1b0397b78aa6ee300855d1a1963503.zip
replaced all use of scale items with scale slots. This allowed me to get rid of two big FIXME's, and might fix other scaling bugs in FT/DIG
svn-id: r10140
-rw-r--r--scumm/actor.cpp41
-rw-r--r--scumm/boxes.cpp139
-rw-r--r--scumm/saveload.cpp9
-rw-r--r--scumm/saveload.h2
-rw-r--r--scumm/script_v5.cpp2
-rw-r--r--scumm/scumm.h1
-rw-r--r--scumm/scummvm.cpp28
7 files changed, 86 insertions, 136 deletions
diff --git a/scumm/actor.cpp b/scumm/actor.cpp
index f451c890e6..e59dae2ffd 100644
--- a/scumm/actor.cpp
+++ b/scumm/actor.cpp
@@ -412,47 +412,10 @@ void Actor::setupActorScale() {
return;
scale = _vm->getScale(walkbox, x, y);
- if (_vm->_version == 8) {
- // At least in COMI, scale values are clipped to range 1-255
- if (scale < 1)
- scale = 1;
- else if (scale > 255)
- scale = 255;
- }
-
- // FIXME - Hack for The Dig 'Tomb' (room 88)
- // Otherwise walking to the far-left door causes the actor
- // to shrink to a one-pixel dot. The reason for this is that
- // scale items (as handled in setScaleItem etc.) are only
- // working as long as the room height is <= 200!!! That's a
- // serious problem for DIG/FT, and causes the FIXME below, too.
- // A way to properly fix the problem would be to use the
- // V8 "scale slots" instead. This would be almost perfect, the
- // only problem being that it might render some old savegames
- // partially broken...
- if (_vm->_gameId == GID_DIG && _vm->_currentRoom == 88) {
- scale = 0xFF;
- }
-
-
- // FIXME - Quick fix to ft's fuel tower bug (by yazoo)
- //
- // Ben's Y position can be anything between 272 and 398 inclusive
- // (which by the way means that we're always looking at the same
- // element in the scale table... hmmm...)
- //
- // 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 (_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);
+ 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 4376107169..325d66d364 100644
--- a/scumm/boxes.cpp
+++ b/scumm/boxes.cpp
@@ -155,53 +155,58 @@ int Scumm::getScale(int box, int x, int y) {
Box *ptr = getBoxBaseAddr(box);
if (!ptr)
return 255;
+
+ int slot , scale;
if (_version == 8) {
- int slot = FROM_LE_32(ptr->v8.scaleSlot);
- if (slot) {
- assert(1 <= slot && slot <= ARRAYSIZE(_scaleSlots));
- int scaleX = 0, scaleY = 0;
- ScaleSlot &s = _scaleSlots[slot-1];
-
- 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;
- }
- }
+ // COMI has a separate field for the scale slot...
+ slot = FROM_LE_32(ptr->v8.scaleSlot);
+ scale = FROM_LE_32(ptr->v8.scale);
+ } else {
+ scale = READ_LE_UINT16(&ptr->old.scale);
+ if (scale & 0x8000)
+ slot = (scale & 0x7FFF) + 1;
+ else
+ slot = 0;
+ }
+
+ // Was a scale slot specified? If so, we compute the effective scale
+ // from it, ignoring the box scale.
+ if (slot) {
+ assert(1 <= slot && slot <= ARRAYSIZE(_scaleSlots));
+ int scaleX = 0, scaleY = 0;
+ ScaleSlot &s = _scaleSlots[slot-1];
+
+ 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) {
+ scale = scaleY;
+ } else {
scaleX = (s.scale2 - s.scale1) * (x - s.x1) / (s.x2 - s.x1) + s.scale1;
if (s.y1 == s.y2) {
- return scaleX;
+ scale = scaleX;
} else {
- return (scaleX + scaleY - s.x1) / 2;
+ scale = (scaleX + scaleY - s.x1) / 2;
}
- } else
- return FROM_LE_32(ptr->v8.scale);
- } else {
- uint16 scale = READ_LE_UINT16(&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 >= _screenHeight)
- y = _screenHeight - 1;
- else if (y < 0)
- y = 0;
- scale = resptr[y];
}
-
- return scale;
+
+ // Clip the scale to range 1-255
+ if (scale < 1)
+ scale = 1;
+ else if (scale > 255)
+ scale = 255;
}
+
+ // Finally return the scale
+ return scale;
}
int Scumm::getBoxScale(int box) {
@@ -216,60 +221,36 @@ int Scumm::getBoxScale(int box) {
return READ_LE_UINT16(&ptr->old.scale);
}
-/*
- FIXME: It seems that scale items and scale slots are the same thing after
- all - they only differ in some details (scale item is used to precompute
- a scale table, while for the scale slots the computations are done on the
- fly; also for scale slots, the scale along the x axis can vary, too).
-
- Now, there are various known scale glitches in FT (and apparently also
- in The Dig, see FIXME comments in Actor::setupActorScale). In this context
- it is very interesting that for V5, there is an opcode which invokes
- setScaleItem, and for V8 one that invokes setScaleSlot. But there is no
- such opcode to be found for V6/V7 games.
-
- Hypothesis: we simple are missing this opcode, and implementing it might
- fix some or all of the Dig/FT scaling issues.
-*/
-void Scumm::setScaleItem(int slot, int y1, int scale1, int y2, int scale2) {
- byte *ptr;
- int y, tmp;
-
- if (y1 == y2)
- return;
-
- ptr = createResource(rtScaleTable, slot, 200);
-
- for (y = 0; y < 200; y++) {
- tmp = ((scale2 - scale1) * (y - y1)) / (y2 - y1) + scale1;
- if (tmp < 1)
- tmp = 1;
- if (tmp > 255)
- tmp = 255;
- *ptr++ = tmp;
- }
-/*
- // TEST!
- printf("setScaleItem(%d, %d, %d, %d, %d)\n", slot, y1, scale1, y2, scale2);
- convertScaleTableToScaleSlot(slot);
-*/
-}
-
+/**
+ * Convert a rtScaleTable resource to a corresponding scale slot entry.
+ *
+ * At some point, we discovered that the old scale items (stored in rtScaleTable
+ * resources) are in fact the same as (or rather, a predecessor of) the
+ * scale slots used in COMI. While not being precomputed (and thus slightly
+ * slower), they are more flexible, and most importantly, can cope with
+ * rooms higher than 200 pixels. That's an essential feature for DIG and FT
+ * and in fact the lack of it caused various bugs in the past.
+ *
+ * Hence, we decided to switch all games to use the more powerful scale slots.
+ * To accomodate old savegames, we attempt here to convert rtScaleTable
+ * resources to scale slots.
+ */
void Scumm::convertScaleTableToScaleSlot(int slot) {
assert(1 <= slot && slot <= ARRAYSIZE(_scaleSlots));
byte *resptr = getResourceAddress(rtScaleTable, slot);
ScaleSlot &s = _scaleSlots[slot-1];
-
int lowerIdx, upperIdx;
float m, oldM;
+ // Do nothing if the given scale table doesn't exist
+ if (resptr == 0)
+ return;
+
if (resptr[0] == resptr[199]) {
// The scale is constant This usually means we encountered one of the
// "broken" cases. We set pseudo scale item values which lead to a
// constant scale of 255.
- // TODO
- printf("Broken case!\n");
s.y1 = 0;
s.y2 = 199;
s.scale1 = s.scale2 = 255;
diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp
index 5e06e851bd..89be05d0db 100644
--- a/scumm/saveload.cpp
+++ b/scumm/saveload.cpp
@@ -658,6 +658,15 @@ void Scumm::saveOrLoad(Serializer *s, uint32 savegameVersion) {
}
}
+ // With version 22, we replace the scale items with scale slots
+ if (savegameVersion < VER(22) && !s->isSaving()) {
+ // Convert all rtScaleTable resources to matching scale items
+ for (i = 1; i < res.num[rtScaleTable]; i++) {
+ convertScaleTableToScaleSlot(i);
+ }
+ }
+
+
if (_imuse && (_saveSound || !_saveLoadCompatible)) {
_imuse->save_or_load(s, this);
_imuse->setMasterVolume(_sound->_sound_volume_master);
diff --git a/scumm/saveload.h b/scumm/saveload.h
index e20fc1237f..225d295c24 100644
--- a/scumm/saveload.h
+++ b/scumm/saveload.h
@@ -28,7 +28,7 @@
// Can be useful for other ports too :)
#define VER(x) x
-#define CURRENT_VER 21
+#define CURRENT_VER 22
// To work around a warning in GCC 3.2 (and 3.1 ?) regarding non-POD types,
// we use a small trick: instead of 0 we use 42. Why? Well, it seems newer GCC
diff --git a/scumm/script_v5.cpp b/scumm/script_v5.cpp
index 5ff8e09a72..6e5f4c6be1 100644
--- a/scumm/script_v5.cpp
+++ b/scumm/script_v5.cpp
@@ -1867,7 +1867,7 @@ void Scumm_v5::o5_roomOps() {
d = getVarOrDirectByte(0x40);
_opcode = fetchScriptByte();
e = getVarOrDirectByte(0x40);
- setScaleItem(e - 1, b, a, d, c);
+ setScaleSlot(e - 1, 0, b, a, 0, d, c);
break;
case 8: /* room scale? */
if (_features & GF_SMALL_HEADER) {
diff --git a/scumm/scumm.h b/scumm/scumm.h
index ec8020ab6e..41d5ad3b1c 100644
--- a/scumm/scumm.h
+++ b/scumm/scumm.h
@@ -1051,7 +1051,6 @@ public:
int getBoxScale(int box);
int getScale(int box, int x, int y);
- void setScaleItem(int slot, int a, int b, int c, int d);
protected:
// Scaling slots/items
diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp
index 35ecd61ea5..72fc298241 100644
--- a/scumm/scummvm.cpp
+++ b/scumm/scummvm.cpp
@@ -1996,7 +1996,7 @@ void Scumm::startScene(int room, Actor *a, int objectNr) {
}
void Scumm::initRoomSubBlocks() {
- int i, offs;
+ int i;
const byte *ptr;
byte *roomptr, *searchptr, *roomResPtr;
const RoomHeader *rmhd;
@@ -2178,29 +2178,27 @@ void Scumm::initRoomSubBlocks() {
// Load scale data
//
if (_features & GF_OLD_BUNDLE)
- ptr = 0; // TODO ?
+ ptr = 0;
else
ptr = findResourceData(MKID('SCAL'), roomptr);
if (ptr) {
- offs = ptr - roomptr;
int s1, s2, y1, y2;
if (_version == 8) {
- for (i = 1; i < _maxScaleTable; i++, offs += 16) {
- s1 = READ_LE_UINT32(roomptr + offs);
- y1 = READ_LE_UINT32(roomptr + offs + 4);
- s2 = READ_LE_UINT32(roomptr + offs + 8);
- y2 = READ_LE_UINT32(roomptr + offs + 12);
+ for (i = 1; i < _maxScaleTable; i++, ptr += 16) {
+ s1 = READ_LE_UINT32(ptr);
+ y1 = READ_LE_UINT32(ptr + 4);
+ s2 = READ_LE_UINT32(ptr + 8);
+ y2 = READ_LE_UINT32(ptr + 12);
setScaleSlot(i, 0, y1, s1, 0, y2, s2);
}
} else {
- for (i = 1; i < _maxScaleTable; i++, offs += 8) {
- s1 = READ_LE_UINT16(roomptr + offs);
- y1 = READ_LE_UINT16(roomptr + offs + 2);
- s2 = READ_LE_UINT16(roomptr + offs + 4);
- y2 = READ_LE_UINT16(roomptr + offs + 6);
+ for (i = 1; i < _maxScaleTable; i++, ptr += 8) {
+ s1 = READ_LE_UINT16(ptr);
+ y1 = READ_LE_UINT16(ptr + 2);
+ s2 = READ_LE_UINT16(ptr + 4);
+ y2 = READ_LE_UINT16(ptr + 6);
if (s1 || y1 || s2 || y2) {
- setScaleItem(i, y1, s1, y2, s2);
- roomptr = getResourceAddress(rtRoom, _roomResource);
+ setScaleSlot(i, 0, y1, s1, 0, y2, s2);
}
}
}