aboutsummaryrefslogtreecommitdiff
path: root/scumm/boxes.cpp
diff options
context:
space:
mode:
authorMax Horn2003-09-09 16:55:25 +0000
committerMax Horn2003-09-09 16:55:25 +0000
commit163ecdc05406edd90dd4b336f23a8853a4b518d8 (patch)
tree1525cead371a2dba66fe3c00e3db7a1ca74a1f42 /scumm/boxes.cpp
parentd5f42972218a11522ac12bc580b566295fa2f7e4 (diff)
downloadscummvm-rg350-163ecdc05406edd90dd4b336f23a8853a4b518d8.tar.gz
scummvm-rg350-163ecdc05406edd90dd4b336f23a8853a4b518d8.tar.bz2
scummvm-rg350-163ecdc05406edd90dd4b336f23a8853a4b518d8.zip
added convertScaleTableToScaleSlot method, preparing to replace scale items with scale slots
svn-id: r10139
Diffstat (limited to 'scumm/boxes.cpp')
-rw-r--r--scumm/boxes.cpp121
1 files changed, 113 insertions, 8 deletions
diff --git a/scumm/boxes.cpp b/scumm/boxes.cpp
index 40a5e7a2a7..4376107169 100644
--- a/scumm/boxes.cpp
+++ b/scumm/boxes.cpp
@@ -159,7 +159,7 @@ int Scumm::getScale(int box, int x, int y) {
if (_version == 8) {
int slot = FROM_LE_32(ptr->v8.scaleSlot);
if (slot) {
- assert(1 <= slot && slot <= 20);
+ assert(1 <= slot && slot <= ARRAYSIZE(_scaleSlots));
int scaleX = 0, scaleY = 0;
ScaleSlot &s = _scaleSlots[slot-1];
@@ -248,16 +248,121 @@ void Scumm::setScaleItem(int slot, int y1, int scale1, int y2, int scale2) {
tmp = 255;
*ptr++ = tmp;
}
+/*
+ // TEST!
+ printf("setScaleItem(%d, %d, %d, %d, %d)\n", slot, y1, scale1, y2, scale2);
+ convertScaleTableToScaleSlot(slot);
+*/
+}
+
+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;
+
+ 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;
+ return;
+ }
+
+ /*
+ * Essentially, what we are doing here is some kind of "line fitting"
+ * algorithm. The data in the scale table represents a linear graph. What
+ * we want to find is the slope and (vertical) offset of this line. Things
+ * are complicated by the fact that the line is cut of vertically at 1 and
+ * 255. We have to be careful in handling this and some border cases.
+ *
+ * Some typical graphs look like these:
+ * --- --- ---
+ * / --- \
+ * ___/ --- \___
+ *
+ * The method used here is to compute the slope of secants fixed at the
+ * left and right end. For most cases this detects the cut-over points
+ * quite accurately.
+ */
+
+ // Search for the bend on the left side
+ m = (resptr[199] - resptr[0]) / 199.0;
+ for (lowerIdx = 0; lowerIdx < 199 && (resptr[lowerIdx] == 1 || resptr[lowerIdx] == 255); lowerIdx++) {
+ oldM = m;
+ m = (resptr[199] - resptr[lowerIdx+1]) / (float)(199 - (lowerIdx+1));
+ if (m > 0) {
+ if (m <= oldM)
+ break;
+ } else {
+ if (m >= oldM)
+ break;
+ }
+ }
+
+ // Search for the bend on the right side
+ m = (resptr[199] - resptr[0]) / 199.0;
+ for (upperIdx = 199; upperIdx > 1 && (resptr[upperIdx] == 1 || resptr[upperIdx] == 255); upperIdx--) {
+ oldM = m;
+ m = (resptr[upperIdx-1] - resptr[0]) / (float)(upperIdx-1);
+ if (m > 0) {
+ if (m <= oldM)
+ break;
+ } else {
+ if (m >= oldM)
+ break;
+ }
+ }
+
+ // If lowerIdx and upperIdx are equal, we assume that there
+ // was no bend at all, and go for the maximum range.
+ if (lowerIdx == upperIdx) {
+ lowerIdx = 0;
+ upperIdx = 199;
+ }
+
+ // The values of y1 and y2, as well as the scale, can now easily be computed
+ s.y1 = lowerIdx;
+ s.y2 = upperIdx;
+ s.scale1 = resptr[lowerIdx];
+ s.scale2 = resptr[upperIdx];
+
+
+ // Compute the variance, for debugging. It shouldn't exceed 1
+ int y;
+ int sum = 0;
+ int scale;
+ float variance;
+ for (y = 0; y < 200; y++) {
+ scale = (s.scale2 - s.scale1) * (y - s.y1) / (s.y2 - s.y1) + s.scale1;
+ if (scale < 1)
+ scale = 1;
+ else if (scale > 255)
+ scale = 255;
+
+ sum += (resptr[y] - scale) * (resptr[y] - scale);
+ }
+ variance = sum / (200.0 - 1.0);
+ if (variance > 1)
+ warning("scale item %d, variance %f exceeds 1 (room %d)\n", slot, variance, _currentRoom);
}
void Scumm::setScaleSlot(int slot, int x1, int y1, int scale1, int x2, int y2, int scale2) {
- assert(1 <= slot && slot <= 20);
- _scaleSlots[slot-1].x2 = x2;
- _scaleSlots[slot-1].y2 = y2;
- _scaleSlots[slot-1].scale2 = scale2;
- _scaleSlots[slot-1].x1 = x1;
- _scaleSlots[slot-1].y1 = y1;
- _scaleSlots[slot-1].scale1 = scale1;
+ assert(1 <= slot && slot <= ARRAYSIZE(_scaleSlots));
+ ScaleSlot &s = _scaleSlots[slot-1];
+ s.x2 = x2;
+ s.y2 = y2;
+ s.scale2 = scale2;
+ s.x1 = x1;
+ s.y1 = y1;
+ s.scale1 = scale1;
}
byte Scumm::getNumBoxes() {