aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
authorTravis Howell2009-10-25 14:20:47 +0000
committerTravis Howell2009-10-25 14:20:47 +0000
commit4064d35d1582e6d18b92c5ec352bde902b41e0d8 (patch)
treeca008bcb480131905aee04d8509e6276cfa394dc /engines/scumm
parent6e5dd8e357ac5f8c08e9713b59d1858086073a36 (diff)
downloadscummvm-rg350-4064d35d1582e6d18b92c5ec352bde902b41e0d8.tar.gz
scummvm-rg350-4064d35d1582e6d18b92c5ec352bde902b41e0d8.tar.bz2
scummvm-rg350-4064d35d1582e6d18b92c5ec352bde902b41e0d8.zip
Add patch from Tobias, for initial costume support in PCE version of Loom, with minor changes.
svn-id: r45370
Diffstat (limited to 'engines/scumm')
-rw-r--r--engines/scumm/base-costume.h2
-rw-r--r--engines/scumm/costume.cpp217
-rw-r--r--engines/scumm/costume.h27
-rw-r--r--engines/scumm/scumm.cpp2
4 files changed, 157 insertions, 91 deletions
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index d41d795e34..d586b211f3 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -103,6 +103,8 @@ protected:
// whether to draw the actor mirrored
bool _mirror;
+ int _numBlocks;
+
// width and height of cel to decode
int _width, _height;
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 5c9cf11ab8..d50ae54480 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -86,13 +86,9 @@ byte ClassicCostumeRenderer::mainRoutine(int xmoveCur, int ymoveCur) {
int step;
Codec1 v1;
- if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine) {
- // FIXME: Unknown costume format
- return 0;
- }
-
const int scaletableSize = 128;
const bool newAmiCost = (_vm->_game.version == 5) && (_vm->_game.platform == Common::kPlatformAmiga);
+ const bool pcEngCost = (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine);
v1.scaletable = smallCostumeScaleTable;
@@ -242,7 +238,7 @@ byte ClassicCostumeRenderer::mainRoutine(int xmoveCur, int ymoveCur) {
if (!use_scaling)
skip = -v1.x;
if (skip > 0) {
- if (!newAmiCost && _loaded._format != 0x57) {
+ if (!newAmiCost && !pcEngCost && _loaded._format != 0x57) {
v1.skip_width -= skip;
codec1_ignorePakCols(v1, skip);
v1.x = 0;
@@ -259,7 +255,7 @@ byte ClassicCostumeRenderer::mainRoutine(int xmoveCur, int ymoveCur) {
if (!use_scaling)
skip = rect.right - _out.w;
if (skip > 0) {
- if (!newAmiCost && _loaded._format != 0x57) {
+ if (!newAmiCost && !pcEngCost && _loaded._format != 0x57) {
v1.skip_width -= skip;
codec1_ignorePakCols(v1, skip);
v1.x = _out.w - 1;
@@ -311,6 +307,8 @@ byte ClassicCostumeRenderer::mainRoutine(int xmoveCur, int ymoveCur) {
procC64(v1, _actorID);
} else if (newAmiCost)
proc3_ami(v1);
+ else if (pcEngCost)
+ procPCEngine(v1);
else
proc3(v1);
@@ -583,14 +581,91 @@ void ClassicCostumeRenderer::proc3_ami(Codec1 &v1) {
} while (1);
}
-void ClassicCostumeLoader::loadCostume(int id) {
- _id = id;
- byte *ptr = _vm->getResourceAddress(rtCostume, id);
+void PCESetCostumeData(byte block[16][16], int index, byte value) {
+ int row = (index % 16);
+ int plane = (index / 16) % 4;
+ int colOffset = (index < 64) ? 8 : 0;
+ for (int i = 0; i < 8; ++i) {
+ int bit = (value >> (7-i)) & 0x1;
+ block[row][i + colOffset] |= bit << plane;
+ }
+}
- if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine) {
- // FIXME: Unknown costume format
+void ClassicCostumeRenderer::procPCEngine(Codec1 &v1) {
+ const byte *mask, *src;
+ byte *dst;
+ byte maskbit;
+ uint width, height;
+ byte scaleIndexY;
+ int vertShift;
+
+ byte block[16][16];
+
+ src = _srcptr;
+ width = _width / 16;
+ height = _height / 16;
+
+ if (_numBlocks == 0)
return;
+
+ scaleIndexY = _scaleIndexY;
+ maskbit = revBitMask(v1.x & 7);
+ mask = v1.mask_ptr + v1.x / 8;
+
+ for (uint x = 0; x < width; ++x) {
+ dst = v1.destptr + 16 * x * _out.bytesPerPixel;
+ for (uint y = 0; y < height; ++y) {
+ vertShift = *src++;
+ if (vertShift == 0xFF) {
+ dst += 16 * _out.pitch;
+ continue;
+ } else {
+ dst += vertShift * _out.pitch;
+ }
+
+ memset(block, 0, sizeof(block));
+
+ int index = 0;
+ while (index < 128) {
+ byte cmd = *src++;
+ int cnt = (cmd & 0x3F) + 1;
+ if (!(cmd & 0xC0)) {
+ for (int i = 0; i < cnt; ++i)
+ PCESetCostumeData(block, index++, 0);
+ } else if (cmd & 0x80) {
+ int value = *src++;
+ for (int i = 0; i < cnt; ++i)
+ PCESetCostumeData(block, index++, value);
+ } else {
+ for (int i = 0; i < cnt; ++i)
+ PCESetCostumeData(block, index++, *src++);
+ }
+ }
+ if (index != 128) {
+ printf("%d\n", index);
+ }
+
+ for (int row = 0; row < 16; ++row) {
+ 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 += _out.pitch;
+ }
+ }
}
+}
+
+void ClassicCostumeLoader::loadCostume(int id) {
+ _id = id;
+ byte *ptr = _vm->getResourceAddress(rtCostume, id);
if (_vm->_game.version >= 6)
ptr += 8;
@@ -607,6 +682,17 @@ void ClassicCostumeLoader::loadCostume(int id) {
_format = ptr[7] & 0x7F;
_mirror = (ptr[7] & 0x80) != 0;
_palette = ptr + 8;
+
+ if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine) {
+ _numColors = 16;
+
+ ptr += 8 + 17;
+ _animCmds = READ_LE_UINT16(ptr) + ptr + 2;
+ _frameOffsets = ptr + 2;
+ _dataOffsets = ptr + 34;
+ return;
+ }
+
switch (_format) {
case 0x57: // Only used in V1 games
_numColors = 0;
@@ -737,8 +823,49 @@ byte NESCostumeRenderer::drawLimb(const Actor *a, int limb) {
return 0;
}
+#define PCE_SIGNED(a) (((a) & 0x80) ? -((a) & 0x7F) : (a))
+
byte PCEngineCostumeRenderer::drawLimb(const Actor *a, int limb) {
- // TODO
+ 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;
}
@@ -813,17 +940,9 @@ 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;
+ const byte *baseptr;
uint mask, j;
int i;
byte extra, cmd;
@@ -837,9 +956,13 @@ void ClassicCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask)
return;
}
- r = _baseptr + READ_LE_UINT16(_dataOffsets + anim * 2);
+ if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine)
+ baseptr = _dataOffsets + anim * 2 + 2;
+ else
+ baseptr = _baseptr;
- if (r == _baseptr) {
+ r = baseptr + READ_LE_UINT16(_dataOffsets + anim * 2);
+ if (r == baseptr) {
return;
}
@@ -852,7 +975,9 @@ void ClassicCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask)
i = 0;
do {
if (mask & 0x8000) {
- if (_vm->_game.version <= 3) {
+ if ((_vm->_game.version <= 3) &&
+ !(_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine))
+ {
j = *r++;
if (j == 0xFF)
@@ -1042,48 +1167,6 @@ 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 b845ee2158..5191a9388e 100644
--- a/engines/scumm/costume.h
+++ b/engines/scumm/costume.h
@@ -71,22 +71,6 @@ 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) {}
@@ -126,6 +110,8 @@ protected:
void procC64(Codec1 &v1, int actor);
+ void procPCEngine(Codec1 &v1);
+
byte mainRoutine(int xmoveCur, int ymoveCur);
};
@@ -144,16 +130,11 @@ protected:
byte drawLimb(const Actor *a, int limb);
};
-class PCEngineCostumeRenderer : public BaseCostumeRenderer {
-protected:
- PCEngineCostumeLoader _loaded;
-
+class PCEngineCostumeRenderer : public ClassicCostumeRenderer {
public:
- PCEngineCostumeRenderer(ScummEngine *vm) : BaseCostumeRenderer(vm), _loaded(vm) {}
+ PCEngineCostumeRenderer(ScummEngine *vm) : ClassicCostumeRenderer(vm) {}
void setPalette(uint16 *palette);
- void setFacing(const Actor *a);
- void setCostume(int costume, int shadow);
protected:
byte drawLimb(const Actor *a, int limb);
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 19c76d6b7d..b8afb5460e 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1284,7 +1284,7 @@ void ScummEngine::setupCostumeRenderer() {
_costumeLoader = new NESCostumeLoader(this);
} else if (_game.platform == Common::kPlatformPCEngine) {
_costumeRenderer = new PCEngineCostumeRenderer(this);
- _costumeLoader = new PCEngineCostumeLoader(this);
+ _costumeLoader = new ClassicCostumeLoader(this);
} else {
_costumeRenderer = new ClassicCostumeRenderer(this);
_costumeLoader = new ClassicCostumeLoader(this);