aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
authorTravis Howell2009-10-26 02:45:26 +0000
committerTravis Howell2009-10-26 02:45:26 +0000
commit6b61700a7bf9ac66acc01b69f19703196b497320 (patch)
treee07b7b0e810a6c0db6da66407b0f0ab29f99182a /engines/scumm
parentcac32b61ceb271631efe297b39e1d2b93af726e3 (diff)
downloadscummvm-rg350-6b61700a7bf9ac66acc01b69f19703196b497320.tar.gz
scummvm-rg350-6b61700a7bf9ac66acc01b69f19703196b497320.tar.bz2
scummvm-rg350-6b61700a7bf9ac66acc01b69f19703196b497320.zip
Add patch from Tobias, for masking support in PCE version of Loom, with minor changes.
svn-id: r45387
Diffstat (limited to 'engines/scumm')
-rw-r--r--engines/scumm/costume.cpp108
-rw-r--r--engines/scumm/costume.h3
-rw-r--r--engines/scumm/gfx.cpp82
-rw-r--r--engines/scumm/gfx.h4
-rw-r--r--engines/scumm/resource.cpp2
5 files changed, 117 insertions, 82 deletions
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index d50ae54480..3d649d3159 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -595,10 +595,11 @@ void ClassicCostumeRenderer::procPCEngine(Codec1 &v1) {
const byte *mask, *src;
byte *dst;
byte maskbit;
- uint width, height;
- byte scaleIndexY;
+ int xPos, yPos;
+ uint color, width, height; //, pcolor;
+ bool masked;
int vertShift;
-
+ int xStep;
byte block[16][16];
src = _srcptr;
@@ -608,19 +609,17 @@ void ClassicCostumeRenderer::procPCEngine(Codec1 &v1) {
if (_numBlocks == 0)
return;
- scaleIndexY = _scaleIndexY;
- maskbit = revBitMask(v1.x & 7);
- mask = v1.mask_ptr + v1.x / 8;
+ xStep = _mirror ? +1 : -1;
for (uint x = 0; x < width; ++x) {
- dst = v1.destptr + 16 * x * _out.bytesPerPixel;
+ yPos = 0;
for (uint y = 0; y < height; ++y) {
vertShift = *src++;
if (vertShift == 0xFF) {
- dst += 16 * _out.pitch;
+ yPos += 16;
continue;
} else {
- dst += vertShift * _out.pitch;
+ yPos += vertShift;
}
memset(block, 0, sizeof(block));
@@ -646,18 +645,24 @@ void ClassicCostumeRenderer::procPCEngine(Codec1 &v1) {
}
for (int row = 0; row < 16; ++row) {
+ xPos = xStep * x * 16;
for (int col = 0; col < 16; ++col) {
- int color = block[row][col];
- if (color != 0) {
- if (dst < v1.destptr + _out.w * _out.h * _out.bytesPerPixel) {
- if (_mirror)
- dst[col] = color;
- else
- dst[-col] = color;
- }
+ dst = v1.destptr + yPos * _out.pitch + xPos;
+ mask = v1.mask_ptr + yPos * _numStrips + (v1.x + xPos) / 8;
+ maskbit = revBitMask((v1.x + xPos) % 8);
+
+ color = block[row][col];
+ masked = (v1.y + yPos < 0 || v1.y + yPos >= _out.h) ||
+ (v1.x + xPos < 0 || v1.x + xPos >= _out.w) ||
+ (v1.mask_ptr && (mask[0] & maskbit));
+
+ if (color && !masked) {
+ *dst = color;
}
+
+ xPos += xStep;
}
- dst += _out.pitch;
+ yPos++;
}
}
}
@@ -825,54 +830,10 @@ byte NESCostumeRenderer::drawLimb(const Actor *a, int limb) {
#define PCE_SIGNED(a) (((a) & 0x80) ? -((a) & 0x7F) : (a))
-byte PCEngineCostumeRenderer::drawLimb(const Actor *a, int limb) {
- int i;
- int code;
- const byte *frameptr, *offset;
- const CostumeData &cost = a->_cost;
-
- // If the specified limb is stopped or not existing, do nothing.
- if (cost.curpos[limb] == 0xFFFF || cost.stopped & (1 << limb))
- return 0;
-
- // Determine the position the limb is at
- i = cost.curpos[limb] & 0x7FFF;
-
- // Get the frame pointer for that limb
- offset = _loaded._frameOffsets + limb * 2;
- frameptr = READ_LE_UINT16(offset) + offset + 2;
-
- // Determine the offset to the costume data for the limb at position i
- code = _loaded._animCmds[i] & 0x7F;
-
- // Code 0x7B indicates a limb for which there is nothing to draw
- if (code != 0x7B) {
- offset = frameptr + code * 2;
- _srcptr = READ_LE_UINT16(offset) + offset + 2;
-
- if (code < 0x79) {
- int xmoveCur, ymoveCur;
-
- _numBlocks = _srcptr[0];
- _width = _srcptr[1] * 16;
- _height = _srcptr[2] * 16;
- xmoveCur = _xmove + PCE_SIGNED(_srcptr[3]);
- ymoveCur = _ymove + PCE_SIGNED(_srcptr[4]);
- _xmove += PCE_SIGNED(_srcptr[5]);
- _ymove += PCE_SIGNED(_srcptr[6]);
- _srcptr += 7;
-
- return mainRoutine(xmoveCur, ymoveCur);
- }
- }
-
- return 0;
-}
-
byte ClassicCostumeRenderer::drawLimb(const Actor *a, int limb) {
int i;
int code;
- const byte *frameptr;
+ const byte *baseptr, *frameptr;
const CostumeData &cost = a->_cost;
// If the specified limb is stopped or not existing, do nothing.
@@ -882,21 +843,36 @@ byte ClassicCostumeRenderer::drawLimb(const Actor *a, int limb) {
// Determine the position the limb is at
i = cost.curpos[limb] & 0x7FFF;
+ baseptr = _loaded._baseptr;
+
// Get the frame pointer for that limb
- frameptr = _loaded._baseptr + READ_LE_UINT16(_loaded._frameOffsets + limb * 2);
+ if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine)
+ baseptr = _loaded._frameOffsets + limb * 2 + 2;
+ frameptr = baseptr + READ_LE_UINT16(_loaded._frameOffsets + limb * 2);
// Determine the offset to the costume data for the limb at position i
code = _loaded._animCmds[i] & 0x7F;
// Code 0x7B indicates a limb for which there is nothing to draw
if (code != 0x7B) {
- _srcptr = _loaded._baseptr + READ_LE_UINT16(frameptr + code * 2);
+ if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine)
+ baseptr = frameptr + code * 2 + 2;
+ _srcptr = baseptr + READ_LE_UINT16(frameptr + code * 2);
if (!(_vm->_game.features & GF_OLD256) || code < 0x79) {
const CostumeInfo *costumeInfo;
int xmoveCur, ymoveCur;
- if (_loaded._format == 0x57) {
+ if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine) {
+ _numBlocks = _srcptr[0];
+ _width = _srcptr[1] * 16;
+ _height = _srcptr[2] * 16;
+ xmoveCur = _xmove + PCE_SIGNED(_srcptr[3]);
+ ymoveCur = _ymove + PCE_SIGNED(_srcptr[4]);
+ _xmove += PCE_SIGNED(_srcptr[5]);
+ _ymove += PCE_SIGNED(_srcptr[6]);
+ _srcptr += 7;
+ } else if (_loaded._format == 0x57) {
_width = _srcptr[0] * 8;
_height = _srcptr[1];
xmoveCur = _xmove + (int8)_srcptr[2] * 8;
diff --git a/engines/scumm/costume.h b/engines/scumm/costume.h
index 5191a9388e..0deb686aa2 100644
--- a/engines/scumm/costume.h
+++ b/engines/scumm/costume.h
@@ -135,9 +135,6 @@ public:
PCEngineCostumeRenderer(ScummEngine *vm) : ClassicCostumeRenderer(vm) {}
void setPalette(uint16 *palette);
-
-protected:
- byte drawLimb(const Actor *a, int limb);
};
class C64CostumeRenderer : public BaseCostumeRenderer {
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index 14a781a0f6..1f73d7581f 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -225,6 +225,7 @@ GdiPCEngine::GdiPCEngine(ScummEngine *vm) : Gdi(vm) {
GdiPCEngine::~GdiPCEngine() {
free(_PCE.tiles);
+ free(_PCE.masks);
}
GdiV1::GdiV1(ScummEngine *vm) : Gdi(vm) {
@@ -1570,7 +1571,9 @@ int Gdi::getZPlanes(const byte *ptr, const byte *zplane_list[9], bool bmapImage)
numzbuf = _numZBuffer;
assert(numzbuf <= 9);
- if (_vm->_game.features & GF_SMALL_HEADER) {
+ if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine) {
+ zplane_list[1] = 0;
+ } else if (_vm->_game.features & GF_SMALL_HEADER) {
if (_vm->_game.features & GF_16COLOR)
zplane_list[1] = ptr + READ_LE_UINT16(ptr);
else {
@@ -1646,11 +1649,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
assert(smap_ptr);
}
- if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine) {
- numzbuf = 0;
- } else {
- numzbuf = getZPlanes(ptr, zplane_list, false);
- }
+ numzbuf = getZPlanes(ptr, zplane_list, false);
const byte *tmsk_ptr = NULL;
if (_vm->_game.heversion >= 72) {
@@ -2611,6 +2610,10 @@ void GdiPCEngine::decodeStrip(const byte *ptr, uint16 *tiles, byte *colors, uint
int loopCnt;
uint16 lastTileData;
+ /*
+ * read tiles indices
+ */
+
int rowIndex = 0;
if (isObject) {
loopCnt = numRows;
@@ -2687,7 +2690,7 @@ void GdiPCEngine::decodeStrip(const byte *ptr, uint16 *tiles, byte *colors, uint
}
/*
- * read z-order or mask???
+ * read mask indices
*/
if (dataWidth == 0 || numRows < 18) {
@@ -2728,6 +2731,7 @@ void GdiPCEngine::decodePCEngineGfx(const byte *room) {
uint16* stripOffsets;
decodePCEngineTileData(_vm->findResourceData(MKID_BE('TILE'), room));
+ decodePCEngineMaskData(_vm->findResourceData(MKID_BE('ZP00'), room));
const byte* smap_ptr = _vm->findResourceData(MKID_BE('IM00'), room);
*smap_ptr++; // roomID
@@ -2795,9 +2799,11 @@ void GdiPCEngine::decodePCEngineTileData(const byte *ptr) {
free(_PCE.tiles);
_PCE.tiles = (byte*)calloc(_PCE.numTiles * 8 * 8, sizeof(byte));
+
for (int i = 0; i < _PCE.numTiles; ++i) {
tile = &_PCE.tiles[i * 64];
tilePtr = ptr + tileOffsets[i];
+
int index = 0;
while (index < 16) {
byte cmd = *tilePtr++;
@@ -2821,21 +2827,61 @@ void GdiPCEngine::decodePCEngineTileData(const byte *ptr) {
free(tileOffsets);
}
+void GdiPCEngine::decodePCEngineMaskData(const byte *ptr) {
+ const byte *maskPtr;
+ byte* mask;
+ uint16* maskOffsets;
+
+ if (!ptr) {
+ _PCE.numMasks = 0;
+ return;
+ }
+
+ readOffsetTable(ptr, &maskOffsets, &_PCE.numMasks);
+
+ free(_PCE.masks);
+ _PCE.masks = (byte*)malloc(_PCE.numMasks * 8 * sizeof(byte));
+
+ for (int i = 0; i < _PCE.numMasks; ++i) {
+ mask = &_PCE.masks[i * 8];
+ maskPtr = ptr + maskOffsets[i];
+
+ int index = 0;
+ while (index < 8) {
+ byte cmd = *maskPtr++;
+ int cnt = cmd & 0x1F;
+ if (cmd & 0x80) {
+ byte value;
+ if (cmd & 0x60)
+ value = (cmd & 0x40) ? 0x00 : 0xFF;
+ else
+ value = *maskPtr++;
+ for (int j = 0; j < cnt; ++j)
+ mask[index++] = ~value;
+ } else {
+ for (int j = 0; j < cnt; ++j)
+ mask[index++] = ~*maskPtr++;
+ }
+ }
+ }
+
+ free(maskOffsets);
+}
+
void GdiPCEngine::drawStripPCEngine(byte *dst, byte *mask, int dstPitch, int stripnr, int top, int height) {
uint16 tileIdx;
byte *tile;
int paletteIdx, paletteOffset, paletteEntry;
height /= 8;
- for (int i = 0; i < height; i++) {
- tileIdx = (_objectMode ? _PCE.nametableObj : _PCE.nametable)[stripnr * height + i];
+ for (int y = 0; y < height; y++) {
+ tileIdx = (_objectMode ? _PCE.nametableObj : _PCE.nametable)[stripnr * height + y];
tile = &_PCE.tiles[tileIdx * 64];
- paletteIdx = (_objectMode ? _PCE.colortableObj : _PCE.colortable)[stripnr * height + i];
+ paletteIdx = (_objectMode ? _PCE.colortableObj : _PCE.colortable)[stripnr * height + y];
paletteOffset = paletteIdx * 16;
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
paletteEntry = tile[row * 8 + col];
- // TODO: handle transparency (paletteEntry == 0)
dst[col] = paletteOffset + paletteEntry;
}
dst += dstPitch;
@@ -2844,7 +2890,19 @@ void GdiPCEngine::drawStripPCEngine(byte *dst, byte *mask, int dstPitch, int str
}
void GdiPCEngine::drawStripPCEngineMask(byte *dst, int stripnr, int top, int height) const {
- // TODO
+ uint16 maskIdx;
+ height /= 8;
+
+ for (int y = 0; y < height; y++) {
+ maskIdx = (_objectMode ? _PCE.masktableObj : _PCE.masktable)[stripnr * height + y];
+ for (int row = 0; row < 8; row++) {
+ if (_PCE.numMasks > 0)
+ *dst = _PCE.masks[maskIdx * 8 + row];
+ else
+ *dst = 0;
+ dst += _numStrips;
+ }
+ }
}
void GdiV1::drawStripC64Background(byte *dst, int dstPitch, int stripnr, int height) {
diff --git a/engines/scumm/gfx.h b/engines/scumm/gfx.h
index 5a4f81da99..3548a93317 100644
--- a/engines/scumm/gfx.h
+++ b/engines/scumm/gfx.h
@@ -308,15 +308,17 @@ protected:
byte colortable[4096], colortableObj[512];
uint16 masktable[4096], masktableObj[512];
int objX;
- bool hasmask;
int numTiles;
+ int numMasks;
byte* tiles;
+ byte* masks;
} _PCE;
protected:
void decodePCEngineGfx(const byte *room);
void decodeStrip(const byte *ptr, uint16 *tiles, byte *colors, uint16 *masks, int dataWidth, int numRows, bool isObject);
void decodePCEngineTileData(const byte *ptr);
+ void decodePCEngineMaskData(const byte *ptr);
void decodePCEngineObject(const byte *ptr, int xpos, int ypos, int width, int height);
void drawStripPCEngine(byte *dst, byte *mask, int dstPitch, int stripnr, int top, int height);
diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp
index ad0c87c6f2..f93df88c6a 100644
--- a/engines/scumm/resource.cpp
+++ b/engines/scumm/resource.cpp
@@ -1474,6 +1474,8 @@ uint16 newTag2Old(uint32 newTag) {
return (0x5053); // SP
case (MKID_BE('TILE')):
return (0x4C54); // TL
+ case (MKID_BE('ZP00')):
+ return (0x505A); // ZP
default:
return (0);
}