mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-03 17:33:05 +00:00
Add cyx's patch for cleanup for planar conversion code, and support for 32 color planar graphics of Amiga ECS version of Simon the Sorcerer 1.
svn-id: r25436
This commit is contained in:
parent
dda1431e7c
commit
eaeada78ac
@ -1278,6 +1278,7 @@ protected:
|
||||
bool drawImages_clip(VC10_state *state);
|
||||
|
||||
void drawImages(VC10_state *state);
|
||||
void drawImages_Amiga(VC10_state *state);
|
||||
void drawImages_Simon(VC10_state *state);
|
||||
void drawImages_Feeble(VC10_state *state);
|
||||
|
||||
@ -1336,7 +1337,7 @@ protected:
|
||||
byte *getBackGround();
|
||||
byte *getScaleBuf();
|
||||
|
||||
byte *convertclip(const byte *src, uint height, uint width, byte flags);
|
||||
byte *convertclip(const byte *src, bool is32Colors, uint height, uint width, byte flags);
|
||||
|
||||
bool decrunchFile(byte *src, byte *dst, uint32 size);
|
||||
void loadVGABeardFile(uint id);
|
||||
|
@ -425,36 +425,30 @@ void AGOSEngine::drawImages_Simon(VC10_state *state) {
|
||||
dst = state->surf_addr + w * 2; /* edi */
|
||||
|
||||
h = state->draw_height;
|
||||
if ((getGameType() == GType_SIMON1) && getBitFlag(88)) {
|
||||
/* transparency */
|
||||
do {
|
||||
if (mask[0] & 0xF0) {
|
||||
if ((dst[0] & 0x0F0) == 0x20)
|
||||
do {
|
||||
if ((getGameType() == GType_SIMON1) && getBitFlag(88)) {
|
||||
/* transparency */
|
||||
if (mask[0] & 0xF0) {
|
||||
if ((dst[0] & 0x0F0) == 0x20)
|
||||
dst[0] = src[0];
|
||||
}
|
||||
if (mask[0] & 0x0F) {
|
||||
if ((dst[1] & 0x0F0) == 0x20)
|
||||
dst[1] = src[1];
|
||||
}
|
||||
} else {
|
||||
/* no transparency */
|
||||
if (mask[0] & 0xF0)
|
||||
dst[0] = src[0];
|
||||
}
|
||||
if (mask[0] & 0x0F) {
|
||||
if ((dst[1] & 0x0F0) == 0x20)
|
||||
if (mask[0] & 0x0F)
|
||||
dst[1] = src[1];
|
||||
}
|
||||
mask++;
|
||||
dst += state->surf_pitch;
|
||||
src += state->surf2_pitch;
|
||||
} while (--h);
|
||||
} else {
|
||||
/* no transparency */
|
||||
do {
|
||||
if (mask[0] & 0xF0)
|
||||
dst[0] = src[0];
|
||||
if (mask[0] & 0x0F)
|
||||
dst[1] = src[1];
|
||||
mask++;
|
||||
dst += state->surf_pitch;
|
||||
src += state->surf2_pitch;
|
||||
} while (--h);
|
||||
}
|
||||
}
|
||||
mask++;
|
||||
dst += state->surf_pitch;
|
||||
src += state->surf2_pitch;
|
||||
} while (--h);
|
||||
} while (++w != state->draw_width);
|
||||
} else if ((((_lockWord & 0x20) && state->palette == 0) || state->palette == 0xC0) &&
|
||||
getPlatform() != Common::kPlatformAmiga) {
|
||||
} else if ((((_lockWord & 0x20) && state->palette == 0) || state->palette == 0xC0)) {
|
||||
const byte *src;
|
||||
byte *dst;
|
||||
uint h, i;
|
||||
@ -589,6 +583,61 @@ void AGOSEngine::drawImages_Simon(VC10_state *state) {
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::drawImages_Amiga(VC10_state *state) {
|
||||
uint8 *dst;
|
||||
const byte *src;
|
||||
const uint16 *vlut = &_videoWindows[_windowNum * 4];
|
||||
|
||||
if (drawImages_clip(state) == 0)
|
||||
return;
|
||||
|
||||
uint xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8;
|
||||
uint yoffs = (vlut[1] - _videoWindows[17] + state->y);
|
||||
|
||||
state->surf2_addr += xoffs + yoffs * state->surf_pitch;
|
||||
state->surf_addr += xoffs + yoffs * state->surf2_pitch;
|
||||
|
||||
if (state->flags & kDFMasked) {
|
||||
const byte *mask = state->depack_src + (state->width * state->y_skip * 16) + (state->x_skip * 8);
|
||||
src = state->surf2_addr;
|
||||
dst = state->surf_addr;
|
||||
|
||||
state->draw_width *= 2;
|
||||
|
||||
uint h = state->draw_height;
|
||||
do {
|
||||
for (uint i = 0; i != state->draw_width; i++) {
|
||||
if ((getGameType() == GType_SIMON1) && getBitFlag(88)) {
|
||||
/* transparency */
|
||||
if (mask[i] & 1 && (dst[i] & 1) == 0x20)
|
||||
dst[i] = src[i];
|
||||
} else {
|
||||
/* no transparency */
|
||||
if (mask[i] & 1)
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
dst += state->surf_pitch;
|
||||
src += state->surf2_pitch;
|
||||
mask += state->width * 16;
|
||||
} while (--h);
|
||||
} else {
|
||||
src = state->depack_src + (state->width * state->y_skip * 16) + (state->x_skip * 8);
|
||||
dst = state->surf_addr;
|
||||
|
||||
state->draw_width *= 2;
|
||||
|
||||
uint h = state->draw_height;
|
||||
do {
|
||||
for (uint i = 0; i != state->draw_width; i++)
|
||||
if ((state->flags & kDFNonTrans) || src[i])
|
||||
dst[i] = src[i];
|
||||
dst += _screenWidth;
|
||||
src += state->width * 16;
|
||||
} while (--h);
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::drawImages(VC10_state *state) {
|
||||
const uint16 *vlut = &_videoWindows[_windowNum * 4];
|
||||
|
||||
|
@ -29,29 +29,29 @@
|
||||
|
||||
namespace AGOS {
|
||||
|
||||
enum {
|
||||
kMaxColorDepth = 5
|
||||
};
|
||||
|
||||
static void uncompressplane(const byte *plane, byte *outptr, uint16 length) {
|
||||
char x;
|
||||
byte y, z;
|
||||
while (length) {
|
||||
x = *plane++;
|
||||
while (length != 0) {
|
||||
char x = *plane++;
|
||||
if (x >= 0) {
|
||||
x += 1;
|
||||
y = *plane++;
|
||||
z = *plane++;
|
||||
while (x) {
|
||||
x++;
|
||||
byte y = *plane++;
|
||||
byte z = *plane++;
|
||||
while (x != 0) {
|
||||
*outptr++ = y;
|
||||
*outptr++ = z;
|
||||
length--;
|
||||
if (length == 0)
|
||||
if (--length == 0)
|
||||
break;
|
||||
x--;
|
||||
}
|
||||
} else {
|
||||
while (x) {
|
||||
while (x != 0) {
|
||||
*outptr++ = *plane++;
|
||||
*outptr++ = *plane++;
|
||||
length--;
|
||||
if (length == 0)
|
||||
if (--length == 0)
|
||||
break;
|
||||
x++;
|
||||
}
|
||||
@ -59,183 +59,87 @@ static void uncompressplane(const byte *plane, byte *outptr, uint16 length) {
|
||||
}
|
||||
}
|
||||
|
||||
static void convertcompressedclip(const byte *src, byte *dst, uint16 height, uint16 width) {
|
||||
const byte *plane0, *plane1, *plane2, *plane3;
|
||||
byte *uncbuffer;
|
||||
byte *uncptr0, *uncptr1, *uncptr2, *uncptr3;
|
||||
byte *uncbfrout;
|
||||
byte *uncbfroutptr;
|
||||
uint16 length, i, j, k, word1, word2, word3, word4, cliplength;
|
||||
byte outbyte, outbyte1, x, y;
|
||||
char n;
|
||||
uncbuffer = (byte *)malloc(height * width * 4);
|
||||
uncbfrout = (byte *)malloc(height * width * 4);
|
||||
|
||||
byte *free_uncbuffer = uncbuffer;
|
||||
byte *free_uncbfrout = uncbfrout;
|
||||
|
||||
length = width / 16;
|
||||
length *= height;
|
||||
plane0 = READ_BE_UINT16(src) + READ_BE_UINT16(src + 2) + src; src += 4; plane0 += 4;
|
||||
plane1 = READ_BE_UINT16(src) + READ_BE_UINT16(src + 2) + src; src += 4; plane1 += 4;
|
||||
plane2 = READ_BE_UINT16(src) + READ_BE_UINT16(src + 2) + src; src += 4; plane2 += 4;
|
||||
plane3 = READ_BE_UINT16(src) + READ_BE_UINT16(src + 2) + src; src += 4; plane3 += 4;
|
||||
plane0 -= 4;
|
||||
plane1 -= 8;
|
||||
plane2 -= 12;
|
||||
plane3 -= 16;
|
||||
uncptr0 = uncbuffer;
|
||||
uncptr1 = uncptr0+(length * 2);
|
||||
uncptr2 = uncptr1+(length * 2);
|
||||
uncptr3 = uncptr2+(length * 2);
|
||||
uncompressplane(plane0, uncptr0, length);
|
||||
uncompressplane(plane1, uncptr1, length);
|
||||
uncompressplane(plane2, uncptr2, length);
|
||||
uncompressplane(plane3, uncptr3, length);
|
||||
uncbfroutptr = uncbfrout;
|
||||
for (i = 0; i < length; i++) {
|
||||
word1=READ_BE_UINT16(uncptr0); uncptr0 += 2;
|
||||
word2=READ_BE_UINT16(uncptr1); uncptr1 += 2;
|
||||
word3=READ_BE_UINT16(uncptr2); uncptr2 += 2;
|
||||
word4=READ_BE_UINT16(uncptr3); uncptr3 += 2;
|
||||
for (j = 0; j < 8; j++) {
|
||||
outbyte = ((word1 / 32768) + ((word2 / 32768) * 2) + ((word3 / 32768) * 4) + ((word4 / 32768) * 8));
|
||||
word1 <<= 1;
|
||||
word2 <<= 1;
|
||||
word3 <<= 1;
|
||||
word4 <<= 1;
|
||||
outbyte1 = ((word1 / 32768) + ((word2 / 32768) * 2) + ((word3 / 32768) * 4) + ((word4 / 32768) * 8));
|
||||
word1 <<= 1;
|
||||
word2 <<= 1;
|
||||
word3 <<= 1;
|
||||
word4 <<= 1;
|
||||
*uncbfroutptr++ = (outbyte * 16 + outbyte1);
|
||||
}
|
||||
}
|
||||
uncptr0 = uncbuffer;
|
||||
uncptr1 = uncbfrout;
|
||||
uncptr2 = uncbfrout;
|
||||
uncptr3 = uncbfrout;
|
||||
for (i = 0; i < (width / 16); i++) {
|
||||
for (k = 0; k < 8; k++) {
|
||||
for (j = 0; j < height; j++) {
|
||||
*uncptr0++ = *uncptr1;
|
||||
uncptr1 += 8;
|
||||
static void bitplanetochunky(uint16 *w, uint8 colorDepth, uint8 *&dst) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
byte color1 = 0;
|
||||
byte color2 = 0;
|
||||
for (int p = 0; p < 5; ++p) {
|
||||
if (w[p] & 0x8000) {
|
||||
color1 |= 1 << p;
|
||||
}
|
||||
uncptr2++;
|
||||
uncptr1 = uncptr2;
|
||||
}
|
||||
uncptr3 += (height * 8);
|
||||
uncptr2 = uncptr3;
|
||||
uncptr1 = uncptr2;
|
||||
}
|
||||
length *= 8;
|
||||
cliplength = 0;
|
||||
while(1) {
|
||||
if (length == 1) {
|
||||
*dst++ = 0xFF;
|
||||
*dst++ = *uncbuffer;
|
||||
cliplength += 2;
|
||||
break;
|
||||
}
|
||||
x = *uncbuffer++;
|
||||
y = *uncbuffer++;
|
||||
length -= 2;
|
||||
if (x == y) {
|
||||
n = 1;
|
||||
y = *uncbuffer++;
|
||||
if (length == 0) {
|
||||
*dst++ = n;
|
||||
*dst++ = x;
|
||||
cliplength += 2;
|
||||
break;
|
||||
if (w[p] & 0x4000) {
|
||||
color2 |= 1 << p;
|
||||
}
|
||||
length--;
|
||||
while (x == y) {
|
||||
n++;
|
||||
y = *uncbuffer++;
|
||||
if (length == 0)
|
||||
break;
|
||||
length--;
|
||||
if(n == 127)
|
||||
break;
|
||||
}
|
||||
*dst++ = n;
|
||||
*dst++ = x;
|
||||
cliplength += 2;
|
||||
uncbuffer--;
|
||||
if (length == 0)
|
||||
break;
|
||||
length++;
|
||||
w[p] <<= 2;
|
||||
}
|
||||
if (colorDepth > 4) {
|
||||
*dst++ = color1;
|
||||
*dst++ = color2;
|
||||
} else {
|
||||
n =- 1;
|
||||
uncptr0 = dst;
|
||||
dst++;
|
||||
*dst++ = x;
|
||||
cliplength += 2;
|
||||
x = y;
|
||||
y = *uncbuffer++;
|
||||
if (length == 0) {
|
||||
*uncptr0 = n;
|
||||
break;
|
||||
}
|
||||
length--;
|
||||
while (x != y) {
|
||||
if (n == -127)
|
||||
break;
|
||||
n--;
|
||||
*dst++ = x;
|
||||
cliplength++;
|
||||
x = y;
|
||||
y = *uncbuffer++;
|
||||
if (length == 0)
|
||||
break;
|
||||
length--;
|
||||
}
|
||||
*uncptr0 = n;
|
||||
if (length == 0)
|
||||
break;
|
||||
uncbuffer -= 2;
|
||||
length += 2;
|
||||
*dst++ = (color1 << 4) | color2;
|
||||
}
|
||||
}
|
||||
|
||||
free(free_uncbuffer);
|
||||
free(free_uncbfrout);
|
||||
}
|
||||
|
||||
byte *AGOSEngine::convertclip(const byte *src, uint height, uint width, byte flags) {
|
||||
static void convertcompressedclip(const byte *src, byte *dst, uint8 colorDepth, uint16 height, uint16 width) {
|
||||
const byte *plane[kMaxColorDepth];
|
||||
byte *uncptr[kMaxColorDepth];
|
||||
uint32 length, i, j;
|
||||
uint16 w[kMaxColorDepth];
|
||||
|
||||
byte *uncbfrout = (byte *)malloc(width * height);
|
||||
|
||||
length = (width + 15) / 16 * height;
|
||||
|
||||
for (i = 0; i < colorDepth; ++i) {
|
||||
plane[i] = src + READ_BE_UINT16(src + i * 4) + READ_BE_UINT16(src + i * 4 + 2);
|
||||
uncptr[i] = (uint8 *)malloc(length * 2);
|
||||
uncompressplane(plane[i], uncptr[i], length);
|
||||
plane[i] = uncptr[i];
|
||||
}
|
||||
|
||||
byte *uncbfroutptr = uncbfrout;
|
||||
for (i = 0; i < length; ++i) {
|
||||
for (j = 0; j < colorDepth; ++j) {
|
||||
w[j] = READ_BE_UINT16(plane[j]); plane[j] += 2;
|
||||
}
|
||||
bitplanetochunky(w, colorDepth, uncbfroutptr);
|
||||
}
|
||||
|
||||
uncbfroutptr = uncbfrout;
|
||||
const int chunkSize = colorDepth > 4 ? 16 : 8;
|
||||
for (i = 0; i < width / 16; ++i) {
|
||||
for (j = 0; j < height; ++j) {
|
||||
memcpy(dst + width * chunkSize / 16 * j + chunkSize * i, uncbfroutptr, chunkSize);
|
||||
uncbfroutptr += chunkSize;
|
||||
}
|
||||
}
|
||||
|
||||
free(uncbfrout);
|
||||
for (i = 0; i < colorDepth; ++i) {
|
||||
free(uncptr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
byte *AGOSEngine::convertclip(const byte *src, bool is32Colors, uint height, uint width, byte flags) {
|
||||
uint8 colorDepth = is32Colors ? 5 : 4;
|
||||
|
||||
uint32 length, i, j;
|
||||
uint16 word1, word2, word3, word4;
|
||||
byte outbyte, outbyte1;
|
||||
|
||||
free(_planarBuf);
|
||||
_planarBuf = (byte *)malloc(width * height);
|
||||
byte *dst = _planarBuf;
|
||||
|
||||
if (flags & 0x80) {
|
||||
convertcompressedclip(src, dst, height, width);
|
||||
convertcompressedclip(src, dst, colorDepth, height, width);
|
||||
} else {
|
||||
width /= 16;
|
||||
length = height * width;
|
||||
length = (width + 15) / 16 * height;
|
||||
for (i = 0; i < length; i++) {
|
||||
word1 = READ_BE_UINT16(src); src += 2;
|
||||
word2 = READ_BE_UINT16(src); src += 2;
|
||||
word3 = READ_BE_UINT16(src); src += 2;
|
||||
word4 = READ_BE_UINT16(src); src += 2;
|
||||
for (j = 0; j < 8; j++) {
|
||||
outbyte = ((word1 / 32768) + ((word2 / 32768) * 2) + ((word3 / 32768) * 4) + ((word4 / 32768) * 8));
|
||||
word1 <<= 1;
|
||||
word2 <<= 1;
|
||||
word3 <<= 1;
|
||||
word4 <<= 1;
|
||||
outbyte1 = ((word1 / 32768) + ((word2 / 32768) * 2) + ((word3 / 32768) * 4) + ((word4 / 32768) * 8));
|
||||
word1 <<= 1;
|
||||
word2 <<= 1;
|
||||
word3 <<= 1;
|
||||
word4 <<= 1;
|
||||
*dst++ = (outbyte * 16 + outbyte1);
|
||||
uint16 w[kMaxColorDepth];
|
||||
for (j = 0; j < colorDepth; ++j) {
|
||||
w[j] = READ_BE_UINT16(src); src += 2;
|
||||
}
|
||||
bitplanetochunky(w, colorDepth, dst);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,24 +541,38 @@ byte *AGOSEngine::vc10_uncompressFlip(const byte *src, uint w, uint h) {
|
||||
}
|
||||
|
||||
byte *AGOSEngine::vc10_flip(const byte *src, uint w, uint h) {
|
||||
w *= 8;
|
||||
|
||||
byte *dstPtr;
|
||||
uint i;
|
||||
|
||||
dstPtr = _videoBuf1 + w;
|
||||
if (getFeatures() & GF_32COLOR) {
|
||||
w *= 16;
|
||||
dstPtr = _videoBuf1 + w;
|
||||
|
||||
do {
|
||||
byte *dst = dstPtr;
|
||||
for (i = 0; i != w; ++i) {
|
||||
byte b = src[i];
|
||||
b = (b >> 4) | (b << 4);
|
||||
*--dst = b;
|
||||
}
|
||||
do {
|
||||
byte *dst = dstPtr;
|
||||
for (i = 0; i != w; ++i) {
|
||||
*--dst = src[i];
|
||||
}
|
||||
|
||||
src += w;
|
||||
dstPtr += w;
|
||||
} while (--h);
|
||||
src += w;
|
||||
dstPtr += w;
|
||||
} while (--h);
|
||||
} else {
|
||||
w *= 8;
|
||||
dstPtr = _videoBuf1 + w;
|
||||
|
||||
do {
|
||||
byte *dst = dstPtr;
|
||||
for (i = 0; i != w; ++i) {
|
||||
byte b = src[i];
|
||||
b = (b >> 4) | (b << 4);
|
||||
*--dst = b;
|
||||
}
|
||||
|
||||
src += w;
|
||||
dstPtr += w;
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
return _videoBuf1;
|
||||
}
|
||||
@ -583,10 +597,6 @@ void AGOSEngine::vc10_draw() {
|
||||
state.palette = 0;
|
||||
}
|
||||
|
||||
if (getFeatures() & GF_32COLOR) {
|
||||
state.palette = 0;
|
||||
}
|
||||
|
||||
state.x = (int16)vcReadNextWord();
|
||||
state.x -= _scrollX;
|
||||
|
||||
@ -617,15 +627,29 @@ void AGOSEngine::vc10_draw() {
|
||||
if (height == 0 || width == 0)
|
||||
return;
|
||||
|
||||
if (getFeatures() & GF_PLANAR) {
|
||||
state.depack_src = convertclip(state.depack_src, height, width * 16, flags);
|
||||
}
|
||||
|
||||
if (_dumpImages)
|
||||
dumpSingleBitmap(_vgaCurZoneNum, state.image, state.depack_src, width, height,
|
||||
state.palette);
|
||||
// Check if image is compressed
|
||||
if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
||||
if (getFeatures() & GF_PLANAR) {
|
||||
bool is32Colors = false;
|
||||
if (getGameType() == GType_SIMON1) {
|
||||
if (((_lockWord & 0x20) && !state.palette) || state.palette == 0xC0 ||
|
||||
(getFeatures() & GF_32COLOR)) {
|
||||
is32Colors = true;
|
||||
}
|
||||
}
|
||||
|
||||
state.depack_src = convertclip(state.depack_src, is32Colors, height, width * 16, flags);
|
||||
|
||||
// converted planar clip is already uncompressed
|
||||
if (state.flags & kDFCompressedFlip) {
|
||||
state.flags &= ~kDFCompressedFlip;
|
||||
state.flags |= kDFFlip;
|
||||
}
|
||||
if (state.flags & kDFCompressed) {
|
||||
state.flags &= ~kDFCompressed;
|
||||
}
|
||||
} else if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
||||
if (flags & 0x80) {
|
||||
state.flags |= kDFCompressed;
|
||||
}
|
||||
@ -674,6 +698,8 @@ void AGOSEngine::vc10_draw() {
|
||||
|
||||
if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
||||
drawImages_Feeble(&state);
|
||||
} else if (getFeatures() & GF_32COLOR) {
|
||||
drawImages_Amiga(&state);
|
||||
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
|
||||
drawImages_Simon(&state);
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user