From 54a84da97c1aab75ed1cec46f65691a00d4ff87a Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Fri, 3 Sep 2004 17:27:40 +0000 Subject: preliminar Wiz images support (HE 72) svn-id: r14875 --- scumm/gfx.cpp | 123 ++++++++++++++++++++++++++++++++++++++++--- scumm/gfx.h | 3 +- scumm/intern.h | 21 ++++++-- scumm/palette.cpp | 21 ++++---- scumm/script_v72he.cpp | 140 ++++++++++++++++++++++++++++++++++++++++++++----- scumm/scumm.h | 4 +- 6 files changed, 278 insertions(+), 34 deletions(-) (limited to 'scumm') diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp index aa040aad4a..e351a60206 100644 --- a/scumm/gfx.cpp +++ b/scumm/gfx.cpp @@ -1385,16 +1385,127 @@ void Gdi::decompressBMAPbg(byte *dst, int screenwidth, int w, int height, const } } -void Gdi::copyVirtScreenBuffers(int x, int y, int w, int h) { - int rw = w - x + 1; - int rh = h - y + 1; +void Gdi::decompressImageHE(uint8 *dst, int dstWidth, const Common::Rect *dstRect, const uint8 *src, const Common::Rect *srcRect) { + const uint8 *dataPtr, *dataPtrNext; + uint8 *dstPtr, *dstPtrNext; + uint32 code; + uint8 databit; + int h, w, xoff; + uint16 off; + + dstPtr = dst + dstRect->left + dstRect->top * dstWidth; + dataPtr = src; + h = srcRect->top; + while (h--) { + dataPtr += READ_LE_UINT16(dataPtr) + 2; + } + h = srcRect->bottom - srcRect->top; + if (h < 0) + return; + w = srcRect->right - srcRect->left + 1; + if (w <= 0) + return; + + while (1) { + xoff = srcRect->left; + off = READ_LE_UINT16(dataPtr); + w = srcRect->right - srcRect->left + 1; + dstPtrNext = dstWidth + dstPtr; + dataPtrNext = off + 2 + dataPtr; + if (h < 0) + break; + --h; + dataPtr += 2; + if (off == 0) goto dec_next; + + while (xoff > 0) { + code = *dataPtr++; + databit = code & 1; + code >>= 1; + if (databit) { + xoff -= code; + if (xoff < 0) { + code = -xoff; + goto dec_sub1; + } + } else { + databit = code & 1; + code >>= 1; + if (databit) { + ++code; + ++dataPtr; + xoff -= code; + if (xoff < 0) { + code = -xoff; + --dataPtr; + goto dec_sub2; + } + } else { + ++code; + dataPtr += code; + xoff -= code; + if (xoff < 0) { + dataPtr += xoff; + code = -xoff; + goto dec_sub3; + } + } + } + } + + while (w > 0) { + code = *dataPtr++; + databit = code & 1; + code >>= 1; + if (databit) { +dec_sub1: dstPtr += code; + w -= code; + } else { + databit = code & 1; + code >>= 1; + if (databit) { + ++code; +dec_sub2: w -= code; + if (w >= 0) { + memset(dstPtr, *dataPtr++, code); + dstPtr += code; + } else { + code += w; + memset(dstPtr, *dataPtr++, code); + dstPtr += code; + } + } else { + ++code; +dec_sub3: w -= code; + if (w >= 0) { + memcpy(dstPtr, dataPtr, code); + dstPtr += code; + dataPtr += code; + } else { + code += w; + memcpy(dstPtr, dataPtr, code); + dstPtr += code; + dataPtr += code; + } + } + } + } +dec_next: + dataPtr = dataPtrNext; + dstPtr = dstPtrNext; + } +} + +void Gdi::copyVirtScreenBuffers(int x1, int y1, int x2, int y2) { + int rw = x2 - x1 + 1; + int rh = y2 - y1 + 1; byte *src, *dst; - src = (byte *)_vm->virtscr[0].backBuf + (_vm->_screenStartStrip + y * _numStrips) * 8 + x; - dst = (byte *)_vm->virtscr[0].pixels + (_vm->_screenStartStrip + y * _numStrips) * 8 + x; + src = (byte *)_vm->virtscr[0].backBuf + (_vm->_screenStartStrip + y1 * _numStrips) * 8 + x1; + dst = (byte *)_vm->virtscr[0].pixels + (_vm->_screenStartStrip + y1 * _numStrips) * 8 + x1; copyBufferBox(dst, src, rw, rh); - _vm->markRectAsDirty(kMainVirtScreen, x, w, y, h, 0); + _vm->markRectAsDirty(kMainVirtScreen, x1, x2, y1, y2, 0); } /** diff --git a/scumm/gfx.h b/scumm/gfx.h index 53f0979492..e06b1b1be0 100644 --- a/scumm/gfx.h +++ b/scumm/gfx.h @@ -274,7 +274,8 @@ public: int stripnr, int numstrip, StripTable *table); StripTable *generateStripTable(const byte *src, int width, int height, StripTable *table); void drawBMAPBg(const byte *ptr, VirtScreen *vs, int startstrip, int width); - void copyVirtScreenBuffers(int x, int y, int w, int h); + void decompressImageHE(uint8 *dst, int dstWidth, const Common::Rect *dstRect, const uint8 *src, const Common::Rect *srcRect); + void copyVirtScreenBuffers(int x1, int y1, int x2, int y2); void disableZBuffer() { _zbufferDisabled = true; } void enableZBuffer() { _zbufferDisabled = false; } diff --git a/scumm/intern.h b/scumm/intern.h index 64126aa755..ff1e497b74 100644 --- a/scumm/intern.h +++ b/scumm/intern.h @@ -661,14 +661,23 @@ protected: byte data[1]; //14 } GCC_PACK; + struct WizImage { + int resnum; + int x1; + int y1; + int flags; + }; + #if !defined(__GNUC__) #pragma END_PACK_STRUCTS #endif const OpcodeEntryV72he *_opcodesV72he; + WizImage _wizImages[20]; + uint16 _wizImagesNum; public: - ScummEngine_v72he(GameDetector *detector, OSystem *syst, const ScummGameSettings &gs) : ScummEngine_v7he(detector, syst, gs) {} + ScummEngine_v72he(GameDetector *detector, OSystem *syst, const ScummGameSettings &gs) : ScummEngine_v7he(detector, syst, gs), _wizImagesNum(0) {} protected: virtual void setupScummVars(); @@ -677,6 +686,8 @@ protected: virtual void setupOpcodes(); virtual void executeOpcode(byte i); virtual const char *getOpcodeDesc(byte i); + + virtual void redrawBGAreas(); ArrayHeader *defineArray(int array, int type, int dim2start, int dim2end, int dim1start, int dim1end); int readArray(int array, int idx2, int idx1); @@ -687,6 +698,10 @@ protected: int readFileToArray(int slot, int32 size); void writeFileFromArray(int slot, int resID); + void drawWizImage(int restype, int resnum, int x1, int y1, int flags); + void flushWizBuffer(); + void copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, Common::Rect *pr); + /* Version 7 script opcodes */ void o72_pushDWord(); void o72_addMessageToStack(); @@ -707,14 +722,14 @@ protected: void o72_startScript(); void o72_startObject(); void o72_drawObject(); - void o72_unknown62(); + void o72_printWizImage(); void o72_getArrayDimSize(); void o72_getNumFreeArrays(); void o72_pickupObject(); void o72_arrayOps(); void o72_dimArray(); void o72_dim2dimArray(); - void o72_unknownCE(); + void o72_drawWizImage(); void o72_shuffle(); void o72_jumpToScript(); void o72_openFile(); diff --git a/scumm/palette.cpp b/scumm/palette.cpp index d4dba16869..983adf6380 100644 --- a/scumm/palette.cpp +++ b/scumm/palette.cpp @@ -106,19 +106,20 @@ void ScummEngine::setupV1ZakPalette() { setPalColor(16, 255, 85, 255); } -void ScummEngine::setPaletteFromPtr(const byte *ptr) { +void ScummEngine::setPaletteFromPtr(const byte *ptr, int numcolor) { int i; byte *dest, r, g, b; - int numcolor; - if (_features & GF_SMALL_HEADER) { - if (_features & GF_OLD256) - numcolor = 256; - else - numcolor = READ_LE_UINT16(ptr + 6) / 3; - ptr += 8; - } else { - numcolor = getResourceDataSize(ptr) / 3; + if (numcolor < 0) { + if (_features & GF_SMALL_HEADER) { + if (_features & GF_OLD256) + numcolor = 256; + else + numcolor = READ_LE_UINT16(ptr + 6) / 3; + ptr += 8; + } else { + numcolor = getResourceDataSize(ptr) / 3; + } } checkRange(256, 0, numcolor, "Too many colors (%d) in Palette"); diff --git a/scumm/script_v72he.cpp b/scumm/script_v72he.cpp index 5cb7abe7fb..3ce899cc11 100644 --- a/scumm/script_v72he.cpp +++ b/scumm/script_v72he.cpp @@ -168,7 +168,7 @@ void ScummEngine_v72he::setupOpcodes() { /* 60 */ OPCODE(o72_startObject), OPCODE(o72_drawObject), - OPCODE(o72_unknown62), + OPCODE(o72_printWizImage), OPCODE(o72_getArrayDimSize), /* 64 */ OPCODE(o72_getNumFreeArrays), @@ -303,7 +303,7 @@ void ScummEngine_v72he::setupOpcodes() { /* CC */ OPCODE(o6_pickOneOfDefault), OPCODE(o6_stampObject), - OPCODE(o72_unknownCE), + OPCODE(o72_drawWizImage), OPCODE(o6_invalid), /* D0 */ OPCODE(o6_getDateTime), @@ -771,10 +771,9 @@ void ScummEngine_v72he::o72_drawObject() { } } -void ScummEngine_v72he::o72_unknown62() { - int a = pop(); - // unknown62(a, 0, 0, 4); - warning("o72_unknown62 stub (%d)", a); +void ScummEngine_v72he::o72_printWizImage() { + int resnum = pop(); + drawWizImage(rtImage, resnum, 0, 0, 4); } void ScummEngine_v72he::o72_getArrayDimSize() { @@ -935,12 +934,129 @@ void ScummEngine_v72he::o72_dim2dimArray() { defineArray(fetchScriptWord(), data, 0, a, 0, b); } -void ScummEngine_v72he::o72_unknownCE() { - int a = pop(); - int b = pop(); - int c = pop(); - int d = pop(); - debug(1,"o72_unknownCE stub (%d, %d, %d, %d)", d, c, b, a); +void ScummEngine_v72he::drawWizImage(int restype, int resnum, int x1, int y1, int flags) { + const uint8 *dataPtr = getResourceAddress(restype, resnum); + if (dataPtr) { + const uint8 *wizh = findResourceData(MKID('WIZH'), dataPtr); + assert(wizh); + uint32 comp = READ_LE_UINT32(wizh + 0x0); + uint32 width = READ_LE_UINT32(wizh + 0x4); + uint32 height = READ_LE_UINT32(wizh + 0x8); + if (comp != 1) { + warning("%d has invalid compression type %d", resnum, comp); + } + const uint8 *wizd = findResourceData(MKID('WIZD'), dataPtr); + assert(wizd); + if (flags & 1) { + const uint8 *pal = findResourceData(MKID('RGBS'), dataPtr); + assert(pal); + setPaletteFromPtr(pal, 256); + } + if (flags & 2) { + warning("unhandled Wiz image w/ rmap"); + } + if (flags & 4) { + warning("printing Wiz image is unimplemented"); + return; + } + + uint8 *dst; + VirtScreen *pvs = &virtscr[kMainVirtScreen]; + if (flags & 0x10) { + dst = pvs->getPixels(0, pvs->topline); + } else { + dst = pvs->getBackPixels(0, pvs->topline); + } + Common::Rect rScreen(0, 0, pvs->w, pvs->h); + if (flags & 2) { +// warning("unhandled Wiz image w/ rmap"); + } else { + copyWizImage(dst, wizd, pvs->w, pvs->h, x1, y1, width, height, &rScreen); + } + + Common::Rect rImage(x1, y1, x1 + width, y1 + height); + if (rImage.intersects(rScreen)) { + rImage.clip(rScreen); + if (flags & 0x18) { + ++rImage.bottom; + markRectAsDirty(kMainVirtScreen, rImage); + } else { + gdi.copyVirtScreenBuffers(rImage.left, rImage.top, rImage.right - 1, rImage.bottom - 1); + } + } + } +} + +void ScummEngine_v72he::redrawBGAreas() { + ScummEngine_v7he::redrawBGAreas(); + flushWizBuffer(); +} + +void ScummEngine_v72he::flushWizBuffer() { + for (int i = 0; i < _wizImagesNum; ++i) { + WizImage *pwi = &_wizImages[i]; + drawWizImage(rtImage, pwi->resnum, pwi->x1, pwi->y1, pwi->flags); + } + _wizImagesNum = 0; +} + +void ScummEngine_v72he::copyWizImage(uint8 *dst, const uint8 *src, int dst_w, int dst_h, int src_x, int src_y, int src_w, int src_h, Common::Rect *rect) { + Common::Rect r1(0, 0, src_w, src_h), r2(src_x, src_y, src_x + src_w, src_y + src_h); + Common::Rect r3; + int diff; + + if (rect) { + r3 = *rect; + Common::Rect r4(0, 0, dst_w, dst_h); + if (!r3.intersects(r4)) { + return; + } else { + r3.clip(r4); + } + } else { + r3 = Common::Rect(0, 0, dst_w, dst_h); + } + diff = r2.left - r3.left; + if (diff < 0) { + r1.left -= diff; + r2.left -= diff; + } + diff = r2.right - r3.right; + if (diff > 0) { + r1.right -= diff; + r2.right -= diff; + } + diff = r2.top - r3.top; + if (diff < 0) { + r1.top -= diff; + r2.top -= diff; + } + diff = r2.bottom - r3.bottom; + if (diff > 0) { + r1.bottom -= diff; + r2.bottom -= diff; + } + if (r1.isValidRect() && r2.isValidRect()) { + gdi.decompressImageHE(dst, dst_w, &r2, src, &r1); + } +} + +void ScummEngine_v72he::o72_drawWizImage() { + int flags = pop(); + int y1 = pop(); + int x1 = pop(); + int resnum = pop(); + if (_fullRedraw) { + assert(_wizImagesNum < ARRAYSIZE(_wizImages)); + WizImage *pwi = &_wizImages[_wizImagesNum]; + pwi->resnum = resnum; + pwi->x1 = x1; + pwi->y1 = y1; + pwi->flags = flags; + ++_wizImagesNum; + } else { + drawWizImage(rtImage, resnum, x1, y1, flags); + } } void ScummEngine_v72he::shuffleArray(int num, int minIdx, int maxIdx) { diff --git a/scumm/scumm.h b/scumm/scumm.h index 379af8b517..25e44e5fd0 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -907,7 +907,7 @@ protected: void restoreBG(Common::Rect rect, byte backColor = 0); void redrawBGStrip(int start, int num); - void redrawBGAreas(); + virtual void redrawBGAreas(); void cameraMoved(); void setCameraAtEx(int at); @@ -924,7 +924,7 @@ protected: void setupV1ManiacPalette(); void setupV1ZakPalette(); void setPalette(int pal); - void setPaletteFromPtr(const byte *ptr); + void setPaletteFromPtr(const byte *ptr, int numcolor = -1); void setPaletteFromRes(); void setPalColor(int index, int r, int g, int b); void setDirtyColors(int min, int max); -- cgit v1.2.3