aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorTravis Howell2009-10-21 12:59:10 +0000
committerTravis Howell2009-10-21 12:59:10 +0000
commit746258f882b74cea1c5d5a34ef6c67e0669cdf09 (patch)
treed266519a68dd149709708c4b641d0fb0fa95015e /engines
parent1e8883dcccfd490ba8844bb46cc90d5437c6f3f1 (diff)
downloadscummvm-rg350-746258f882b74cea1c5d5a34ef6c67e0669cdf09.tar.gz
scummvm-rg350-746258f882b74cea1c5d5a34ef6c67e0669cdf09.tar.bz2
scummvm-rg350-746258f882b74cea1c5d5a34ef6c67e0669cdf09.zip
Add patch from Tobias, for graphic support (backgrounds/objects) in PCE version of Loom, with minor changes.
svn-id: r45304
Diffstat (limited to 'engines')
-rw-r--r--engines/scumm/costume.cpp59
-rw-r--r--engines/scumm/costume.h31
-rw-r--r--engines/scumm/detection.cpp2
-rw-r--r--engines/scumm/detection_tables.h2
-rw-r--r--engines/scumm/gfx.cpp312
-rw-r--r--engines/scumm/gfx.h41
-rw-r--r--engines/scumm/palette.cpp67
-rw-r--r--engines/scumm/resource.cpp2
-rw-r--r--engines/scumm/scumm.cpp7
-rw-r--r--engines/scumm/scumm.h1
10 files changed, 505 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);