From 6b61700a7bf9ac66acc01b69f19703196b497320 Mon Sep 17 00:00:00 2001 From: Travis Howell Date: Mon, 26 Oct 2009 02:45:26 +0000 Subject: Add patch from Tobias, for masking support in PCE version of Loom, with minor changes. svn-id: r45387 --- engines/scumm/costume.cpp | 108 ++++++++++++++++++--------------------------- engines/scumm/costume.h | 3 -- engines/scumm/gfx.cpp | 82 +++++++++++++++++++++++++++++----- engines/scumm/gfx.h | 4 +- engines/scumm/resource.cpp | 2 + 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); } -- cgit v1.2.3