aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schickel2009-08-09 19:11:10 +0000
committerJohannes Schickel2009-08-09 19:11:10 +0000
commitad40f3b46eb898fac1447c7ceb55f312fbed8a8c (patch)
tree7d5701d687cc1853a370dde98570bbcb6c42e104
parent9711cb0191eee52e2ea26031f078a8adbc94c16a (diff)
downloadscummvm-rg350-ad40f3b46eb898fac1447c7ceb55f312fbed8a8c.tar.gz
scummvm-rg350-ad40f3b46eb898fac1447c7ceb55f312fbed8a8c.tar.bz2
scummvm-rg350-ad40f3b46eb898fac1447c7ceb55f312fbed8a8c.zip
Cleanup AMIGA graphics conversion.
svn-id: r43183
-rw-r--r--engines/kyra/screen.cpp143
-rw-r--r--engines/kyra/screen.h2
-rw-r--r--engines/kyra/wsamovie.cpp4
3 files changed, 79 insertions, 70 deletions
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 7a7544a589..d726a32a5a 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -2068,85 +2068,94 @@ void Screen::decodeFrameDeltaPage(uint8 *dst, const uint8 *src, int pitch, bool
wrapped_decodeFrameDeltaPage<false>(dst, src, pitch);
}
-void Screen::convertAmigaGfx(uint8 *data, int w, int h, bool offscreen) {
- static uint8 tmp[320*200];
-
- if (offscreen) {
- uint8 *curLine = tmp;
- const uint8 *src = data;
- int hC = h;
- while (hC--) {
- uint8 *dst1 = curLine;
- uint8 *dst2 = dst1 + 8000;
- uint8 *dst3 = dst2 + 8000;
- uint8 *dst4 = dst3 + 8000;
- uint8 *dst5 = dst4 + 8000;
-
- int width = w >> 3;
- while (width--) {
- *dst1++ = *src++;
- *dst2++ = *src++;
- *dst3++ = *src++;
- *dst4++ = *src++;
- *dst5++ = *src++;
- }
-
- curLine += 40;
+void Screen::convertAmigaGfx(uint8 *data, int w, int h, int depth, bool wsa) {
+ const int planeWidth = (w + 7) / 8;
+ const int planeSize = planeWidth * h;
+ const uint imageSize = planeSize * depth;
+
+ // Our static buffer which holds the plane data. We need this
+ // because the "data" pointer is both source and destination pointer.
+ // The buffer has enough space to fit the AMIGA MSC files, which are
+ // the biggest graphics files found in the AMIGA version.
+ static uint8 temp[40320];
+ assert(imageSize <= sizeof(temp));
+
+ // WSA files store their graphics data in a little different format, than
+ // the usual AMIGA graphics format used in BitMaps. Thus we need to do
+ // some special handling for them here. Means we convert them into
+ // the usual format.
+ //
+ // TODO: We might think of moving this conversion into the WSAMovieAmiga
+ // class.
+ if (wsa) {
+ const byte *src = data;
+ for (int y = 0; y < h; ++y) {
+ for (int x = 0; x < planeWidth; ++x)
+ for (int i = 0; i < depth; ++i)
+ temp[y * planeWidth + x + planeSize * i] = *src++;
}
} else {
- memcpy(tmp, data, w*h);
+ memcpy(temp, data, imageSize);
}
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
- int bytePos = x/8+y*40;
- int bitPos = 7-(x&7);
-
- byte colorIndex = 0;
- colorIndex |= (((tmp[bytePos + 8000 * 0] & (1 << bitPos)) >> bitPos) & 0x1) << 0;
- colorIndex |= (((tmp[bytePos + 8000 * 1] & (1 << bitPos)) >> bitPos) & 0x1) << 1;
- colorIndex |= (((tmp[bytePos + 8000 * 2] & (1 << bitPos)) >> bitPos) & 0x1) << 2;
- colorIndex |= (((tmp[bytePos + 8000 * 3] & (1 << bitPos)) >> bitPos) & 0x1) << 3;
- colorIndex |= (((tmp[bytePos + 8000 * 4] & (1 << bitPos)) >> bitPos) & 0x1) << 4;
- *data++ = colorIndex;
+ const int bytePos = x / 8 + y * planeWidth;
+ const int bitPos = 7 - (x & 7); // x & 7 == x % 8
+
+ byte col = 0;
+
+ for (int i = 0; i < depth; ++i)
+ col |= ((temp[bytePos + planeSize * i] >> bitPos) & 1) << i;
+
+ *data++ = col;
}
}
}
void Screen::convertAmigaMsc(uint8 *data) {
- byte *plane1 = data + 5760 * 1;
- byte *plane2 = data + 5760 * 2;
- byte *plane3 = data + 5760 * 3;
- byte *plane4 = data + 5760 * 4;
- byte *plane5 = data + 5760 * 5;
- byte *plane6 = data + 5760 * 6;
- for (int i = 0; i < 5760; ++i) {
- byte d = plane6[i];
- d = (plane5[i] |= d);
- d = (plane4[i] |= d);
- d = (plane3[i] |= d);
- d = (plane2[i] |= d);
- d = (plane1[i] |= d);
- }
- byte dst[320*144];
- memset(dst, 0, sizeof(dst));
- static const byte flagTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
- for (int y = 0; y < 144; ++y) {
- for (int x = 0; x < 320; ++x) {
- if (!(flagTable[x&7] & data[y*40+(x>>3)]))
- dst[y*320+x] |= 0x80;
-
- int layer = 0;
- for (int i = 0; i < 7; ++i) {
- if (flagTable[x&7] & data[y*40+(x>>3)+i*5760])
- layer = i;
- }
+ // MSC files are always 320x144, thus we can safely assume
+ // this to be correct. Also they contain 7 planes instead
+ // of the normal 5 planes, which is used in 32 color mode.
+ // The need for 7 planes can be explained, because the MSC
+ // files have 6 bits for the layer number (bits 1 to 6)
+ // and one bit for the "blocked" flag (bit 0), and every
+ // plane contains one bit per pixel.
+ convertAmigaGfx(data, 320, 144, 7);
+
+ // We need to do some post conversion, since
+ // the AMIGA MSC format is different from the DOS
+ // one we use internally for our code.That is even
+ // after converting it from the AMIGA plane based
+ // approach to one byte per pixel approach.
+ for (int i = 0; i < 320 * 144; ++i) {
+ // The lowest bit indicates, whether the position
+ // is walkable or not. If the bit is set, the
+ // position is walkable, elsewise it is blocked.
+ if (data[i] & 1)
+ data[i] &= 0xFE;
+ else
+ data[i] |= 0x80;
- if (layer)
- dst[y*320+x] |= (layer+1);
- }
+ // The graphics layer for the pixel is saved
+ // in the following format:
+ // The highest bit set indicates the number of
+ // the graphics layer. We count the first
+ // bit as 0 here, thus we need to add one,
+ // to get the correct number.
+ //
+ // Funnily since the first bit (bit 0) is
+ // resevered for testing whether the position
+ // is walkable or not, there is no possibility
+ // for layer 1 to be present.
+ int layer = 0;
+ for (int k = 0; k < 7; ++k)
+ if (data[i] & (1 << k))
+ layer = k + 1;
+
+ data[i] &= 0x80;
+ data[i] |= layer;
}
- memcpy(data, dst, 320*144);
}
template<bool noXor>
@@ -2815,7 +2824,7 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, Palette
if (!scumm_stricmp(ext, "MSC"))
Screen::convertAmigaMsc(dstData);
else
- Screen::convertAmigaGfx(dstData, 320, 200, false);
+ Screen::convertAmigaGfx(dstData, 320, 200);
}
if (skip)
diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h
index d8380d104d..f7fb389fe8 100644
--- a/engines/kyra/screen.h
+++ b/engines/kyra/screen.h
@@ -342,7 +342,7 @@ public:
static void decodeFrameDelta(uint8 *dst, const uint8 *src, bool noXor = false);
static void decodeFrameDeltaPage(uint8 *dst, const uint8 *src, const int pitch, bool noXor);
- static void convertAmigaGfx(uint8 *data, int w, int h, bool offscreen = true);
+ static void convertAmigaGfx(uint8 *data, int w, int h, int depth = 5, bool wsa = false);
static void convertAmigaMsc(uint8 *data);
protected:
diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp
index ef3fd1a966..0aaeebc589 100644
--- a/engines/kyra/wsamovie.cpp
+++ b/engines/kyra/wsamovie.cpp
@@ -262,7 +262,7 @@ void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, uint16
if (_currentFrame == _numFrames) {
if (!(_flags & WF_NO_FIRST_FRAME)) {
Screen::decodeFrameDelta(dst, _deltaBuffer, true);
- Screen::convertAmigaGfx(dst, _width, _height);
+ Screen::convertAmigaGfx(dst, _width, _height, 5, true);
if (_flags & WF_OFFSCREEN_DECODE) {
dst = _offscreenBuffer;
@@ -341,7 +341,7 @@ void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) {
const uint8 *src = _frameData + _frameOffsTable[frameNum];
Screen::decodeFrame4(src, _deltaBuffer, _deltaBufferSize);
Screen::decodeFrameDelta(dst, _deltaBuffer, true);
- Screen::convertAmigaGfx(dst, _width, _height);
+ Screen::convertAmigaGfx(dst, _width, _height, 5, true);
src = dst;
dst = 0;