From eaeada78acef36750c89a653df4a38b7f4aaf4cc Mon Sep 17 00:00:00 2001 From: Travis Howell Date: Fri, 9 Feb 2007 00:35:57 +0000 Subject: 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 --- engines/agos/agos.h | 3 +- engines/agos/gfx.cpp | 103 ++++++++++++++------ engines/agos/res_ami.cpp | 246 +++++++++++++++-------------------------------- engines/agos/vga.cpp | 72 +++++++++----- 4 files changed, 202 insertions(+), 222 deletions(-) (limited to 'engines/agos') diff --git a/engines/agos/agos.h b/engines/agos/agos.h index ad46fe572d..51d4f4b77a 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -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); diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp index 644747012a..f5727b5b90 100644 --- a/engines/agos/gfx.cpp +++ b/engines/agos/gfx.cpp @@ -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]; diff --git a/engines/agos/res_ami.cpp b/engines/agos/res_ami.cpp index 6afe08e61e..c16b907f01 100644 --- a/engines/agos/res_ami.cpp +++ b/engines/agos/res_ami.cpp @@ -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; + if (w[p] & 0x4000) { + color2 |= 1 << p; + } + w[p] <<= 2; + } + if (colorDepth > 4) { + *dst++ = color1; + *dst++ = color2; + } else { + *dst++ = (color1 << 4) | color2; } - uncptr3 += (height * 8); - uncptr2 = uncptr3; - uncptr1 = uncptr2; } - length *= 8; - cliplength = 0; - while(1) { - if (length == 1) { - *dst++ = 0xFF; - *dst++ = *uncbuffer; - cliplength += 2; - break; +} + +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; } - x = *uncbuffer++; - y = *uncbuffer++; - length -= 2; - if (x == y) { - n = 1; - y = *uncbuffer++; - if (length == 0) { - *dst++ = n; - *dst++ = x; - cliplength += 2; - break; - } - 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++; - } 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; + 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(free_uncbuffer); - free(free_uncbfrout); + free(uncbfrout); + for (i = 0; i < colorDepth; ++i) { + free(uncptr[i]); + } } -byte *AGOSEngine::convertclip(const byte *src, uint height, uint width, byte flags) { +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); } } diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp index 93aeda6c5e..0ec2c5004f 100644 --- a/engines/agos/vga.cpp +++ b/engines/agos/vga.cpp @@ -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 { -- cgit v1.2.3