aboutsummaryrefslogtreecommitdiff
path: root/scumm
diff options
context:
space:
mode:
authorGregory Montoir2004-09-03 17:27:40 +0000
committerGregory Montoir2004-09-03 17:27:40 +0000
commit54a84da97c1aab75ed1cec46f65691a00d4ff87a (patch)
treea80f131d1acfd355c002b4bb15dbc26998952100 /scumm
parent08fc27b764dcf93f5d052912d9ab5a241e2b7602 (diff)
downloadscummvm-rg350-54a84da97c1aab75ed1cec46f65691a00d4ff87a.tar.gz
scummvm-rg350-54a84da97c1aab75ed1cec46f65691a00d4ff87a.tar.bz2
scummvm-rg350-54a84da97c1aab75ed1cec46f65691a00d4ff87a.zip
preliminar Wiz images support (HE 72)
svn-id: r14875
Diffstat (limited to 'scumm')
-rw-r--r--scumm/gfx.cpp123
-rw-r--r--scumm/gfx.h3
-rw-r--r--scumm/intern.h21
-rw-r--r--scumm/palette.cpp21
-rw-r--r--scumm/script_v72he.cpp140
-rw-r--r--scumm/scumm.h4
6 files changed, 278 insertions, 34 deletions
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);