From 22b2cfa00255dcb282c88817f5b33c0999473ab7 Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Sat, 18 Sep 2004 00:36:17 +0000 Subject: preliminar AuxQueue support (freddemo intro), some glitches though svn-id: r15149 --- scumm/actor.cpp | 113 ++++++++++++++++++++++++++++++++++++++- scumm/actor.h | 1 + scumm/akos.cpp | 8 +-- scumm/gfx.cpp | 143 ++++++++++++++++++++++++++++++++++++++++++++++++-- scumm/gfx.h | 6 ++- scumm/palette.cpp | 1 - scumm/script_v7he.cpp | 17 ++---- scumm/scumm.cpp | 19 +++++-- scumm/scumm.h | 22 ++++++++ 9 files changed, 302 insertions(+), 28 deletions(-) diff --git a/scumm/actor.cpp b/scumm/actor.cpp index e37456ab40..b4db39afe4 100644 --- a/scumm/actor.cpp +++ b/scumm/actor.cpp @@ -137,6 +137,8 @@ void Actor::initActor(int mode) { clipOverride = _vm->_actorClipOverride; + auxBlock.visible = false; + _vm->_classData[number] = (_vm->_version >= 7) ? _vm->_classData[0] : 0; } @@ -492,8 +494,10 @@ void Actor::startAnimActor(int f) { // Causes Zak to lose his body in several scenes, see bug #771508 if (_vm->_version >= 3 && f == initFrame) cost.reset(); - if (_vm->_features & GF_NEW_COSTUMES) + if (_vm->_features & GF_NEW_COSTUMES) { + auxBlock.visible = false; _vm->akos_decodeData(this, f, (uint) - 1); + } else _vm->cost_decodeData(this, f, (uint) - 1); frame = f; @@ -602,6 +606,12 @@ void Actor::putActor(int dstX, int dstY, byte newRoom) { } adjustActorPos(); } else { + if (_vm->_heversion >= 72) { + if (auxBlock.visible) { + _vm->queueAuxBlock(this); + auxBlock.visible = false; + } + } hideActor(); } } else { @@ -1356,6 +1366,12 @@ void Actor::setActorCostume(int c) { memset(animVariable, 0, sizeof(animVariable)); costume = c; + if (_vm->_heversion >= 72) { + if (auxBlock.visible) { + _vm->queueAuxBlock(this); + } + } + if (visible) { if (costume) { _vm->ensureResourceLoaded(rtCostume, costume); @@ -1869,6 +1885,101 @@ bool Actor::isTalkConditionSet(int slot) { return condMask & (1 << (slot - 1)); } +void ScummEngine::preProcessAuxQueue() { + if (!_skipProcessActors) { + for (int i = 0; i < _auxBlocksNum; ++i) { + AuxBlock *ab = &_auxBlocks[i]; + assert(ab->r.top <= ab->r.bottom); + if (ab->visible) { + gdi.copyVirtScreenBuffers(ab->r); + } + } + } + _auxBlocksNum = 0; +} + +void ScummEngine::postProcessAuxQueue() { + if (!_skipProcessActors) { + for (int i = 0; i < _auxEntriesNum; ++i) { + AuxEntry *ae = &_auxEntries[i]; + if (ae->actorNum != -1) { + Actor *a = derefActor(ae->actorNum, "postProcessAuxQueue"); + const uint8 *cost = getResourceAddress(rtCostume, a->costume); + + int dy = a->offs_y + a->_pos.y - a->getElevation(); + int dx = a->offs_x + a->_pos.x; + + const uint8 *akax = findResource(MKID('AKAX'), cost); + if (!akax) { + error("No AKAX block for actor %d", ae->actorNum); + } + const uint8 *auxd = findPalInPals(akax, ae->subIndex) - _resourceHeaderSize; + if (!auxd) { + error("No AUXD block for actor %d", ae->actorNum); + } + const uint8 *axfd = findResourceData(MKID('AXFD'), auxd); + if (!axfd) { + error("No AXFD block for actor %d", ae->actorNum); + } else { + uint16 comp = READ_LE_UINT16(axfd); + if (comp == 1 || comp == 16) { + int x1 = (int16)READ_LE_UINT16(axfd + 2) + dx; + int y1 = (int16)READ_LE_UINT16(axfd + 4) + dy; + int x2 = (int16)READ_LE_UINT16(axfd + 6); + int y2 = (int16)READ_LE_UINT16(axfd + 8); + VirtScreen *pvs = &virtscr[kMainVirtScreen]; + uint8 *dst1 = pvs->getPixels(0, 0); + uint8 *dst2 = pvs->getBackPixels(0, 0); + switch (comp) { + case 1: + gdi.copyAuxImage(dst1, dst2, axfd + 10, pvs->w, pvs->h, x1, y1, x2, y2, 0); + break; + default: + warning("unimplemented compression type %d", comp); + break; + } + } + } + const uint8 *axur = findResourceData(MKID('AXUR'), auxd); + if (axur) { + uint16 n = READ_LE_UINT16(axur); axur += 2; + while (n--) { + int x = (int16)READ_LE_UINT16(axur + 0) + dx; + int y = (int16)READ_LE_UINT16(axur + 2) + dy; + int w = (int16)READ_LE_UINT16(axur + 4) + dx; + int h = (int16)READ_LE_UINT16(axur + 6) + dy; + markRectAsDirty(kMainVirtScreen, x, w, y, h); + axur += 8; + } + } + const uint8 *axer = findResourceData(MKID('AXER'), auxd); + if (axer) { + a->auxBlock.visible = true; + a->auxBlock.r.left = (int16)READ_LE_UINT16(axer + 0) + dx; + a->auxBlock.r.top = (int16)READ_LE_UINT16(axer + 2) + dy; + a->auxBlock.r.right = (int16)READ_LE_UINT16(axer + 4) + dx; + a->auxBlock.r.bottom = (int16)READ_LE_UINT16(axer + 6) + dy; + } + } + } + } + _auxEntriesNum = 0; +} + +void ScummEngine::queueAuxBlock(Actor *a) { + assert(_auxBlocksNum < ARRAYSIZE(_auxBlocks)); + _auxBlocks[_auxBlocksNum] = a->auxBlock; + ++_auxBlocksNum; +} + +void ScummEngine::queueAuxEntry(int actorNum, int subIndex) { + assert(_auxEntriesNum < ARRAYSIZE(_auxEntries)); + AuxEntry *ae = &_auxEntries[_auxEntriesNum]; + ae->actorNum = actorNum; + ae->subIndex = subIndex; + ++_auxEntriesNum; +} + const SaveLoadEntry *Actor::getSaveLoadEntries() { static const SaveLoadEntry actorEntries[] = { diff --git a/scumm/actor.h b/scumm/actor.h index 66381fe353..8e839dc3fb 100644 --- a/scumm/actor.h +++ b/scumm/actor.h @@ -125,6 +125,7 @@ public: CostumeData cost; uint32 condMask; bool talkUnk; + AuxBlock auxBlock; protected: byte palette[256]; int elevation; diff --git a/scumm/akos.cpp b/scumm/akos.cpp index 27a130c6a7..f2b498e05d 100644 --- a/scumm/akos.cpp +++ b/scumm/akos.cpp @@ -1245,7 +1245,7 @@ byte AkosRenderer::codec32(int xmoveCur, int ymoveCur) { if (_draw_bottom < dst.bottom) _draw_bottom = dst.bottom; - _vm->gdi.decompressImageHE(_outptr, _outwidth, &dst, _srcptr, &src); + _vm->gdi.decompressWizImage(_outptr, _outwidth, &dst, _srcptr, &src); return 0; } @@ -1381,7 +1381,7 @@ bool ScummEngine::akos_increaseAnim(Actor *a, int chan, const byte *aksq, const curpos += aksq[curpos + 2]; break; case AKC_C08E: - //akos_queCommand(7, a, GB(2), 0); + akos_queCommand(7, a, GW(2), 0); curpos += 4; break; default: @@ -1674,7 +1674,9 @@ void ScummEngine::akos_processQueue() { a->offs_y = param_2; break; case 7: - if (param_1 != 0) { + if (_heversion >= 72) { + queueAuxEntry(a->number, param_1); + } else if (param_1 != 0) { if (_imuseDigital) { _imuseDigital->setVolume(param_1, param_2); } diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp index bcbc26c2f7..9ddf3fc35c 100644 --- a/scumm/gfx.cpp +++ b/scumm/gfx.cpp @@ -1481,11 +1481,11 @@ void Gdi::copyWizImage(uint8 *dst, const uint8 *src, int dst_w, int dst_h, int s r2.bottom -= diff; } if (r1.isValidRect() && r2.isValidRect()) { - decompressImageHE(dst, dst_w, &r2, src, &r1); + decompressWizImage(dst, dst_w, &r2, src, &r1); } } -void Gdi::decompressImageHE(uint8 *dst, int dstWidth, const Common::Rect *dstRect, const uint8 *src, const Common::Rect *srcRect) { +void Gdi::decompressWizImage(uint8 *dst, int dstPitch, const Common::Rect *dstRect, const uint8 *src, const Common::Rect *srcRect) { const uint8 *dataPtr, *dataPtrNext; uint8 *dstPtr, *dstPtrNext; uint32 code; @@ -1493,7 +1493,7 @@ void Gdi::decompressImageHE(uint8 *dst, int dstWidth, const Common::Rect *dstRec int h, w, xoff; uint16 off; - dstPtr = dst + dstRect->left + dstRect->top * dstWidth; + dstPtr = dst + dstRect->left + dstRect->top * dstPitch; dataPtr = src; h = srcRect->top; while (h--) { @@ -1513,7 +1513,7 @@ void Gdi::decompressImageHE(uint8 *dst, int dstWidth, const Common::Rect *dstRec xoff = srcRect->left; off = READ_LE_UINT16(dataPtr); w = srcRect->right - srcRect->left + 1; - dstPtrNext = dstWidth + dstPtr; + dstPtrNext = dstPitch + dstPtr; dataPtrNext = off + 2 + dataPtr; dataPtr += 2; if (off == 0) goto dec_next; @@ -1589,6 +1589,141 @@ dec_next: } } +void Gdi::copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, Common::Rect *rect) { + Common::Rect r1(0, 0, srcw - 1, srch - 1); + Common::Rect r2(srcx, srcy, srcx + srcw - 1, srcy + srch - 1); + Common::Rect r3; + int diff; + + if (rect) { + r3 = *rect; + Common::Rect r4(0, 0, dstw - 1, dsth - 1); + if (!r3.intersects(r4)) { + return; + } + } else { + r3 = Common::Rect(0, 0, dstw - 1, dsth - 1); + } + 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()) { + decompressAuxImage(dst1, dst2, dstw, &r2, src, &r1); + } +} + +void Gdi::decompressAuxImage(uint8 *dst1, uint8 *dst2, int dstPitch, const Common::Rect *dstRect, const uint8 *src, const Common::Rect *srcRect) { + uint8 *dstCur2, *dstCur1; + const uint8 *srcCur; + uint8 code; + + int w = srcRect->right - srcRect->left + 1; + int h = srcRect->bottom - srcRect->top + 1; + int off = dstRect->top * dstPitch + dstRect->left; + + dst1 += off; + dst2 += off; + + int n = srcRect->top; + while (n--) { + src += READ_LE_UINT16(src) + 2; + } + + while (h--) { + uint16 var_8 = READ_LE_UINT16(src); + if (var_8) { + int rw = w; + int xoff = srcRect->left; + srcCur = src + 2; + dstCur1 = dst1; + dstCur2 = dst2; + while (xoff > 0) { + code = *srcCur++; + if (code & 1) { + code >>= 1; + if (code > xoff) { + code -= xoff; + goto dec_sub1; + } + xoff -= code; + } else if (code & 2) { + code = (code >> 2) + 1; + if (code > xoff) { + code -= xoff; + goto dec_sub2; + } + xoff -= code; + ++srcCur; + } else { + code = (code >> 2) + 1; + if (code > xoff) { + code -= xoff; + srcCur += xoff; + goto dec_sub3; + } + xoff -= code; + srcCur += code; + } + } + while (rw > 0) { + code = *srcCur++; + if (code & 1) { + code >>= 1; +dec_sub1: dstCur1 += code; + dstCur2 += code; + rw -= code; + } else if (code & 2) { + code = (code >> 2) + 1; +dec_sub2: rw -= code; + if (rw >= 0) { + memset(dstCur1, *srcCur++, code); + dstCur1 += code; + dstCur2 += code; + } else { + code += rw; + memset(dstCur1, *srcCur, code); + } + } else { + code = (code >> 2) + 1; +dec_sub3: rw -= code; + if (rw >= 0) { + memcpy(dstCur1, dstCur2, code); + dstCur1 += code; + dstCur2 += code; + } else { + code += rw; + memcpy(dstCur1, dstCur2, code); + } + } + } + src += var_8 + 2; + dst1 += dstPitch; + dst2 += dstPitch; + } else { + src += 2; + dst1 += dstPitch; + dst2 += dstPitch; + } + } +} + void Gdi::copyVirtScreenBuffers(Common::Rect rect) { int rw = rect.right - rect.left + 1; int rh = rect.bottom - rect.top + 1; diff --git a/scumm/gfx.h b/scumm/gfx.h index 06a9fa9f04..5dcfe48374 100644 --- a/scumm/gfx.h +++ b/scumm/gfx.h @@ -275,8 +275,10 @@ public: StripTable *generateStripTable(const byte *src, int width, int height, StripTable *table); void drawBMAPBg(const byte *ptr, VirtScreen *vs, int startstrip, int width); void drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y, int w, int h); - void copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, Common::Rect *pr); - void decompressImageHE(uint8 *dst, int dstWidth, const Common::Rect *dstRect, const uint8 *src, const Common::Rect *srcRect); + void copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, Common::Rect *rect); + void decompressWizImage(uint8 *dst, int dstPitch, const Common::Rect *dstRect, const uint8 *src, const Common::Rect *srcRect); + void copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, Common::Rect *rect); + void decompressAuxImage(uint8 *dst1, uint8 *dst2, int dstPitch, const Common::Rect *dstRect, const uint8 *src, const Common::Rect *srcRect); void copyVirtScreenBuffers(Common::Rect rect); void disableZBuffer() { _zbufferDisabled = true; } diff --git a/scumm/palette.cpp b/scumm/palette.cpp index 983adf6380..5f4ed3b09d 100644 --- a/scumm/palette.cpp +++ b/scumm/palette.cpp @@ -785,7 +785,6 @@ const byte *ScummEngine::findPalInPals(const byte *pal, int idx) { return NULL; size = getResourceDataSize(offs) / 4; - if ((uint32)idx >= (uint32)size) return NULL; diff --git a/scumm/script_v7he.cpp b/scumm/script_v7he.cpp index 37a9460eb1..1267255000 100644 --- a/scumm/script_v7he.cpp +++ b/scumm/script_v7he.cpp @@ -745,8 +745,9 @@ void ScummEngine_v7he::o7_kernelSetFunctions() { // Fatty Bear's Birthday Surprise virtScreenLoad(args[1], args[2], args[3], args[4], args[5]); break; - case 20: - // erase aux animation actor? + case 20: // HE72+ + a = derefActor(args[1], "o7_kernelSetFunctions: 20"); + queueAuxBlock(a); break; case 21: _skipDrawObject = 1; @@ -759,19 +760,11 @@ void ScummEngine_v7he::o7_kernelSetFunctions() { _fullRedraw = 1; break; case 24: - if (_heversion <= 72) { - _skipProcessActors = 1; - } else { - //Pause aux animation - } + _skipProcessActors = 1; _fullRedraw = 1; break; case 25: - if (_heversion <= 72) { - _skipProcessActors = 0; - } else { - //Resume aux animation - } + _skipProcessActors = 0; _fullRedraw = 1; break; case 30: diff --git a/scumm/scumm.cpp b/scumm/scumm.cpp index 1ffaa2a72b..d6d84b5909 100644 --- a/scumm/scumm.cpp +++ b/scumm/scumm.cpp @@ -691,6 +691,10 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS _skipDrawObject = 0; _skipProcessActors = 0; + _auxBlocksNum = 0; + memset(_auxBlocks, 0, sizeof(_auxBlocks)); + _auxEntriesNum = 0; + memset(_auxEntries, 0, sizeof(_auxEntries)); _heSndSoundId = 0; _heSndOffset = 0; _heSndChannel = 0; @@ -1820,8 +1824,14 @@ load_game: drawFlashlight(); setActorRedrawFlags(); } - - processActors(); + if (_heversion >= 72) { + preProcessAuxQueue(); + processActors(); + postProcessAuxQueue(); + } else { + processActors(); + } + _fullRedraw = false; if (_version >= 4 && _heversion <= 60) cyclePalette(); @@ -2329,9 +2339,8 @@ void ScummEngine::startScene(int room, Actor *a, int objectNr) { stopCycle(0); _sound->processSoundQues(); - if (_heversion >= 70 && _WizPolygons) { - for (i = 0; i < _WizNumPolygons; i++) - memset(&_WizPolygons[i], 0, sizeof(WizPolygon)); + if (_heversion >= 70 && _WizPolygons) { + memset(_WizPolygons, 0, _WizNumPolygons * sizeof(WizPolygon)); } for (i = 0; i < _numRoomVariables; i++) diff --git a/scumm/scumm.h b/scumm/scumm.h index 7e27a2b002..aae2e11def 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -329,6 +329,16 @@ struct WizPolygon { bool flag; }; +struct AuxBlock { + bool visible; + Common::Rect r; +}; + +struct AuxEntry { + int actorNum; + int subIndex; +}; + class ScummEngine : public Engine { friend class ScummDebugger; friend class SmushPlayer; @@ -838,6 +848,18 @@ protected: bool isCostumeInUse(int i) const; +public: + /* Actor AuxQueue stuff (HE) */ + AuxBlock _auxBlocks[16]; + uint16 _auxBlocksNum; + AuxEntry _auxEntries[16]; + uint16 _auxEntriesNum; + + void preProcessAuxQueue(); + void postProcessAuxQueue(); + void queueAuxBlock(Actor *a); + void queueAuxEntry(int actorNum, int subIndex); + public: /* Actor talking stuff */ byte _actorToPrintStrFor, _V1_talkingActor; -- cgit v1.2.3