From 2e0814514c346cc3c7bf091131dce91f99473810 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Wed, 23 Jun 2004 01:36:57 +0000 Subject: HE 7.0 fixes o Stub for o7_startSound o graphics decoders o findResource was moved to ScummEngine and extended o 7.0+ titles use akos costumes, so fix that in launcher o more o6_resourceRoutines stubs Now HE 7.0 games (first 320x200 windows ports) show intros and some are playable to some extent. svn-id: r14003 --- scumm/actor.cpp | 6 ++-- scumm/gfx.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++++--- scumm/gfx.h | 1 + scumm/intern.h | 1 + scumm/resource.cpp | 29 +++++++++++------ scumm/resource.h | 1 - scumm/script_v6.cpp | 15 +++++++-- scumm/script_v7he.cpp | 46 +++++++++++++++++++++++++- scumm/scumm.cpp | 13 ++++++-- scumm/scumm.h | 4 +++ 10 files changed, 182 insertions(+), 23 deletions(-) diff --git a/scumm/actor.cpp b/scumm/actor.cpp index 024a8886be..f30327ccde 100644 --- a/scumm/actor.cpp +++ b/scumm/actor.cpp @@ -1624,7 +1624,7 @@ void Actor::remapActorPaletteColor(int color, int new_color) { return; } - akpl = findResource(MKID('AKPL'), akos); + akpl = _vm->findResource(MKID('AKPL'), akos); if (!akpl) { warning("Can't remap actor %d, costume %d doesn't contain an AKPL block", number, costume); return; @@ -1660,7 +1660,7 @@ void Actor::remapActorPalette(int r_fact, int g_fact, int b_fact, int threshold) return; } - akpl = findResource(MKID('AKPL'), akos); + akpl = _vm->findResource(MKID('AKPL'), akos); if (!akpl) { warning("Can't remap actor %d, costume %d doesn't contain an AKPL block", number, costume); return; @@ -1672,7 +1672,7 @@ void Actor::remapActorPalette(int r_fact, int g_fact, int b_fact, int threshold) //skip resource header akpl = RES_DATA(akpl); - rgbs = findResource(MKID('RGBS'), akos); + rgbs = _vm->findResource(MKID('RGBS'), akos); if (!rgbs) { warning("Can't remap actor %d costume %d doesn't contain an RGB block", number, costume); diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp index a0dea70ff2..d51cea01cb 100644 --- a/scumm/gfx.cpp +++ b/scumm/gfx.cpp @@ -466,7 +466,11 @@ void ScummEngine::initBGBuffers(int height) { initVirtScreen(kMainVirtScreen, 0, virtscr[0].topline, _screenWidth, height, 1, 1); } - room = getResourceAddress(rtRoom, _roomResource); + if (_heversion >= 70) + room = getResourceAddress(rtLast, _roomResource); + else + room = getResourceAddress(rtRoom, _roomResource); + if (_version <= 3) { gdi._numZBuffer = 2; } else if (_features & GF_SMALL_HEADER) { @@ -488,6 +492,9 @@ void ScummEngine::initBGBuffers(int height) { // in V8 there is no RMIH and num z buffers is in RMHD ptr = findResource(MKID('RMHD'), room); gdi._numZBuffer = READ_LE_UINT32(ptr + 24) + 1; + } else if (_heversion >= 70) { + ptr = findResource(MKID('RMIH'), room); + gdi._numZBuffer = READ_LE_UINT16(ptr + 8) + 1; } else { ptr = findResource(MKID('RMIH'), findResource(MKID('RMIM'), room)); gdi._numZBuffer = READ_LE_UINT16(ptr + 8) + 1; @@ -566,6 +573,8 @@ void ScummEngine::redrawBGAreas() { } void ScummEngine::redrawBGStrip(int start, int num) { + byte *room; + int s = _screenStartStrip + start; assert(s >= 0 && (size_t) s < sizeof(gfxUsageBits) / (3 * sizeof(gfxUsageBits[0]))); @@ -576,7 +585,12 @@ void ScummEngine::redrawBGStrip(int start, int num) { if (_version == 1) { gdi._C64ObjectMode = false; } - gdi.drawBitmap(getResourceAddress(rtRoom, _roomResource) + _IM00_offs, + if (_heversion >= 70) + room = getResourceAddress(rtRoomStart, _roomResource); + else + room = getResourceAddress(rtRoom, _roomResource); + + gdi.drawBitmap(room + _IM00_offs, &virtscr[0], s, 0, _roomWidth, virtscr[0].height, s, num, 0, _roomStrips); } @@ -922,7 +936,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi else if (_vm->_version == 8) smap_ptr = ptr; else - smap_ptr = findResource(MKID('SMAP'), ptr); + smap_ptr = _vm->findResource(MKID('SMAP'), ptr); assert(smap_ptr); @@ -974,7 +988,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi }; for (i = 1; i < numzbuf; i++) { - zplane_list[i] = findResource(zplane_tags[i], ptr); + zplane_list[i] = _vm->findResource(zplane_tags[i], ptr); } } } @@ -1632,6 +1646,23 @@ bool Gdi::decompressBitmap(byte *bgbak_ptr, const byte *src, int numLinesToProce unkDecodeA_trans(bgbak_ptr, src, numLinesToProcess); break; + case 134: + case 135: + case 136: + case 137: + case 138: + decodeStripHE(bgbak_ptr, src, numLinesToProcess, false); + break; + + case 144: + case 145: + case 146: + case 147: + case 148: + useOrDecompress = true; + decodeStripHE(bgbak_ptr, src, numLinesToProcess, true); + break; + default: error("Gdi::decompressBitmap: default case %d", code); } @@ -2241,6 +2272,56 @@ void Gdi::decodeStrip3DO(byte *dst, const byte *src, int height, byte transpChec } +void Gdi::decodeStripHE(byte *dst, const byte *src, int height, byte transpCheck) { + uint32 color, dataBit, data, shift, iteration; + + color = *src; + src++; + data = READ_LE_UINT24(src); + src += 3; + shift = 24; + + while (height) { + for (iteration = 0; iteration < 8; iteration++) { + if (color != _transparentColor || !transpCheck) + *dst = color; + dst++; + if (shift <= 16) { + data |= *src << shift; + src++; + shift += 8; + data |= *src << shift; + src++; + shift += 8; + } + + dataBit = data & 1; + shift--; + data >>= 1; + if (dataBit) { + dataBit = data & 1; + shift--; + data >>= 1; + if (!dataBit) { + color = _decomp_mask & data; + shift -= _decomp_shr; + data >>= _decomp_shr; + } else { + dataBit = data & 7; + shift -= 3; + data >>= 3; + if (dataBit >= 4) + color += dataBit - 3; + else + color += dataBit - 4; + } + } + } + dst += 312; + height--; + } +} + #undef NEXT_ROW #undef READ_256BIT diff --git a/scumm/gfx.h b/scumm/gfx.h index f503eada83..ecfe6d2af1 100644 --- a/scumm/gfx.h +++ b/scumm/gfx.h @@ -249,6 +249,7 @@ protected: void unkDecode10(byte *dst, const byte *src, int height); void unkDecode11(byte *dst, const byte *src, int height); void decodeStrip3DO(byte *dst, const byte *src, int height, byte transpCheck); + void decodeStripHE(byte *dst, const byte *src, int height, byte transpCheck); void draw8ColWithMasking(byte *dst, const byte *src, int height, byte *mask); void draw8Col(byte *dst, const byte *src, int height); diff --git a/scumm/intern.h b/scumm/intern.h index 9ee08890a9..8f42802103 100644 --- a/scumm/intern.h +++ b/scumm/intern.h @@ -636,6 +636,7 @@ protected: void o7_unknownFB(); void o7_quitPauseRestart(); void o7_pickupObject(); + void o7_startSound(); }; class ScummEngine_v7 : public ScummEngine_v6 { diff --git a/scumm/resource.cpp b/scumm/resource.cpp index e2fc0d9976..beaa1b7703 100644 --- a/scumm/resource.cpp +++ b/scumm/resource.cpp @@ -2283,21 +2283,32 @@ const byte *ResourceIterator::findNext(uint32 tag) { return result; } -const byte *findResource(uint32 tag, const byte *searchin) { +const byte *ScummEngine::findResource(uint32 tag, const byte *searchin) { uint32 curpos, totalsize, size; - // It seems that in HE games if searchin == NULL, it continues - // search from last position - assert(searchin); + debugC(DEBUG_RESOURCE, "findResource(%s, %lx)", tag2str(tag), searchin); - searchin += 4; - totalsize = READ_BE_UINT32(searchin); - curpos = 8; - searchin += 4; + if (!searchin) { + if (_heversion >= 70) { + searchin = _resourceLastSearchBuf; + totalsize = _resourceLastSearchSize; + curpos = 0; + } else { + assert(searchin); + return NULL; + } + } else { + searchin += 4; + _resourceLastSearchSize = totalsize = READ_BE_UINT32(searchin); + curpos = 8; + searchin += 4; + } while (curpos < totalsize) { - if (READ_UINT32(searchin) == tag) + if (READ_UINT32(searchin) == tag) { + _resourceLastSearchBuf = searchin; return searchin; + } size = READ_BE_UINT32(searchin + 4); if ((int32)size <= 0) { diff --git a/scumm/resource.h b/scumm/resource.h index 567981ee14..77fdd147af 100644 --- a/scumm/resource.h +++ b/scumm/resource.h @@ -59,7 +59,6 @@ enum { }; -const byte *findResource(uint32 tag, const byte *searchin); const byte *findResourceSmall(uint32 tag, const byte *searchin); class ResourceIterator { diff --git a/scumm/script_v6.cpp b/scumm/script_v6.cpp index d836c28442..fea6f88b1f 100644 --- a/scumm/script_v6.cpp +++ b/scumm/script_v6.cpp @@ -386,7 +386,7 @@ const char *ScummEngine_v6::getOpcodeDesc(byte i) { int ScummEngine_v6::popRoomAndObj(int *room) { int obj; - if (_version >= 7) { + if (_version >= 7 || _heversion >= 70) { obj = pop(); *room = getObjectRoom(obj); } else { @@ -1461,6 +1461,7 @@ void ScummEngine_v6::o6_resourceRoutines() { int resid, op; op = fetchScriptByte(); + debug(0, "resourceRoutines op: %d", op); switch (op) { case 100: // SO_LOAD_SCRIPT resid = pop(); @@ -1586,7 +1587,7 @@ void ScummEngine_v6::o6_resourceRoutines() { // QL_QueGlobForLoad(3, pop(), 1); break; } - case 123: + case 123: { if (_heversion < 70) error("o6_resourceRoutines: default case %d", op); @@ -1597,6 +1598,16 @@ void ScummEngine_v6::o6_resourceRoutines() { // QL_QueGlobForLoad(1, resid, 1); break; } + case 233: + resid = pop(); + warning("stub o6_resourceRoutines resource %d, 1", resid); + // foo(resid, 1); + break; + case 235: + resid = pop(); + warning("stub o6_resourceRoutines resource %d, 0", resid); + // foo(resid, 0); + break; default: error("o6_resourceRoutines: default case %d", op); } diff --git a/scumm/script_v7he.cpp b/scumm/script_v7he.cpp index a58f4bb129..f29945759c 100644 --- a/scumm/script_v7he.cpp +++ b/scumm/script_v7he.cpp @@ -196,7 +196,7 @@ void ScummEngine_v7he::setupOpcodes() { OPCODE(o6_getOwner), OPCODE(o6_jump), /* 74 */ - OPCODE(o6_startSound), + OPCODE(o7_startSound), OPCODE(o6_stopSound), OPCODE(o6_startMusic), OPCODE(o6_stopObjectScript), @@ -644,4 +644,48 @@ void ScummEngine_v7he::o7_pickupObject() { } +void ScummEngine_v7he::o7_startSound() { + byte op; + op = fetchScriptByte(); + + switch (op) { + case 224: + // _staticVar1 = pop(); + pop(); + break; + + case 230: + // _staticVar2 = pop(); + pop(); + break; + + case 231: + // _staticVar3 = pop(); + pop(); + break; + + case 232: + pop(); + // _staticVar4 = pop(); + // _staticVar3 = 0; + // _staticVar1 = 11025; + // _staticVar2 = VAR(VAR_MUSIC_TIMER); + break; + + case 245: + // _staticVar5 |= 1; + break; + + case 255: + // _sound->addSoundToQueue(_staticVar4, _staticVar3, _staticVar2, _staticVar5); + // _staticVar5 = 0; + break; + + default: + break; + } + warning("o7_startSound stub (%d)", op); +} + + } // End of namespace Scumm diff --git a/scumm/scumm.cpp b/scumm/scumm.cpp index ad08405d3b..8a4eecbe26 100644 --- a/scumm/scumm.cpp +++ b/scumm/scumm.cpp @@ -2060,6 +2060,7 @@ void ScummEngine::startScene(int room, Actor *a, int objectNr) { } initRoomSubBlocks(); + if (_features & GF_OLD_BUNDLE) loadRoomObjectsOldBundle(); else if (_features & GF_SMALL_HEADER) @@ -2149,7 +2150,7 @@ void ScummEngine::startScene(int room, Actor *a, int objectNr) { void ScummEngine::initRoomSubBlocks() { int i; const byte *ptr; - byte *roomptr, *searchptr, *roomResPtr; + byte *roomptr, *searchptr, *roomResPtr, *roomStartPtr = 0; const RoomHeader *rmhd; _ENCD_offs = 0; @@ -2169,7 +2170,9 @@ void ScummEngine::initRoomSubBlocks() { // Determine the room and room script base address roomResPtr = roomptr = getResourceAddress(rtRoom, _roomResource); - if (_version == 8) + if (_heversion >= 70) + roomStartPtr = getResourceAddress(rtRoomStart, _roomResource); + else if (_version == 8) roomResPtr = getResourceAddress(rtRoomScripts, _roomResource); if (!roomptr || !roomResPtr) error("Room %d: data not found (" __FILE__ ":%d)", _roomResource, __LINE__); @@ -2222,6 +2225,8 @@ void ScummEngine::initRoomSubBlocks() { _IM00_offs = getObjectImage(roomptr, 1) - roomptr; } else if (_features & GF_SMALL_HEADER) { _IM00_offs = findResourceData(MKID('IM00'), roomptr) - roomptr; + } else if (_heversion >= 70) { + _IM00_offs = findResource(MKID('IM00'), roomStartPtr) - roomStartPtr; } else { _IM00_offs = findResource(MKID('IM00'), findResource(MKID('RMIM'), roomptr)) - roomptr; } @@ -2990,8 +2995,10 @@ Engine *Engine_SCUMM_create(GameDetector *detector, OSystem *syst) { // There are both Windows and DOS versions of early HE titles // specify correct version here - if (game.features & GF_HUMONGOUS && (game.heversion == 60 || game.id == GID_PUTTDEMO)) + if (game.features & GF_HUMONGOUS && (game.heversion == 60 || game.id == GID_PUTTDEMO)) { game.heversion = 70; + game.features |= GF_NEW_COSTUMES; + } break; case Common::kPlatformFMTowns: if (game.version == 3) { diff --git a/scumm/scumm.h b/scumm/scumm.h index 27908e2d37..625c0823c4 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -204,6 +204,7 @@ enum ResTypes { rtBox = 15, rtObjectName = 16, rtRoomScripts = 17, + rtRoomStart = 17, rtLast = 17, rtNumTypes = 18 }; @@ -626,6 +627,8 @@ protected: byte _expire_counter; byte *_HEV7RoomOffsets; uint32 *_HEV7RoomIntOffsets; + const byte *_resourceLastSearchBuf; // FIXME: need to put it to savefile? + uint32 _resourceLastSearchSize; // FIXME: need to put it to savefile? void allocateArrays(); void openRoom(int room); @@ -677,6 +680,7 @@ protected: int _lastLoadedRoom; public: const byte *findResourceData(uint32 tag, const byte *ptr); + const byte *findResource(uint32 tag, const byte *ptr); int getResourceDataSize(const byte *ptr) const; void dumpResource(const char *tag, int index, const byte *ptr, int length = -1); -- cgit v1.2.3