diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp index 7875e9abdee..349a239f518 100644 --- a/scumm/gfx.cpp +++ b/scumm/gfx.cpp @@ -66,7 +66,7 @@ struct TransitionEffect { #ifdef __PALM_OS__ static const TransitionEffect *transitionEffects; #else -static const TransitionEffect transitionEffects[5] = { +static const TransitionEffect transitionEffects[4] = { // Iris effect (looks like an opening/closing camera iris) { 13, // Number of iterations @@ -134,23 +134,6 @@ static const TransitionEffect transitionEffects[5] = { 38, 0, 38, 24, 255, 0, 0, 0 } - }, - - // Inverse iris effect, specially tailored for V2 games - { - 8, // Number of iterations - { - -1, -1, 1, -1, - -1, 1, 1, 1, - -1, -1, -1, 1, - 1, -1, 1, 1 - }, - { - 7, 7, 32, 7, - 7, 8, 32, 8, - 7, 8, 7, 8, - 32, 7, 32, 8 - } } }; #endif @@ -993,7 +976,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi // dificult to draw only parts of a room/object. We handle the V2 graphics // differently from all other (newer) graphic formats for this reason. // - if (_vm->_features & GF_AFTER_V2) { + if ((_vm->_features & GF_AFTER_V2) && !(_vm->_features & GF_AFTER_V1)) { if (vs->alloctwobuffers) bgbak_ptr = _vm->getResourceAddress(rtBuffer, vs->number + 5) + (y * _numStrips + x) * 8; @@ -1138,7 +1121,9 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi else bgbak_ptr = backbuff_ptr; - if (!(_vm->_features & GF_AFTER_V2)) { + if (_vm->_features & GF_AFTER_V1) { + drawStripC64Background(bgbak_ptr, stripnr, height); + } else if (!(_vm->_features & GF_AFTER_V2)) { if (_vm->_features & GF_16COLOR) { decodeStripEGA(bgbak_ptr, smap_ptr + READ_LE_UINT16(smap_ptr + stripnr * 2 + 2), height); } else if (_vm->_features & GF_SMALL_HEADER) { @@ -1166,7 +1151,10 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi } CHECK_HEAP; - if (_vm->_features & GF_AFTER_V2) { + if (_vm->_features & GF_AFTER_V1) { + mask_ptr = _vm->getResourceAddress(rtBuffer, 9) + y * _numStrips + x + _imgBufOffs[1]; +// drawStripC64Mask(mask_ptr, stripnr, height); + } else if (_vm->_features & GF_AFTER_V2) { // Do nothing here for V2 games - zplane was handled already. } else if (flag & dbDrawMaskOnAll) { // Sam & Max uses dbDrawMaskOnAll for things like the inventory @@ -1351,6 +1339,59 @@ StripTable *Gdi::generateStripTable(const byte *src, int width, int height, Stri return table; } +void Gdi::drawStripC64Background(byte *dst, int stripnr, int height) { + for(int y = 0; y < (height >> 3); y++) { + _C64Colors[3] = (_C64ColorMap[y + stripnr * (height >> 3)] & 7); + for(int i = 0; i < 8; i++) { + for(int j = 7; j >= 0; j--) { + *(dst + (7 - j) + stripnr * 8 + (y * 8 + i) * _vm->_screenWidth) = + _C64Colors[((_C64CharMap[_C64PicMap[y + stripnr * (height >> 3)] * 8 + i] >> (j & 6)) & 3)]; + } + } + } +} + +void Gdi::drawStripC64Mask(byte *dst, int stripnr, int height) { + for(int y = 0; y < (height / 8); y++) { + for(int i = 0; i < 8; i++) { + for(int j = 7; j >= 0; j--) { + *(dst + (7 - j) + stripnr * 8 + (y * 8 + i) * _vm->_screenWidth) = + ((_C64MaskChar[_C64MaskMap[y + stripnr * (height >> 3)] * 8 + i] >> (j & 6)) & 3); + } + } + } +} + +void Gdi::decodeC64Gfx(byte *src, byte *dst, int size) { + int x, z; + byte color, run, common[4]; + + for(z = 0; z < 4; z++) { + common[z] = *src++; + } + + x = 0; + while(x < size){ + color = *src++; + if (color < 0x40) { + for (z = 0; z <= color; z++) { + dst[x++] = *src++; + } + } else if (color < 0x80) { + color &= 0x3F; + run = *src++; + for (z = 0; z <= color; z++) { + dst[x++] = run; + } + } else { + run = common[(color >> 5) & 3]; + color &= 0x1F; + for (z = 0; z <= color; z++) { + dst[x++] = run; + } + } + } +} void Gdi::decodeStripEGA(byte *dst, const byte *src, int height) { byte color = 0; @@ -2088,14 +2129,6 @@ void Scumm::fadeIn(int effect) { case 2: case 3: case 4: - case 5: - // Some of the transition effects won't work properly unless - // the screen is marked as clean first. At first I thought I - // could safely do this every time fadeIn() was called, but - // that broke the FOA intro. Probably other things as well. - // - // Hopefully it's safe to do it at this point, at least. - virtscr[0].setDirtyRange(0, 0); transitionEffect(effect - 1); break; case 128: @@ -2140,7 +2173,6 @@ void Scumm::fadeOut(int effect) { case 2: case 3: case 4: - case 5: transitionEffect(effect - 1); break; case 128: @@ -2214,8 +2246,6 @@ void Scumm::transitionEffect(int a) { continue; if (b > bottom) b = bottom; - if (t < 0) - t = 0; virtscr[0].tdirty[l] = t << 3; virtscr[0].bdirty[l] = (b + 1) << 3; } @@ -2471,6 +2501,25 @@ void Scumm::setupEGAPalette() { setPalColor(15, 252, 252, 252); } +void Scumm::setupC64Palette() { + setPalColor( 0, 0, 0, 0); + setPalColor( 1, 252, 252, 252); + setPalColor( 2, 204, 0, 0); + setPalColor( 3, 0, 252, 204); + setPalColor( 4, 252, 0, 252); + setPalColor( 5, 0, 204, 0); + setPalColor( 6, 0, 0, 204); + setPalColor( 7, 252, 252, 252); + setPalColor( 8, 252, 136, 0); + setPalColor( 9, 136, 68, 0); + setPalColor(10, 252, 136, 136); + setPalColor(11, 68, 68, 68); + setPalColor(12, 136, 136, 136); + setPalColor(13, 136, 252, 136); + setPalColor(14, 136, 136, 252); + setPalColor(15, 204, 204, 204); +} + void Scumm::setPaletteFromPtr(const byte *ptr) { int i; byte *dest, r, g, b; diff --git a/scumm/gfx.h b/scumm/gfx.h index cae76988e49..f10ef8f6131 100644 --- a/scumm/gfx.h +++ b/scumm/gfx.h @@ -122,9 +122,15 @@ protected: bool _zbufferDisabled; + byte _C64Colors[4], _C64CharMap[256 * 8], _C64PicMap[4096], _C64ColorMap[4096]; + byte _C64MaskMap[4096], _C64MaskChar[4096]; + /* Bitmap decompressors */ bool decompressBitmap(byte *bgbak_ptr, const byte *src, int numLinesToProcess); void decodeStripEGA(byte *dst, const byte *src, int height); + void decodeC64Gfx(byte *src, byte *dst, int size); + void drawStripC64Background(byte *dst, int stripnr, int height); + void drawStripC64Mask(byte *dst, int stripnr, int height); void unkDecodeA(byte *dst, const byte *src, int height); void unkDecodeA_trans(byte *dst, const byte *src, int height); void unkDecodeB(byte *dst, const byte *src, int height); diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp index f4f58878e44..8dbb726f2a4 100644 --- a/scumm/saveload.cpp +++ b/scumm/saveload.cpp @@ -162,7 +162,10 @@ bool Scumm::loadState(int slot, bool compat, SaveFileManager *mgr) { _completeScreenRedraw = true; - if (_features & GF_16COLOR) { + if (_features & GF_AFTER_V1) { + setupC64Palette(); + setDirtyColors(0, 15); + } else if (_features & GF_16COLOR) { // HACK: There was a time when ScummVM didn't store the // palette in _currentPalette for 16-color games. To avoid // breaking savegame compatibility, always set up the default diff --git a/scumm/scumm.h b/scumm/scumm.h index 57b891fb996..3afc33d491a 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -841,6 +841,7 @@ protected: const byte *getPalettePtr(); void setupEGAPalette(); + void setupC64Palette(); void setPalette(int pal); void setPaletteFromPtr(const byte *ptr); void setPaletteFromRes(); diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp index 079605b58da..911e0706e9e 100644 --- a/scumm/scummvm.cpp +++ b/scumm/scummvm.cpp @@ -766,7 +766,11 @@ void Scumm::scummInit() { initScreens(0, 16, _screenWidth, 144); } - if (_features & GF_16COLOR) { + if (_features & GF_AFTER_V1) { + for (i = 0; i < 16; i++) + _shadowPalette[i] = i; + setupC64Palette(); + } else if (_features & GF_16COLOR) { for (i = 0; i < 16; i++) _shadowPalette[i] = i; setupEGAPalette(); @@ -1397,7 +1401,10 @@ void Scumm::initRoomSubBlocks() { else rmhd = (const RoomHeader *)findResourceData(MKID('RMHD'), roomptr); - if (_features & GF_AFTER_V8) { + if (_features & GF_AFTER_V1) { + _roomWidth = roomptr[4] * 8; + _roomHeight = roomptr[5] * 8; + } else if (_features & GF_AFTER_V8) { _roomWidth = READ_LE_UINT32(&(rmhd->v8.width)); _roomHeight = READ_LE_UINT32(&(rmhd->v8.height)); } else if (_features & GF_AFTER_V7) { @@ -1411,7 +1418,17 @@ void Scumm::initRoomSubBlocks() { // // Find the room image data // - if (_features & GF_OLD_BUNDLE) { + if (_features & GF_AFTER_V1) { + _IM00_offs = 0; + for(i = 0; i < 4; i++){ + gdi._C64Colors[i] = roomptr[6 + i]; + } + gdi.decodeC64Gfx(roomptr + READ_LE_UINT16(roomptr + 10), gdi._C64CharMap, 256 * 8); + gdi.decodeC64Gfx(roomptr + READ_LE_UINT16(roomptr + 12), gdi._C64PicMap, roomptr[4] * roomptr[5]); + gdi.decodeC64Gfx(roomptr + READ_LE_UINT16(roomptr + 14), gdi._C64ColorMap, roomptr[4] * roomptr[5]); + gdi.decodeC64Gfx(roomptr + READ_LE_UINT16(roomptr + 16), gdi._C64MaskMap, roomptr[4] * roomptr[5]); + gdi.decodeC64Gfx(roomptr + READ_LE_UINT16(roomptr + 18), gdi._C64MaskChar, READ_LE_UINT16(roomptr + 18)); + } else if (_features & GF_OLD_BUNDLE) { _IM00_offs = READ_LE_UINT16(roomptr + 0x0A); if (_features & GF_AFTER_V2) _roomStrips = gdi.generateStripTable(roomptr + _IM00_offs, _roomWidth, _roomHeight, _roomStrips);