diff options
author | athrxx | 2019-11-17 01:46:17 +0100 |
---|---|---|
committer | athrxx | 2019-12-18 20:50:42 +0100 |
commit | 1db3ec1f712ba75e04911e0a936f873998f9d1c9 (patch) | |
tree | 1c51fcc87265e54c28a1e8f30337d845819e62c4 | |
parent | 7cae73aae3775e82ca8e78abe7809d125b67ccc3 (diff) | |
download | scummvm-rg350-1db3ec1f712ba75e04911e0a936f873998f9d1c9.tar.gz scummvm-rg350-1db3ec1f712ba75e04911e0a936f873998f9d1c9.tar.bz2 scummvm-rg350-1db3ec1f712ba75e04911e0a936f873998f9d1c9.zip |
KYRA: (EOB/PC98) - add bitmap decoders
The PC98 version has a modified version of decodeFrame4() and also requires planar decoding (similiar to Amiga).
-rw-r--r-- | engines/kyra/graphics/screen_eob.cpp | 144 | ||||
-rw-r--r-- | engines/kyra/graphics/screen_eob.h | 14 | ||||
-rw-r--r-- | engines/kyra/sequence/sequences_eob.cpp | 2 |
3 files changed, 122 insertions, 38 deletions
diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp index 785317ba23..882c45c5d0 100644 --- a/engines/kyra/graphics/screen_eob.cpp +++ b/engines/kyra/graphics/screen_eob.cpp @@ -63,18 +63,10 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system, _cgaMappingDefault = 0; _cgaDitheringTables[0] = _cgaDitheringTables[1] = 0; _useHiResEGADithering = _dualPaletteMode = false; + _cpsFileExt = 0; + _decodeTempBuffer = 0; for (int i = 0; i < 10; ++i) - _palette16c[i] = 0; - - _cpsFilePattern = "%s.CPS"; - if (_vm->gameFlags().platform == Common::kPlatformFMTowns) { - _cpsFilePattern = "%s.SHP"; - } else if (_vm->game() == GI_EOB1) { - if (_vm->gameFlags().platform == Common::kPlatformPC98) - _cpsFilePattern = "%s.BIN"; - else if (_renderMode == Common::kRenderEGA || _renderMode == Common::kRenderCGA) - _cpsFilePattern = "%s.EGA"; - } + _palette16c[i] = 0; } Screen_EoB::~Screen_EoB() { @@ -86,6 +78,7 @@ Screen_EoB::~Screen_EoB() { delete[] _egaDitheringTempPage; delete[] _cgaDitheringTables[0]; delete[] _cgaDitheringTables[1]; + delete[] _decodeTempBuffer; } bool Screen_EoB::init() { @@ -132,6 +125,20 @@ bool Screen_EoB::init() { _palette16c[i] = pal16c + i * 48; } + static const char *cpsExt[] = { "CPS", "EGA", "SHP", "BIN" }; + int ci = 0; + if (_vm->game() == GI_EOB1) { + if (_vm->gameFlags().platform == Common::kPlatformPC98) { + _decodeTempBuffer = new uint8[2048]; + ci = 3; + } else if (_renderMode == Common::kRenderEGA || _renderMode == Common::kRenderCGA) { + ci = 1; + } + } else if (_vm->gameFlags().platform == Common::kPlatformFMTowns) { + ci = 2; + } + _cpsFileExt = cpsExt[ci]; + return true; } return false; @@ -251,7 +258,22 @@ void Screen_EoB::loadShapeSetBitmap(const char *file, int tempPage, int destPage } void Screen_EoB::loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip) { - Screen::loadBitmap(filename, tempPage, dstPage, pal); + if (_use16ColorMode) { + Common::SeekableReadStream *str = _vm->resource()->createReadStream(filename); + if (!str) + error("Screen_EoB::loadBitmap(): Failed to load file '%s'", filename); + str->skip(2); + uint16 imgSize = str->readUint16LE(); + assert(imgSize == str->size() - 4); + loadFileDataToPage(str, tempPage, imgSize); + delete str; + + decodeBIN(_pagePtrs[tempPage], _pagePtrs[dstPage], imgSize); + if (!skip) + decodePC98PlanarBitmap(dstPage, tempPage); + } else { + Screen::loadBitmap(filename, tempPage, dstPage, pal); + } if (_isAmiga && !skip) { Common::SeekableReadStream *str = _vm->resource()->createReadStream(filename); @@ -278,7 +300,7 @@ void Screen_EoB::loadBitmap(const char *filename, int tempPage, int dstPage, Pal } void Screen_EoB::loadEoBBitmap(const char *file, const uint8 *cgaMapping, int tempPage, int destPage, int convertToPage) { - Common::String tmp = Common::String::format(_cpsFilePattern, file); + Common::String tmp = Common::String::format("%s.%s", file, _cpsFileExt); Common::SeekableReadStream *s = _vm->resource()->createReadStream(tmp); bool loadAlternative = false; @@ -288,14 +310,6 @@ void Screen_EoB::loadEoBBitmap(const char *file, const uint8 *cgaMapping, int te s->read(_shpBuffer, s->size()); decodeSHP(_shpBuffer, destPage); - } if (_vm->gameFlags().platform == Common::kPlatformPC98) { - if (!s) - error("Screen_EoB::loadEoBBitmap(): Failed to load file '%s'", file); - s->skip(2); - uint16 imgSize = s->readUint16LE(); - loadFileDataToPage(s, tempPage, s->size() - 4); - decodeBIN(_pagePtrs[tempPage], _pagePtrs[destPage], imgSize); - } else if (s) { // This additional check is necessary since some localized versions of EOB II seem to contain invalid (size zero) cps files if (s->size() == 0) { @@ -1553,6 +1567,84 @@ void Screen_EoB::shadeRect(int x1, int y1, int x2, int y2, int shadingLevel) { _16bitShadingLevel = l; } +void Screen_EoB::loadPC98Palette(int palID, Palette &dest) { + if (!_palette16c[palID]) + return; + loadPalette(_palette16c[palID], dest, 48); +} + +void Screen_EoB::decodeBIN(const uint8 *src, uint8 *dst, uint16 inSize) { + const uint8 *end = src + inSize; + memset(_decodeTempBuffer, 0, 2048); + int tmpDstOffs = 0; + + while (src < end) { + uint8 code = *src++; + if (!(code & 0x80)) { + int offs = code << 4; + code = *src++; + offs |= (code >> 4); + int len = (code & 0x0F) + 2; + int tmpSrcOffs = (tmpDstOffs - offs) & 0x7FF; + const uint8 *tmpSrc2 = dst; + + for (int len2 = len; len2; len2--) { + *dst++ = _decodeTempBuffer[tmpSrcOffs++]; + tmpSrcOffs &= 0x7FF; + } + + while (len--) { + _decodeTempBuffer[tmpDstOffs++] = *tmpSrc2++; + tmpDstOffs &= 0x7FF; + } + + } else if (code & 0x40) { + int len = code & 7; + if (code & 0x20) + len = (len << 8) | *src++; + len += 2; + + int planes = ((code >> 3) & 3) + 1; + while (len--) { + for (int i = 0; i < planes; ++i) { + *dst++ = _decodeTempBuffer[tmpDstOffs++] = src[i]; + tmpDstOffs &= 0x7FF; + } + } + src += planes; + } else { + for (int len = (code & 0x3F) + 1; len; len--) { + *dst++ = _decodeTempBuffer[tmpDstOffs++] = *src++; + tmpDstOffs &= 0x7FF; + } + } + } +} + +void Screen_EoB::decodePC98PlanarBitmap(int srcDstPage, int tempPage) { + assert(tempPage != srcDstPage); + copyPage(srcDstPage, tempPage); + const uint8 *src = getCPagePtr(tempPage); + uint8 *dst1 = _pagePtrs[srcDstPage]; + uint8 *dst2 = _pagePtrs[srcDstPage] + 4; + uint16 len = (SCREEN_W * SCREEN_H) >> 3; + while (len--) { + for (int i = 0; i < 4; ++i) { + uint8 col1 = 0; + uint8 col2 = 0; + for (int ii = 0; ii < 4; ++ii) { + col1 |= ((src[ii] >> (7 - i)) & 1) << ii; + col2 |= ((src[ii] >> (3 - i)) & 1) << ii; + } + *dst1++ = col1; + *dst2++ = col2; + } + src += 4; + dst1 += 4; + dst2 += 4; + } +} + static uint32 _decodeFrameAmiga_x = 0; bool decodeFrameAmiga_readNextBit(const uint8 *&data, uint32 &code, uint32 &chk) { @@ -1675,16 +1767,6 @@ void Screen_EoB::loadSpecialAmigaCPS(const char *fileName, int destPage, bool is convertAmigaGfx(_pagePtrs[destPage], 320, 200); } -void Screen_EoB::load16ColPalette(int palID, Palette &dest) { - if (!_palette16c[palID]) - return; - loadPalette(_palette16c[palID], dest, 48); -} - -void Screen_EoB::decodeBIN(const uint8 *src, uint8 *dst, uint32 dstSize) { - -} - void Screen_EoB::setupDualPalettesSplitScreen(Palette &top, Palette &bottom) { // The original supports simultaneous fading of both palettes, but doesn't make any use of that // feature. The fade rate is always set to 0. So I see no need to implement that. diff --git a/engines/kyra/graphics/screen_eob.h b/engines/kyra/graphics/screen_eob.h index edc49e144a..aaae79a13c 100644 --- a/engines/kyra/graphics/screen_eob.h +++ b/engines/kyra/graphics/screen_eob.h @@ -90,13 +90,15 @@ public: void convertToHiColor(int page); void shadeRect(int x1, int y1, int x2, int y2, int shadingLevel); - // Amiga specific - void loadSpecialAmigaCPS(const char *fileName, int destPage, bool isGraphics); - // PC-98 specific - void load16ColPalette(int palID, Palette &dest); - void decodeBIN(const uint8 *src, uint8 *dst, uint32 dstSize); + void loadPC98Palette(int palID, Palette &dest); + void decodeBIN(const uint8 *src, uint8 *dst, uint16 inSize); + void decodePC98PlanarBitmap(int srcDstPage, int tempPage); + uint8 *_decodeTempBuffer; + + // Amiga specific + void loadSpecialAmigaCPS(const char *fileName, int destPage, bool isGraphics); // This is a simple way of emulating the Amiga copper list palette magic for more than 32 colors. // I use colors 32 to 63 for these extra colors (which the Amiga copper sends to the color // registers on the fly at vertical beam position 120). @@ -143,7 +145,7 @@ private: // hard coded 16 color palettes for PC98 version of EOB1 const uint8 *_palette16c[10]; - const char *_cpsFilePattern; + const char *_cpsFileExt; const uint16 _cursorColorKey16Bit; diff --git a/engines/kyra/sequence/sequences_eob.cpp b/engines/kyra/sequence/sequences_eob.cpp index e091530807..9139a25f04 100644 --- a/engines/kyra/sequence/sequences_eob.cpp +++ b/engines/kyra/sequence/sequences_eob.cpp @@ -935,7 +935,7 @@ void EoBIntroPlayer::loadAndSetPalette(const char *dosPaletteFile, int pc98Palet if (_vm->gameFlags().platform == Common::kPlatformDOS) _screen->loadPalette(dosPaletteFile, _screen->getPalette(0)); else if (_vm->gameFlags().platform == Common::kPlatformPC98) - _screen->load16ColPalette(pc98PaletteID, _screen->getPalette(0)); + _screen->loadPC98Palette(pc98PaletteID, _screen->getPalette(0)); _screen->getPalette(0).fill(0, 1, 0); _screen->setScreenPalette(_screen->getPalette(0)); |