From 746258f882b74cea1c5d5a34ef6c67e0669cdf09 Mon Sep 17 00:00:00 2001 From: Travis Howell Date: Wed, 21 Oct 2009 12:59:10 +0000 Subject: Add patch from Tobias, for graphic support (backgrounds/objects) in PCE version of Loom, with minor changes. svn-id: r45304 --- engines/scumm/costume.cpp | 59 ++++++++ engines/scumm/costume.h | 31 ++++ engines/scumm/detection.cpp | 2 +- engines/scumm/detection_tables.h | 2 +- engines/scumm/gfx.cpp | 312 +++++++++++++++++++++++++++++++++++++-- engines/scumm/gfx.h | 41 +++++ engines/scumm/palette.cpp | 67 ++++++++- engines/scumm/resource.cpp | 2 + engines/scumm/scumm.cpp | 7 +- engines/scumm/scumm.h | 1 + tools/credits.pl | 1 + 11 files changed, 506 insertions(+), 19 deletions(-) diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp index 6923c27b38..f270cb94f5 100644 --- a/engines/scumm/costume.cpp +++ b/engines/scumm/costume.cpp @@ -737,6 +737,10 @@ byte NESCostumeRenderer::drawLimb(const Actor *a, int limb) { return 0; } +byte PCEngineCostumeRenderer::drawLimb(const Actor *a, int limb) { + return 0; +} + byte ClassicCostumeRenderer::drawLimb(const Actor *a, int limb) { int i; int code; @@ -804,6 +808,19 @@ void NESCostumeRenderer::setCostume(int costume, int shadow) { _loaded.loadCostume(costume); } +void PCEngineCostumeRenderer::setPalette(uint16 *palette) { + // TODO +} + +void PCEngineCostumeRenderer::setFacing(const Actor *a) { + // TODO + //_mirror = newDirToOldDir(a->getFacing()) != 0 || _loaded._mirror; +} + +void PCEngineCostumeRenderer::setCostume(int costume, int shadow) { + _loaded.loadCostume(costume); +} + void ClassicCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) { const byte *r; uint mask, j; @@ -1024,6 +1041,48 @@ byte NESCostumeLoader::increaseAnim(Actor *a, int slot) { return (a->_cost.curpos[slot] != oldframe); } +void PCEngineCostumeLoader::loadCostume(int id) { + _id = id; + _baseptr = _vm->getResourceAddress(rtCostume, id); + _dataOffsets = _baseptr + 2; + _numAnim = 0x17; +} + +void PCEngineCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) { + int anim; + + loadCostume(a->_costume); + + anim = 4 * frame + newDirToOldDir(a->getFacing()); + + if (anim > _numAnim) { + return; + } + + a->_cost.curpos[0] = 0; + a->_cost.start[0] = 0; + a->_cost.end[0] = _dataOffsets[2 * anim + 1]; + a->_cost.frame[0] = frame; +} + +byte PCEngineCostumeLoader::increaseAnims(Actor *a) { + int i; + byte r = 0; + + for (i = 0; i != 16; i++) { + if (a->_cost.curpos[i] != 0xFFFF) + r += increaseAnim(a, i); + } + return r; +} + +byte PCEngineCostumeLoader::increaseAnim(Actor *a, int slot) { + int oldframe = a->_cost.curpos[slot]++; + if (a->_cost.curpos[slot] >= a->_cost.end[slot]) + a->_cost.curpos[slot] = a->_cost.start[slot]; + return (a->_cost.curpos[slot] != oldframe); +} + static const byte actorColorsMMC64[25] = { 0, 7, 2, 6, 9, 1, 3, 7, 7, 1, 1, 9, 1, 4, 5, 5, 4, 1, 0, 5, 4, 2, 2, 7, 7 }; diff --git a/engines/scumm/costume.h b/engines/scumm/costume.h index 929eb8c451..b845ee2158 100644 --- a/engines/scumm/costume.h +++ b/engines/scumm/costume.h @@ -71,6 +71,22 @@ protected: byte increaseAnim(Actor *a, int slot); }; +class PCEngineCostumeLoader : public BaseCostumeLoader { +public: + int _id; + const byte *_baseptr; + const byte *_dataOffsets; + byte _numAnim; + + PCEngineCostumeLoader(ScummEngine *vm) : BaseCostumeLoader(vm) {} + void loadCostume(int id); + void costumeDecodeData(Actor *a, int frame, uint usemask); + byte increaseAnims(Actor *a); + +protected: + byte increaseAnim(Actor *a, int slot); +}; + class C64CostumeLoader : public ClassicCostumeLoader { public: C64CostumeLoader(ScummEngine *vm) : ClassicCostumeLoader(vm) {} @@ -128,6 +144,21 @@ protected: byte drawLimb(const Actor *a, int limb); }; +class PCEngineCostumeRenderer : public BaseCostumeRenderer { +protected: + PCEngineCostumeLoader _loaded; + +public: + PCEngineCostumeRenderer(ScummEngine *vm) : BaseCostumeRenderer(vm), _loaded(vm) {} + + void setPalette(uint16 *palette); + void setFacing(const Actor *a); + void setCostume(int costume, int shadow); + +protected: + byte drawLimb(const Actor *a, int limb); +}; + class C64CostumeRenderer : public BaseCostumeRenderer { protected: C64CostumeLoader _loaded; diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 8beb2ef720..cbf6cd2cff 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -923,7 +923,7 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co *engine = new ScummEngine_v2(syst, res); break; case 3: - if ((res.game.features & GF_OLD256) || res.game.platform == Common::kPlatformPCEngine) + if (res.game.features & GF_OLD256) *engine = new ScummEngine_v3(syst, res); else *engine = new ScummEngine_v3old(syst, res); diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index da8e54fba5..914bf2e5a8 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -216,7 +216,7 @@ static const GameSettings gameVariantsTable[] = { {"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, {"loom", "No Adlib", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, - {"loom", "PC-Engine", 0, GID_LOOM, 3, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformPCEngine, GUIO_NOSPEECH | GUIO_NOMIDI}, + {"loom", "PC-Engine", 0, GID_LOOM, 3, 0, MDT_NONE, GF_AUDIOTRACKS | GF_OLD256, Common::kPlatformPCEngine, GUIO_NOSPEECH | GUIO_NOMIDI}, {"loom", "FM-TOWNS", 0, GID_LOOM, 3, 0, MDT_TOWNS, GF_AUDIOTRACKS | GF_OLD256, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI}, {"loom", "VGA", "vga", GID_LOOM, 4, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index d1bb1d53b2..5482a85014 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -219,6 +219,14 @@ GdiNES::GdiNES(ScummEngine *vm) : Gdi(vm) { memset(&_NES, 0, sizeof(_NES)); } +GdiPCEngine::GdiPCEngine(ScummEngine *vm) : Gdi(vm) { + memset(&_PCE, 0, sizeof(_PCE)); +} + +GdiPCEngine::~GdiPCEngine() { + free(_PCE.tiles); +} + GdiV1::GdiV1(ScummEngine *vm) : Gdi(vm) { memset(&_C64, 0, sizeof(_C64)); } @@ -258,6 +266,10 @@ void GdiNES::roomChanged(byte *roomptr) { decodeNESGfx(roomptr); } +void GdiPCEngine::roomChanged(byte *roomptr) { + decodePCEngineGfx(roomptr); +} + void GdiV1::roomChanged(byte *roomptr) { for (int i = 0; i < 4; i++){ _C64.colors[i] = roomptr[6 + i]; @@ -1411,6 +1423,13 @@ void GdiNES::prepareDrawBitmap(const byte *ptr, VirtScreen *vs, } } +void GdiPCEngine::prepareDrawBitmap(const byte *ptr, VirtScreen *vs, + const int x, const int y, const int width, const int height, + int stripnr, int numstrip) { + if (_objectMode) { + decodePCEngineObject(ptr, x - stripnr, y, width, height); + } +} void GdiV2::prepareDrawBitmap(const byte *ptr, VirtScreen *vs, const int x, const int y, const int width, const int height, @@ -1617,11 +1636,6 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const // Check whether lights are turned on or not const bool lightsOn = _vm->isLightOn(); - if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine) { - // FIXME: Image format unknown - return; - } - if (_vm->_game.features & GF_SMALL_HEADER) { smap_ptr = ptr; } else if (_vm->_game.version == 8) { @@ -1632,7 +1646,11 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const assert(smap_ptr); } - numzbuf = getZPlanes(ptr, zplane_list, false); + if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine) { + numzbuf = 0; + } else { + numzbuf = getZPlanes(ptr, zplane_list, false); + } const byte *tmsk_ptr = NULL; if (_vm->_game.heversion >= 72) { @@ -1729,15 +1747,7 @@ bool Gdi::drawStrip(byte *dstPtr, VirtScreen *vs, int x, int y, const int width, // but if e.g. a savegame gets corrupted, we can easily get into // trouble here. See also bug #795214. int offset = -1, smapLen; - if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine) { - // Length of offsets segment only - smapLen = READ_LE_UINT16(smap_ptr); - if (stripnr * 2 + 2 < smapLen) { - offset = READ_LE_UINT16(smap_ptr + stripnr * 2 + 2); - offset += stripnr * 2 + 3; - } - debug(0, "stripnr %d len %d offset %d", stripnr, smapLen, offset); - } else if (_vm->_game.features & GF_16COLOR) { + if (_vm->_game.features & GF_16COLOR) { smapLen = READ_LE_UINT16(smap_ptr); if (stripnr * 2 + 2 < smapLen) { offset = READ_LE_UINT16(smap_ptr + stripnr * 2 + 2); @@ -1766,6 +1776,13 @@ bool GdiNES::drawStrip(byte *dstPtr, VirtScreen *vs, int x, int y, const int wid return false; } +bool GdiPCEngine::drawStrip(byte *dstPtr, VirtScreen *vs, int x, int y, const int width, const int height, + int stripnr, const byte *smap_ptr) { + byte *mask_ptr = getMaskBuffer(x, y, 1); + drawStripPCEngine(dstPtr, mask_ptr, vs->pitch, stripnr, y, height); + return false; +} + bool GdiV1::drawStrip(byte *dstPtr, VirtScreen *vs, int x, int y, const int width, const int height, int stripnr, const byte *smap_ptr) { if (_objectMode) @@ -1865,6 +1882,13 @@ void GdiNES::decodeMask(int x, int y, const int width, const int height, drawStripNESMask(mask_ptr, stripnr, y, height); } +void GdiPCEngine::decodeMask(int x, int y, const int width, const int height, + int stripnr, int numzbuf, const byte *zplane_list[9], + bool transpStrip, byte flag, const byte *tmsk_ptr) { + byte *mask_ptr = getMaskBuffer(x, y, 1); + drawStripPCEngineMask(mask_ptr, stripnr, y, height); +} + void GdiV1::decodeMask(int x, int y, const int width, const int height, int stripnr, int numzbuf, const byte *zplane_list[9], bool transpStrip, byte flag, const byte *tmsk_ptr) { @@ -2567,6 +2591,264 @@ void GdiNES::drawStripNESMask(byte *dst, int stripnr, int top, int height) const } } +void readOffsetTable(const byte *ptr, uint16 **table, int *count) { + int pos = 0; + *count = READ_LE_UINT16(ptr) / 2 + 1; + *table = (uint16*)malloc(*count * sizeof(uint16)); + for (int i = 0; i < *count; i++) { + (*table)[i] = READ_LE_UINT16(ptr + pos) + pos + 2; + pos += 2; + } +} + +void decodeTileColor(byte cmd, byte *colors, int *rowIndex, int numRows) { + colors[(*rowIndex)++] = ((cmd) >> 4) & 0xF; + if (*rowIndex < numRows) + colors[(*rowIndex)++] = (cmd) & 0xF; +} + +void GdiPCEngine::decodeStrip(const byte *ptr, uint16 *tiles, byte *colors, uint16 *masks, int dataWidth, int numRows, bool isObject) { + int loopCnt; + uint16 lastTileData; + + int rowIndex = 0; + if (isObject) { + loopCnt = numRows; + } else { + tiles[rowIndex++] = 0; + tiles[numRows - 1] = 0; + loopCnt = numRows - 1; + } + + while (true) { + uint16 cmd = READ_LE_UINT16(ptr); + ptr += 2; + if (cmd & 0x8000) { + tiles[rowIndex - 1] = cmd & 0x0FFF; + } else if (cmd & 0x4000) { + tiles[numRows - 1] = cmd & 0x0FFF; + } else { + tiles[rowIndex++] = cmd; + lastTileData = cmd; + break; + } + } + + while (rowIndex < loopCnt) { + byte cmd = *ptr++; + int cnt = cmd & 0x1F; + + if (cmd & 0x80) { + for (int i = 0; i < cnt; ++i) { + tiles[rowIndex++] = lastTileData; + } + } else if (cmd & 0x40) { + for (int i = 0; i < cnt; ++i) { + ++lastTileData; + tiles[rowIndex++] = lastTileData; + } + } else { + for (int i = 0; i < cnt; ++i) { + lastTileData = READ_LE_UINT16(ptr); + ptr += 2; + tiles[rowIndex++] = lastTileData; + } + } + } + + /* + * read palette data + */ + + rowIndex = 0; + byte cmd = *ptr++; + if (cmd == 0xFE) { + while (rowIndex < numRows) { + decodeTileColor(*ptr++, colors, &rowIndex, numRows); + } + } else { + byte lastCmd = cmd; + decodeTileColor(cmd, colors, &rowIndex, numRows); + while (rowIndex < numRows) { + cmd = *ptr++; + int cnt = cmd & 0x1F; + if (cmd & 0x80) { + for (int j = 0; j < cnt; ++j) { + decodeTileColor(lastCmd, colors, &rowIndex, numRows); + } + } else { + for (int j = 0; j < cnt; ++j) { + cmd = *ptr++; + decodeTileColor(cmd, colors, &rowIndex, numRows); + } + lastCmd = cmd; + } + } + } + + /* + * read z-order or mask??? + */ + + if (dataWidth == 0 || numRows < 18) { + return; + } + + rowIndex = 0; + while (rowIndex < numRows) { + cmd = *ptr++; + int cnt = cmd & 0x1F; + if (cmd & 0x80) { + uint16 value; + if (cmd & 0x60) { + value = (cmd & 0x40) ? 0 : 0xFF; + } else if (dataWidth == 1) { + value = *ptr++; + } else { + value = READ_LE_UINT16(ptr); + ptr += 2; + } + for (int i = 0; i < cnt; ++i) { + masks[rowIndex++] = value; + } + } else { + for (int i = 0; i < cnt; ++i) { + if (dataWidth == 1) { + masks[rowIndex++] = *ptr++; + } else { + masks[rowIndex++] = READ_LE_UINT16(ptr); + ptr += 2; + } + } + } + } +} + +void GdiPCEngine::decodePCEngineGfx(const byte *room) { + uint16* stripOffsets; + + decodePCEngineTileData(_vm->findResourceData(MKID_BE('TILE'), room)); + + const byte* smap_ptr = _vm->findResourceData(MKID_BE('IM00'), room); + *smap_ptr++; // roomID + int numStrips = *smap_ptr++; + int numRows = *smap_ptr++; + int dataWidth = *smap_ptr++; + *smap_ptr++; // unknown + + memset(_PCE.nametable, 0, sizeof(_PCE.nametable)); + memset(_PCE.colortable, 0, sizeof(_PCE.colortable)); + readOffsetTable(smap_ptr, &stripOffsets, &numStrips); + for (int i = 0; i < numStrips; ++i) { + const byte *tilePtr = smap_ptr + stripOffsets[i]; + decodeStrip(tilePtr, + &_PCE.nametable[i * numRows], + &_PCE.colortable[i * numRows], + &_PCE.masktable[i * numRows], + dataWidth, + numRows, + false); + } + free(stripOffsets); +} + +void GdiPCEngine::decodePCEngineObject(const byte *ptr, int xpos, int ypos, int width, int height) { + uint16 *stripOffsets; + int numStrips; + int numRows = height / 8; + + memset(_PCE.nametableObj, 0, sizeof(_PCE.nametableObj)); + memset(_PCE.colortableObj, 0, sizeof(_PCE.colortableObj)); + readOffsetTable(ptr, &stripOffsets, &numStrips); + for (int i = 0; i < numStrips; ++i) { + const byte *tilePtr = ptr + stripOffsets[i]; + decodeStrip(tilePtr, + &_PCE.nametableObj[i * numRows], + &_PCE.colortableObj[i * numRows], + &_PCE.masktableObj[i * numRows], + 0, // is this true? + numRows, + true); + } + free(stripOffsets); +} + +void setTileData(byte *tile, int index, byte byte0, byte byte1) { + int row = index % 8; + int plane = (index / 8) * 2; + int plane02Bit, plane13Bit; + for (int col = 0; col < 8; ++col) { + plane02Bit = (byte0 >> (7-col)) & 0x1; // plane=0: bit0, plane=2: bit2 + plane13Bit = (byte1 >> (7-col)) & 0x1; // plane=0: bit1, plane=2: bit3 + tile[row * 8 + col] |= plane02Bit << (plane + 0); + tile[row * 8 + col] |= plane13Bit << (plane + 1); + } +} + +void GdiPCEngine::decodePCEngineTileData(const byte *ptr) { + const byte *tilePtr; + byte* tile; + uint16* tileOffsets; + byte byte0, byte1; + + readOffsetTable(ptr, &tileOffsets, &_PCE.numTiles); + + 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++; + byte cnt = (cmd & 0x0F) + 1; + if (cmd & 0x80) { + byte0 = (cmd & 0x10) ? 0 : *tilePtr++; + byte1 = (cmd & 0x40) ? 0 : *tilePtr++; + while (cnt--) { + setTileData(tile, index++, byte0, byte1); + } + } else { + while (cnt--) { + byte0 = (cmd & 0x10) ? 0 : *tilePtr++; + byte1 = (cmd & 0x40) ? 0 : *tilePtr++; + setTileData(tile, index++, byte0, byte1); + } + } + } + } + + free(tileOffsets); +} + +// 52, 1: 2 532 + +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]; + tile = &_PCE.tiles[tileIdx * 64]; + paletteIdx = (_objectMode ? _PCE.colortableObj : _PCE.colortable)[stripnr * height + i]; + 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; + } + } +} + +void GdiPCEngine::drawStripPCEngineMask(byte *dst, int stripnr, int top, int height) const { + // TODO +} + void GdiV1::drawStripC64Background(byte *dst, int dstPitch, int stripnr, int height) { int charIdx; height /= 8; diff --git a/engines/scumm/gfx.h b/engines/scumm/gfx.h index 0910d9bc59..34ba63164c 100644 --- a/engines/scumm/gfx.h +++ b/engines/scumm/gfx.h @@ -301,6 +301,47 @@ public: virtual void roomChanged(byte *roomptr); }; +class GdiPCEngine : public Gdi { +protected: + struct { + uint16 nametable[4096], nametableObj[512]; + byte colortable[4096], colortableObj[512]; + byte attributes[64], attributesObj[64]; + uint16 masktable[4096], masktableObj[512]; + int objX; + bool hasmask; + int numTiles; + byte* tiles; + } _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 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); + void drawStripPCEngineMask(byte *dst, int stripnr, int top, int height) const; + + virtual bool drawStrip(byte *dstPtr, VirtScreen *vs, + int x, int y, const int width, const int height, + int stripnr, const byte *smap_ptr); + + virtual void decodeMask(int x, int y, const int width, const int height, + int stripnr, int numzbuf, const byte *zplane_list[9], + bool transpStrip, byte flag, const byte *tmsk_ptr); + + virtual void prepareDrawBitmap(const byte *ptr, VirtScreen *vs, + const int x, const int y, const int width, const int height, + int stripnr, int numstrip); + +public: + GdiPCEngine(ScummEngine *vm); + ~GdiPCEngine(); + + virtual void roomChanged(byte *roomptr); +}; + class GdiV1 : public Gdi { protected: /** Render settings which are specific to the C64 graphic decoders. */ diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp index 18881e1089..c6ec6021f3 100644 --- a/engines/scumm/palette.cpp +++ b/engines/scumm/palette.cpp @@ -202,6 +202,67 @@ void ScummEngine::setPaletteFromTable(const byte *ptr, int numcolor, int index) setPalColor( index, ptr[0], ptr[1], ptr[2]); } +void colorPCEToRGB(uint16 color, byte *r, byte *g, byte *b) { + // 3 bits for each color component: 0xgggrrrbbb + *b = ((color) & 0x7) << 5; + *r = ((color >> 3) & 0x7) << 5; + *g = ((color >> 6) & 0x7) << 5; +} + +void readPalette(const byte **ptr, byte **dest, int numEntries) { + byte r, g, b; + byte msbs = 0; + + for (int i = 0; i < numEntries; ++i) { + if (i % 8 == 0) { + // byte contains MSBs (bit 8) for the next 8 bytes + msbs = *(*ptr)++; + } + uint16 msb = (msbs & 0x1) << 8; + uint16 paletteEntry = msb | *(*ptr)++; + colorPCEToRGB(paletteEntry, &r, &g, &b); + *(*dest)++ = r; + *(*dest)++ = g; + *(*dest)++ = b; + msbs >>= 1; + } +} + +void ScummEngine::setPCEPaletteFromPtr(const byte *ptr) { + byte *dest; + byte bgSpriteR, bgSpriteG, bgSpriteB; + + int paletteOffset = *ptr++; + int numPalettes = *ptr++; + + int firstIndex = paletteOffset * 16; + int numcolor = numPalettes * 16; + + // the only color over which a background sprite + // (bit 7 of the sprite attributes) will be visible + colorPCEToRGB(READ_LE_UINT16(ptr), &bgSpriteR, &bgSpriteG, &bgSpriteB); + ptr += 2; + + dest = _currentPalette + firstIndex * 3; + + for (int i = 0; i < numPalettes; ++i) { + // entry 0 + *dest++ = bgSpriteR; + *dest++ = bgSpriteG; + *dest++ = bgSpriteB; + + // entry 1 - 14 + readPalette(&ptr, &dest, 14); + + // entry 15: DEFAULT_PALETTE[var3AE3]; + *dest++ = 6 << 5; + *dest++ = 6 << 5; + *dest++ = 6 << 5; + } + + setDirtyColors(firstIndex, firstIndex + numcolor - 1); +} + void ScummEngine::setPaletteFromPtr(const byte *ptr, int numcolor) { int firstIndex = 0; int i; @@ -870,7 +931,11 @@ void ScummEngine::setCurrentPalette(int palindex) { _curPalIndex = palindex; pals = getPalettePtr(_curPalIndex, _roomResource); - setPaletteFromPtr(pals); + if (_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine) { + setPCEPaletteFromPtr(pals); + } else { + setPaletteFromPtr(pals); + } } void ScummEngine::setRoomPalette(int palindex, int room) { diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp index d3faa15c10..ad0c87c6f2 100644 --- a/engines/scumm/resource.cpp +++ b/engines/scumm/resource.cpp @@ -1472,6 +1472,8 @@ uint16 newTag2Old(uint32 newTag) { return (0x4343); // CC case (MKID_BE('EPAL')): return (0x5053); // SP + case (MKID_BE('TILE')): + return (0x4C54); // TL default: return (0); } diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index bced8a784d..19c76d6b7d 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -115,6 +115,8 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr) _gdi = new Gdi16Bit(this); } else if (_game.platform == Common::kPlatformNES) { _gdi = new GdiNES(this); + } else if (_game.platform == Common::kPlatformPCEngine) { + _gdi = new GdiPCEngine(this); } else if (_game.version <= 1) { _gdi = new GdiV1(this); } else if (_game.version == 2) { @@ -613,7 +615,7 @@ ScummEngine_v5::ScummEngine_v5(OSystem *syst, const DetectorResult &dr) // All "classic" games (V5 and older) encrypted their data files // with exception of the GF_OLD256 games and the PC-Engine version // of Loom. - if (!(_game.features & GF_OLD256) && _game.platform != Common::kPlatformPCEngine) + if (!(_game.features & GF_OLD256)) _game.features |= GF_USE_KEY; resetCursors(); @@ -1280,6 +1282,9 @@ void ScummEngine::setupCostumeRenderer() { } else if (_game.platform == Common::kPlatformNES) { _costumeRenderer = new NESCostumeRenderer(this); _costumeLoader = new NESCostumeLoader(this); + } else if (_game.platform == Common::kPlatformPCEngine) { + _costumeRenderer = new PCEngineCostumeRenderer(this); + _costumeLoader = new PCEngineCostumeLoader(this); } else { _costumeRenderer = new ClassicCostumeRenderer(this); _costumeLoader = new ClassicCostumeLoader(this); diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index 57094e0c59..e3475d6bf7 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -1034,6 +1034,7 @@ protected: void setCurrentPalette(int pal); void setRoomPalette(int pal, int room); + void setPCEPaletteFromPtr(const byte *ptr); virtual void setPaletteFromPtr(const byte *ptr, int numcolor = -1); virtual void setPalColor(int index, int r, int g, int b); void setDirtyColors(int min, int max); diff --git a/tools/credits.pl b/tools/credits.pl index 59f54a3dc8..d8355257e2 100755 --- a/tools/credits.pl +++ b/tools/credits.pl @@ -827,6 +827,7 @@ begin_credits("Credits"); begin_persons(); add_person("Ori Avtalion", "salty-horse", "Subtitle control options in the GUI; BASS GUI fixes"); add_person("Stuart Caie", "", "Decoders for Amiga and AtariST data files (AGOS engine)"); + add_person("Tobias Gunkel", "hennymcc", "Graphic support for PCE version of Loom"); add_person("Paolo Costabel", "", "PSP port contributions"); add_person("Thierry Crozat", "criezy", "Support for Broken Sword 1 Macintosh version"); add_person("Martin Doucha", "next_ghost", "CinE engine objectification"); -- cgit v1.2.3