aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scumm/akos.cpp191
-rw-r--r--scumm/gfx.cpp361
-rw-r--r--scumm/object.cpp151
-rw-r--r--scumm/scumm.h21
4 files changed, 496 insertions, 228 deletions
diff --git a/scumm/akos.cpp b/scumm/akos.cpp
index de5bbdb9e3..9ee3b0b4f6 100644
--- a/scumm/akos.cpp
+++ b/scumm/akos.cpp
@@ -137,6 +137,15 @@ void AkosRenderer::setPalette(byte *new_palette)
for (i = 0; i < size; i++) {
palette[i] = new_palette[i] != 0xFF ? new_palette[i] : the_akpl[i];
}
+
+ if (size == 256) {
+ byte color = new_palette[0];
+ if (color == 255) {
+ palette[0] = color;
+ } else {
+ _vm->_bompActorPalletePtr = palette;
+ }
+ }
}
void AkosRenderer::setCostume(int costume)
@@ -842,143 +851,87 @@ void AkosRenderer::codec1_ignorePakCols(int num)
} while (1);
}
+void AkosRenderer::codec5() {
+ int32 clip_left, clip_right, clip_top, clip_bottom, maxw, maxh, tmp_x, tmp_y;
-void AkosRenderer::codec5()
-{
- int left, right, top, bottom;
- int clip_left, clip_right, clip_top, clip_bottom;
-
- byte *src, *dest;
- int src_x, src_y;
- int dst_x, dst_y;
+ _vm->_bompShadowMode = shadow_mode;
- bool masking;
- byte maskbit;
- byte *mask = NULL;
-
- // I don't know if this is complete. It used to simply call drawBomp()
- // to draw an unscaled image, but I don't know if that was because it
- // will never have to scale, or if it's because until quite recently
- // drawBomp() didn't know how to scale images.
- //
- // What I do know is that drawBomp() doesn't care about masking and
- // shadows, and these are both needed for Full Throttle and The Dig.
-
if (!mirror) {
- left = (_x - move_x_cur - _width) + 1;
+ clip_left = (_x - move_x_cur - _width) + 1;
} else {
- left = _x + move_x_cur - 1;
+ clip_left = _x + move_x_cur - 1;
+ }
+
+ clip_right = (clip_left + _width) - 1;
+ clip_top = _y + move_y_cur;
+ clip_bottom = (clip_top + _height) - 1;
+ maxw = outwidth - 1;
+ maxh = outheight - 1;
+
+ if (clip_left < 0) {
+ clip_left = 0;
+ }
+
+ tmp_x = clip_right - maxw;
+ if (tmp_x > 0) {
+ clip_right -= tmp_x;
+ }
+
+ tmp_y = clip_top;
+ if (tmp_y < 0) {
+ clip_top -= tmp_y;
}
- right = left + _width;
- top = _y + move_y_cur;
- bottom = top + _height;
+ tmp_y = clip_bottom - maxh;
+ if (tmp_y > 0) {
+ clip_bottom -= tmp_y;
+ }
- if (left >= (int) outwidth || top >= (int) outheight)
+ if ((clip_right <= clip_left) || (clip_top >= clip_bottom))
return;
- // The actual drawing code shouldn't survive even if the image is
- // partially outside the screen, but something before that seems to
- // be less tolerant...
+ _vm->updateDirtyRect(0, clip_left, clip_right + 1, clip_top, clip_bottom + 1, 1 << dirty_id);
- clip_left = (left >= 0) ? left : 0;
- clip_right = (right > (int) outwidth) ? (int) outwidth : right;
- clip_top = (top >= 0) ? top : 0;
- clip_bottom = (bottom > (int) outheight) ? (int) outheight : bottom;
-
if (clip_top < draw_top)
draw_top = clip_top;
if (clip_bottom > draw_bottom)
- draw_bottom = clip_bottom;
-
- _vm->updateDirtyRect(0, clip_left, clip_right, clip_top, clip_bottom, 1 << dirty_id);
-
- masking = false;
- if (clipping) {
- masking = _vm->isMaskActiveAt(clip_left, clip_top, clip_right, clip_bottom,
- _vm->getResourceAddress(rtBuffer, 9) +
- _vm->gdi._imgBufOffs[clipping] +
- _vm->_screenStartStrip) != 0;
- }
+ draw_bottom = clip_bottom + 1;
- v1.mask_ptr = NULL;
+ BompDrawData bdd;
- if (masking || charsetmask) {
- v1.mask_ptr = _vm->getResourceAddress(rtBuffer, 9) + _vm->_screenStartStrip;
- v1.imgbufoffs = _vm->gdi._imgBufOffs[clipping];
- if (!charsetmask && masking) {
- v1.mask_ptr += v1.imgbufoffs;
- v1.imgbufoffs = 0;
- }
- }
+ bdd.srcwidth = _width;
+ bdd.srcheight = _height;
+ bdd.out = outptr;
+ bdd.outwidth = outwidth;
+ bdd.outheight = outheight;
+ bdd.dataptr = srcptr;
+ bdd.scale_x = 255;
+ bdd.scale_y = 255;
- src = srcptr;
- dest = outptr;
+ _vm->_bompScallingXPtr = NULL;
+ _vm->_bompScallingYPtr = NULL;
- for (src_y = 0, dst_y = top; src_y < _height; src_y++) {
- byte code, color;
- uint num, i;
- byte *d = dest + dst_y * outwidth + left;
- byte *s;
- uint data_length;
+ int decode_mode;
- data_length = READ_LE_UINT16(src) + 2;
+ if (!mirror) {
+ bdd.x = (_x - move_x_cur - _width) + 1;
+ decode_mode = 3;
+ } else {
+ bdd.x = _x + move_x_cur;
+ decode_mode = 1;
+ }
- if (dst_y < 0 || dst_y >= (int) outheight) {
- src += data_length;
- dst_y++;
- continue;
- }
+ bdd.y = _y + move_y_cur;
- src_x = 0;
- dst_x = left;
- s = src + 2;
-
- while (src_x < _width) {
- code = *s++;
- num = (code >> 1) + 1;
- if (code & 1) {
- color = *s++;
- for (i = 0; i < num; i++) {
- if (dst_x >= 0 && dst_x < (int) outwidth) {
- if (color != 255) {
- if (v1.mask_ptr)
- mask = v1.mask_ptr + _numStrips * dst_y + (dst_x >> 3);
- maskbit = revBitMask[dst_x & 7];
- if (shadow_mode && color == 13)
- color = shadow_table[*d];
- if (!mask || !((mask[0] | mask[v1.imgbufoffs]) & maskbit))
- *d = color;
- }
- }
- d++;
- dst_x++;
- src_x++;
- }
- } else {
- for (i = 0; i < num; i++) {
- color = s[i];
- if (dst_x >= 0 && dst_x < (int) outwidth) {
- if (color != 255) {
- if (v1.mask_ptr)
- mask = v1.mask_ptr + _numStrips * dst_y + (dst_x >> 3);
- maskbit = revBitMask[dst_x & 7];
- if (shadow_mode && color == 13)
- color = shadow_table[*d];
- if (!mask || !((mask[0] | mask[v1.imgbufoffs]) & maskbit))
- *d = color;
- }
- }
- d++;
- dst_x++;
- src_x++;
- }
- s += num;
- }
- }
- src += data_length;
- dst_y++;
+ if (clipping != 0) {
+ _vm->_bompMaskPtr = _vm->getResourceAddress(rtBuffer, 9) + _vm->_screenStartStrip + _vm->gdi._imgBufOffs[clipping];
+ _vm->_bompMaskPitch = _vm->_realWidth / 8;
+ _vm->drawBomp(&bdd, 0, bdd.dataptr, decode_mode, 1);
+ } else {
+ _vm->drawBomp(&bdd, 0, bdd.dataptr, decode_mode, 0);
}
+
+ _vm->_bompActorPalletePtr = NULL;
}
void AkosRenderer::akos16SetupBitReader(byte *src) {
@@ -1195,7 +1148,7 @@ void AkosRenderer::akos16DecompressMask(byte * dest, int32 pitch, byte * src, in
akos16SkipData(numskip_before);
}
- maskpitch = _numStrips + 1;
+ maskpitch = _numStrips ;
while (t_height != 0) {
akos16DecodeLine(tmp_buf, t_width, dir);
@@ -1286,7 +1239,7 @@ void AkosRenderer::codec16() {
if (!mirror) {
dir = -1;
-
+
int tmp_skip_x = skip_x;
skip_x = _width-1-cur_x;
cur_x = _width-1-tmp_skip_x;
@@ -1331,7 +1284,7 @@ void AkosRenderer::codec16() {
}
byte * ptr = _vm->_screenStartStrip + _vm->getResourceAddress(rtBuffer, 9) + _vm->gdi._imgBufOffs[clipping];
- ptr += (_numStrips + 1) * clip_top + (clip_left / 8);
+ ptr += _numStrips * clip_top + (clip_left / 8);
akos16DecompressMask(dest, pitch, srcptr, cur_x, out_height, dir, numskip_before, numskip_after, 255, ptr, clip_left / 8);
}
diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp
index 6fd4e44b1e..288baf279c 100644
--- a/scumm/gfx.cpp
+++ b/scumm/gfx.cpp
@@ -3155,137 +3155,294 @@ static byte blend(byte *pal, byte method, int dest_color)
return blend_cache[cache][dest_color];
}
-// param3= clipping
-// param2= mirror
-// param1= never used ?
-
-void Scumm::drawBomp(BompDrawData *bd, int param1, byte *dataPtr, int param2, int param3)
-{
- byte *scale_rows = NULL;
- byte *scale_cols = NULL;
- byte *dest = bd->out + bd->y * bd->outwidth, *src;
- int src_x, src_y, dst_x, dst_y;
- uint scaled_width, scaled_height;
- int h = bd->srcheight;
- byte *mask = NULL;
- uint i;
-
- if (h == 0 || bd->srcwidth == 0)
- return;
+int32 Scumm::bompDecodeLineMode0(byte * src, byte * line_buffer, int32 size) {
+ if (size <= 0)
+ return size;
+
+ for (int32 l = 0; l < size; l++) {
+ *(line_buffer++) = *(src++);
+ }
+ return size;
+}
+
+int32 Scumm::bompDecodeLineMode1(byte * src, byte * line_buffer, int32 size) {
+ int32 t_size = READ_LE_UINT16(src) + 2;
+ if (size <= 0)
+ return t_size;
+
+ int32 len = size;
+ src += 2;
+ while (len) {
+ byte code = *src++;
+ int32 num = (code >> 1) + 1;
+ if (num > len)
+ num = len;
+ len -= num;
+ if (code & 1) {
+ byte color = *src++;
+ do
+ *line_buffer++ = color;
+ while (--num);
+ } else {
+ do
+ *line_buffer++ = *src++;
+ while (--num);
+ }
+ }
+ return t_size;
+}
+
+int32 Scumm::bompDecodeLineMode3(byte * src, byte * line_buffer, int32 size) {
+ int32 t_size = READ_LE_UINT16(src) + 2;
+ line_buffer += size;
+ if (size <= 0)
+ return t_size;
+
+ int32 len = size;
+ src += 2;
+ while (len) {
+ byte code = *src++;
+ int32 num = (code >> 1) + 1;
+ if (num > len)
+ num = len;
+ len -= num;
+ if (code & 1) {
+ byte color = *src++;
+ do
+ *--line_buffer = color;
+ while (--num);
+ } else {
+ do
+ *--line_buffer = *src++;
+ while (--num);
+ }
+ }
+ return t_size;
+}
+
+void Scumm::bompApplyMask(byte * line_buffer, byte * mask_src, byte bits, int32 size) {
+ while(1) {
+ byte tmp = *(mask_src++);
+ do {
+ if (size-- == 0)
+ return;
+ if (tmp & bits) {
+ *(line_buffer) = 255;
+ }
+ line_buffer++;
+ bits >>= 1;
+ } while (bits != 0);
+ bits = 128;
+ }
+}
- if (bd->scale_x != 255) {
- scale_rows = (byte *) calloc(bd->srcheight, 1);
- if (scale_rows == NULL) {
- warning("drawBomp: out of memory");
+void Scumm::bompApplyShadow0(byte * line_buffer, byte * dst, int32 size) {
+ while(1) {
+ if (size-- == 0)
return;
+ byte tmp = *(line_buffer++);
+ if (tmp != 255) {
+ *(dst) = tmp;
}
+ dst++;
}
+}
- if (bd->scale_y != 255) {
- scale_cols = (byte *) calloc(bd->srcwidth, 1);
- if (scale_cols == NULL) {
- warning("drawBomp: out of memory");
- if (scale_rows)
- free(scale_rows);
+void Scumm::bompApplyShadow1(byte * line_buffer, byte * dst, int32 size) {
+ while(1) {
+ if (size-- == 0)
return;
+ byte tmp = *(line_buffer++);
+ if (tmp != 255) {
+ if (tmp == 13) {
+ tmp = _shadowPalette[*(dst)];
+ }
+ *(dst) = tmp;
}
+ dst++;
}
+}
- // We take charset masking into consideration, because otherwise the
- // inventory window in The Dig may overwrite text.
+void Scumm::bompApplyShadow3(byte * line_buffer, byte * dst, int32 size) {
+ while(1) {
+ if (size-- == 0)
+ return;
+ byte tmp = *(line_buffer++);
+ if (tmp != 255) {
+ if (tmp < 8) {
+ tmp = _shadowPalette[*(dst) + (tmp << 8)];
+ }
+ *(dst) = tmp;
+ }
+ dst++;
+ }
+}
- mask = getResourceAddress(rtBuffer, 9) + _screenStartStrip;
-
- // Select which rows and columns from the original to show in the
- // scaled version of the image. This is a pretty stupid way of scaling
- // images, but it will have to do for now.
+void Scumm::bompApplyActorPalette(byte * line_buffer, int32 size) {
+ if (_bompActorPalletePtr != 0) {
+ *(_bompActorPalletePtr + 255) = 255;
+ while(1) {
+ if (size-- == 0)
+ break;
+ *(line_buffer++) = *(_bompActorPalletePtr + *(line_buffer));
+ }
+ }
+}
+
+void Scumm::bompScaleFuncX(byte * line_buffer, byte * scalling_x_ptr, byte skip, int32 size) {
+ byte * line_ptr1 = line_buffer;
+ byte * line_ptr2 = line_buffer;
- if (bd->scale_x < 255) {
- scaled_width = (bd->srcwidth * bd->scale_x) / 255;
- for (i = 0; i < scaled_width; i++)
- scale_cols[(i * 255) / bd->scale_x] = 1;
+ byte tmp = *(scalling_x_ptr++);
+
+ while (size--) {
+ if ((skip & tmp) == 0) {
+ *(line_ptr1++) = *(line_ptr2);
+ }
+ line_ptr2++;
+ skip >>= 1;
+ if (skip == 0) {
+ skip = 128;
+ tmp = *(scalling_x_ptr++);
+ }
}
+}
+
+void Scumm::drawBomp(BompDrawData * bd, int param1, byte * data_ptr, int decode_mode, int mask) {
+ byte skip_y = 128, skip_y_new;
+ byte bits, tmp;
+ int32 clip_left, clip_right, clip_top, clip_bottom, tmp_x, tmp_y;
+ byte * mask_out;
- if (bd->scale_y < 255) {
- scaled_height = (bd->srcheight * bd->scale_y) / 255;
- for (i = 0; i < scaled_height; i++)
- scale_rows[(i * 255) / bd->scale_y] = 1;
+ if (bd->x < 0) {
+ clip_left = -bd->x;
+ } else {
+ clip_left = 0;
}
- // FIXME: Be more intelligent about clearing the blend cache. It
- // should be possible to clear it only for the parts of the palette
- // that have changed since the last time.
+ if (bd->y < 0) {
+ clip_top = -bd->y;
+ } else {
+ clip_top = 0;
+ }
- clear_blend_cache();
+ clip_right = bd->srcwidth - clip_left;
+ tmp_x = bd->x + bd->srcwidth;
+ if (tmp_x > bd->outwidth) {
+ clip_right -= tmp_x - bd->outwidth;
+ }
- dest += bd->x;
- src = bd->dataptr;
+ clip_bottom = bd->srcheight;
+ tmp_y = bd->y + bd->srcheight;
+ if (tmp_y > bd->outheight) {
+ clip_bottom -= tmp_y - bd->outheight;
+ }
+
+ byte * src = bd->dataptr;
+ byte * dst = bd->out + bd->y * bd->outwidth + bd->x + clip_left;
- for (src_y = 0, dst_y = bd->y; src_y < bd->srcheight; src_y++) {
- byte code, color;
- uint len, num;
- byte *d = dest;
+ if (mask == 1) {
+ mask_out = _bompMaskPtr + (bd->y * _bompMaskPitch) + ((bd->x + clip_left) >> 3);
+ bits = 128 >> ((bd->x + clip_left) & 7);
+ }
- if ((dst_y < 0 || dst_y >= bd->outheight) || (bd->scale_y != 255 && !scale_rows[src_y])) {
- src += READ_LE_UINT16(src) + 2;
- continue;
+ if (mask == 3) {
+ if (_bompScallingYPtr != NULL) {
+ skip_y_new = *(_bompScallingYPtr++);
}
- len = bd->srcwidth;
- src_x = 0;
- dst_x = bd->x;
- src += 2;
-
- while (src_x < bd->srcwidth) {
- code = *src++;
- num = (code >> 1) + 1;
- if (num > len)
- num = len;
- len -= num;
- if (code & 1) {
- color = *src++;
- for (i = 0; i < num; i++) {
- if (bd->scale_x == 255 || scale_cols[src_x]) {
- if (dst_x >= 0 && dst_x < bd->outwidth) {
- if (!(*(mask + dst_y * gdi._numStrips + (dst_x >> 3)) & revBitMask[dst_x & 7]))
-
- *d = blend(_currentPalette, color, *d);
- }
- d++;
- dst_x++;
- }
- src_x++;
- }
- } else {
- for (i = 0; i < num; i++) {
- if (bd->scale_x == 255 || scale_cols[src_x]) {
- if (dst_x >= 0 && dst_x < bd->outwidth)
- if (!(*(mask + dst_y * gdi._numStrips + (dst_x >> 3)) & revBitMask[dst_x & 7]))
- *d = blend(_currentPalette, src[i], *d);
- d++;
- dst_x++;
- }
- src_x++;
+ if ((clip_right + clip_left) > _bompScaleRight) {
+ clip_right = _bompScaleRight - clip_left;
+ }
+
+ if (clip_bottom > _bompScaleBottom) {
+ clip_bottom = _bompScaleBottom;
+ }
+ }
+
+ if ((clip_right <= 0) || (clip_bottom <= 0))
+ return;
+
+ int32 pos_y = 0;
+
+ byte line_buffer[1024];
+
+ byte * line_ptr = (byte*)&line_buffer + clip_left;
+
+ while(1) {
+ switch(decode_mode) {
+ case 0:
+ {
+ src += bompDecodeLineMode0(src, (byte*)&line_buffer, bd->srcwidth);
+ break;
+ }
+ case 1:
+ {
+ src += bompDecodeLineMode1(src, (byte*)&line_buffer, bd->srcwidth);
+ break;
+ }
+ case 3:
+ {
+ src += bompDecodeLineMode3(src, (byte*)&line_buffer, bd->srcwidth);
+ break;
+ }
+ }
+
+ if (mask == 3) {
+ if (bd->scale_y != 255) {
+ tmp = skip_y_new & skip_y;
+ skip_y >>= 1;
+ if (skip_y == 0) {
+ skip_y = 128;
+ skip_y_new = *(_bompScallingYPtr++);
}
- src += num;
+
+ if (tmp != 0)
+ continue;
+ }
+
+ if (bd->scale_x != 255) {
+ bompScaleFuncX((byte*)&line_buffer, _bompScallingXPtr, 128, bd->srcwidth);
}
}
- dest += bd->outwidth;
- dst_y++;
-
- }
- if (scale_rows)
- free(scale_rows);
- if (scale_cols)
- free(scale_cols);
- CHECK_HEAP;
-}
+ if (clip_top-- > 0)
+ goto labelBompSkip;
+ if (mask == 1) {
+ bompApplyMask(line_ptr, mask_out, bits, clip_right);
+ }
-/* Yazoo: This function create the specialPalette used for semi-transparency in SamnMax */
+ bompApplyActorPalette(line_ptr, clip_right);
+ switch(_bompShadowMode) {
+ case 0:
+ {
+ bompApplyShadow0(line_ptr, dst, clip_right);
+ break;
+ }
+ case 1:
+ {
+ bompApplyShadow1(line_ptr, dst, clip_right);
+ break;
+ }
+ case 3:
+ {
+ bompApplyShadow3(line_ptr, dst, clip_right);
+ break;
+ }
+ }
+
+labelBompSkip:
+ mask_out += _bompMaskPitch;
+ pos_y++;
+ dst += bd->outwidth;
+ if (pos_y >= clip_bottom)
+ break;
+ }
+}
+/* Yazoo: This function create the specialPalette used for semi-transparency in SamnMax */
void Scumm::createSpecialPalette(int16 a, int16 b, int16 c, int16 d, int16 e, int16 colorMin,
int16 colorMax)
{
diff --git a/scumm/object.cpp b/scumm/object.cpp
index 11246ad16c..fefa9833e7 100644
--- a/scumm/object.cpp
+++ b/scumm/object.cpp
@@ -1248,13 +1248,154 @@ void Scumm::drawBlastObject(BlastObject *eo)
bdd.dataptr = bomp + 10;
bdd.x = eo->posX;
bdd.y = eo->posY;
- bdd.scale_x = (unsigned char)eo->scaleX;
- bdd.scale_y = (unsigned char)eo->scaleY;
+ bdd.scale_x = (byte)eo->scaleX;
+ bdd.scale_y = (byte)eo->scaleY;
+
+ byte bomp_scalling_x[64], bomp_scalling_y[64];
+
+ _bompShadowMode = 0;
+
+ if ((bdd.scale_x != 255) || (bdd.scale_y != 255)) {
+ _bompScallingXPtr = (byte*)&bomp_scalling_x;
+ _bompScallingYPtr = (byte*)&bomp_scalling_y;
+ _bompScaleRight = setupBompScale(_bompScallingXPtr, bdd.srcwidth, bdd.scale_x);
+ _bompScaleBottom = setupBompScale(_bompScallingYPtr, bdd.srcheight, bdd.scale_y);
+ drawBomp(&bdd, 0, bdd.dataptr, 1, 3);
+ } else {
+ _bompShadowMode = eo->mode;
+ drawBomp(&bdd, 0, bdd.dataptr, 1, 0);
+ }
+
+ _bompShadowMode = 0;
+ _bompScallingXPtr = NULL;
+ _bompScallingYPtr = NULL;
+ _bompScaleRight = 0;
+ _bompScaleBottom = 0;
- drawBomp(&bdd, 0, bdd.dataptr, 1, 0);
updateDirtyRect(vs->number, bdd.x, bdd.x + bdd.srcwidth, bdd.y, bdd.y + bdd.srcheight, 0);
}
+byte _bompScaleTable[] = {
+ 0, 128, 64, 192, 32, 160, 96, 224,
+ 16, 144, 80, 208, 48, 176, 112, 240,
+ 8, 136, 72, 200, 40, 168, 104, 232,
+ 24, 152, 88, 216, 56, 184, 120, 248,
+ 4, 132, 68, 196, 36, 164, 100, 228,
+ 20, 148, 84, 212, 52, 180, 116, 244,
+ 12, 140, 76, 204, 44, 172, 108, 236,
+ 28, 156, 92, 220, 60, 188, 124, 252,
+ 2, 130, 66, 194, 34, 162, 98, 226,
+ 18, 146, 82, 210, 50, 178, 114, 242,
+ 10, 138, 74, 202, 42, 170, 106, 234,
+ 26, 154, 90, 218, 58, 186, 122, 250,
+ 6, 134, 70, 198, 38, 166, 102, 230,
+ 22, 150, 86, 214, 54, 182, 118, 246,
+ 14, 142, 78, 206, 46, 174, 110, 238,
+ 30, 158, 94, 222, 62, 190, 126, 254,
+ 1, 129, 65, 193, 33, 161, 97, 225,
+ 17, 145, 81, 209, 49, 177, 113, 241,
+ 9, 137, 73, 201, 41, 169, 105, 233,
+ 25, 153, 89, 217, 57, 185, 121, 249,
+ 5, 133, 69, 197, 37, 165, 101, 229,
+ 21, 149, 85, 213, 53, 181, 117, 245,
+ 13, 141, 77, 205, 45, 173, 109, 237,
+ 29, 157, 93, 221, 61, 189, 125, 253,
+ 3, 131, 67, 195, 35, 163, 99, 227,
+ 19, 147, 83, 211, 51, 179, 115, 243,
+ 11, 139, 75, 203, 43, 171, 107, 235,
+ 27, 155, 91, 219, 59, 187, 123, 251,
+ 7, 135, 71, 199, 39, 167, 103, 231,
+ 23, 151, 87, 215, 55, 183, 119, 247,
+ 15, 143, 79, 207, 47, 175, 111, 239,
+ 31, 159, 95, 223, 63, 191, 127, 255,
+};
+
+byte _bompBitsTable[] = {
+ 8, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 4,
+ 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3,
+ 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3,
+ 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
+ 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3,
+ 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
+ 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
+ 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1,
+ 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3,
+ 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
+ 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
+ 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1,
+ 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
+ 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1,
+ 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1,
+ 4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0,
+};
+
+int32 Scumm::setupBompScale(byte * scalling, int32 size, byte scale) {
+ uint32 tmp;
+ int32 count = (size + 7) >> 3;
+ byte * tmp_ptr = _bompScaleTable + (256 - (size >> 1));
+ byte * tmp_scalling = scalling;
+ byte a = 0;
+
+ while((count--) != 0) {
+ tmp = *(tmp_ptr + 3);
+ a <<= 1;
+ if (scale < tmp) {
+ a |= 1;
+ }
+ tmp = *(tmp_ptr + 2);
+ a <<= 1;
+ if (scale < tmp) {
+ a |= 1;
+ }
+ tmp = *(tmp_ptr + 1);
+ a <<= 1;
+ if (scale < tmp) {
+ a |= 1;
+ }
+ tmp = *(tmp_ptr + 0);
+ a <<= 1;
+ if (scale < tmp) {
+ a |= 1;
+ }
+ tmp_ptr += 4;
+
+ tmp = *(tmp_ptr + 3);
+ a <<= 1;
+ if (scale < tmp) {
+ a |= 1;
+ }
+ tmp = *(tmp_ptr + 2);
+ a <<= 1;
+ if (scale < tmp) {
+ a |= 1;
+ }
+ tmp = *(tmp_ptr + 1);
+ a <<= 1;
+ if (scale < tmp) {
+ a |= 1;
+ }
+ tmp = *(tmp_ptr + 0);
+ a <<= 1;
+ if (scale < tmp) {
+ a |= 1;
+ }
+ tmp_ptr += 4;
+
+ *(tmp_scalling++) = a;
+ }
+ if ((size & 7) != 0) {
+ *(tmp_scalling - 1) |= revBitMask[size & 7];
+ }
+
+ count = (size + 7) >> 3;
+ byte ret_value = 0;
+ while((count--) != 0) {
+ ret_value += *(*(scalling++) + _bompBitsTable);
+ }
+
+ return ret_value;
+}
+
void Scumm::removeBlastObjects()
{
BlastObject *eo;
@@ -1298,8 +1439,8 @@ void Scumm::removeBlastObject(BlastObject *eo)
if (left_strip < 0)
left_strip = 0;
- if (right_strip >= 240)
- right_strip = 240;
+ if (right_strip >= 409)
+ right_strip = 409;
for (i = left_strip; i <= right_strip; i++)
gdi.resetBackground(top, bottom, i);
diff --git a/scumm/scumm.h b/scumm/scumm.h
index 6b4b3c3d5d..643633afed 100644
--- a/scumm/scumm.h
+++ b/scumm/scumm.h
@@ -778,7 +778,17 @@ public:
void drawRoomObjects(int arg);
void drawRoomObject(int i, int arg);
void drawBox(int x, int y, int x2, int y2, int color);
- void drawBomp(BompDrawData *bd, int param1, byte *dataPtr, int param2, int param3);
+ void drawBomp(BompDrawData * bd, int param1, byte *data_ptr, int decode_mode, int mask);
+ int32 setupBompScale(byte * scalling, int32 size, byte scale);
+ void bompScaleFuncX(byte * line_buffer, byte * scalling_x_ptr, byte skip, int32 size);
+ int32 bompDecodeLineMode0(byte * src, byte * line_buffer, int32 size);
+ int32 bompDecodeLineMode1(byte * src, byte * line_buffer, int32 size);
+ int32 bompDecodeLineMode3(byte * src, byte * line_buffer, int32 size);
+ void bompApplyMask(byte * line_buffer, byte * mask_out, byte bits, int32 size);
+ void bompApplyShadow0(byte * line_buffer, byte * dst, int32 size);
+ void bompApplyShadow1(byte * line_buffer, byte * dst, int32 size);
+ void bompApplyShadow3(byte * line_buffer, byte * dst, int32 size);
+ void bompApplyActorPalette(byte * line_buffer, int32 size);
void restoreBG(int left, int top, int right, int bottom);
void redrawBGStrip(int start, int num);
@@ -865,13 +875,20 @@ public:
void removeBlastObjects();
void removeBlastObject(BlastObject *eo);
+ uint16 _bompShadowMode;
+ int32 _bompScaleRight, _bompScaleBottom;
+ byte * _bompScallingXPtr, * _bompScallingYPtr;
+ byte * _bompMaskPtr;
+ int32 _bompMaskPitch;
+ byte * _bompActorPalletePtr;
+
int _drawObjectQueNr;
byte _drawObjectQue[200];
byte _palManipStart, _palManipEnd;
uint16 _palManipCounter;
byte *_palManipPalette;
byte *_palManipIntermediatePal;
- uint32 gfxUsageBits[240];
+ uint32 gfxUsageBits[409];
byte *_shadowPalette;
int _shadowPaletteSize;
byte _currentPalette[0x300];