From 3e6414a55fb05fa733248574f8305c0f716415d8 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 12 Nov 2006 19:05:51 +0000 Subject: Slighty modified Patch #1571787: "Support for Mac Broken Sword 1". sword1macdemo target was commented out until existence of the demo is confirmed. svn-id: r24697 --- engines/sword1/control.cpp | 33 ++++--- engines/sword1/logic.cpp | 54 +++++------ engines/sword1/mouse.cpp | 33 ++++--- engines/sword1/objectman.cpp | 11 +-- engines/sword1/resman.cpp | 163 +++++++++++++++++++++++--------- engines/sword1/resman.h | 36 ++++++- engines/sword1/router.cpp | 41 ++++---- engines/sword1/screen.cpp | 47 +++++----- engines/sword1/sword1.cpp | 218 +++++++++++++++++++++++++++++++++---------- engines/sword1/sword1.h | 4 +- engines/sword1/text.cpp | 14 +-- 11 files changed, 443 insertions(+), 211 deletions(-) (limited to 'engines/sword1') diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp index 38cc2f4554..85e25c75fc 100644 --- a/engines/sword1/control.cpp +++ b/engines/sword1/control.cpp @@ -21,7 +21,6 @@ */ #include "common/stdafx.h" -#include "common/endian.h" #include "common/file.h" #include "common/util.h" #include "common/savefile.h" @@ -118,8 +117,8 @@ ControlButton::ControlButton(uint16 x, uint16 y, uint32 resId, uint8 id, uint8 f _frameIdx = 0; _resMan->resOpen(_resId); FrameHeader *tmp = _resMan->fetchFrame(_resMan->fetchRes(_resId), 0); - _width = FROM_LE_16(tmp->width); - _height = FROM_LE_16(tmp->height); + _width = _resMan->getUint16(tmp->width); + _height = _resMan->getUint16(tmp->height); if ((x == 0) && (y == 0)) { // center the frame (used for panels); _x = (640 - _width) / 2; _y = (480 - _height) / 2; @@ -140,12 +139,12 @@ void ControlButton::draw(void) { FrameHeader *fHead = _resMan->fetchFrame(_resMan->fetchRes(_resId), _frameIdx); uint8 *src = (uint8*)fHead + sizeof(FrameHeader); uint8 *dst = _dstBuf; - for (uint16 cnt = 0; cnt < READ_LE_UINT16(&fHead->height); cnt++) { - for (uint16 cntx = 0; cntx < READ_LE_UINT16(&fHead->width); cntx++) + for (uint16 cnt = 0; cnt < _resMan->readUint16(&fHead->height); cnt++) { + for (uint16 cntx = 0; cntx < _resMan->readUint16(&fHead->width); cntx++) if (src[cntx]) dst[cntx] = src[cntx]; dst += SCREEN_WIDTH; - src += READ_LE_UINT16(&fHead->width); + src += _resMan->readUint16(&fHead->width); } _system->copyRectToScreen(_dstBuf, SCREEN_WIDTH, _x, _y, _width, _height); } @@ -485,8 +484,8 @@ void Control::setupMainPanel(void) { void Control::setupSaveRestorePanel(bool saving) { FrameHeader *savePanel = _resMan->fetchFrame(_resMan->openFetchRes(SR_WINDOW), 0); - uint16 panelX = (640 - FROM_LE_16(savePanel->width)) / 2; - uint16 panelY = (480 - FROM_LE_16(savePanel->height)) / 2; + uint16 panelX = (640 - _resMan->getUint16(savePanel->width)) / 2; + uint16 panelY = (480 - _resMan->getUint16(savePanel->height)) / 2; ControlButton *panel = new ControlButton(panelX, panelY, SR_WINDOW, 0, 0, _resMan, _screenBuf, _system); panel->draw(); delete panel; @@ -870,7 +869,7 @@ void Control::destroyButtons(void) { uint16 Control::getTextWidth(const uint8 *str) { uint16 width = 0; while (*str) { - width += FROM_LE_16(_resMan->fetchFrame(_font, *str - 32)->width) - 3; + width += _resMan->getUint16(_resMan->fetchFrame(_font, *str - 32)->width) - 3; str++; } return width; @@ -894,15 +893,15 @@ void Control::renderText(const uint8 *str, uint16 x, uint16 y, uint8 mode) { FrameHeader *chSpr = _resMan->fetchFrame(font, *str - 32); uint8 *sprData = (uint8*)chSpr + sizeof(FrameHeader); - for (uint16 cnty = 0; cnty < FROM_LE_16(chSpr->height); cnty++) { - for (uint16 cntx = 0; cntx < FROM_LE_16(chSpr->width); cntx++) { + for (uint16 cnty = 0; cnty < _resMan->getUint16(chSpr->height); cnty++) { + for (uint16 cntx = 0; cntx < _resMan->getUint16(chSpr->width); cntx++) { if (sprData[cntx]) dst[cntx] = sprData[cntx]; } - sprData += FROM_LE_16(chSpr->width); + sprData += _resMan->getUint16(chSpr->width); dst += SCREEN_WIDTH; } - destX += FROM_LE_16(chSpr->width) - 3; + destX += _resMan->getUint16(chSpr->width) - 3; str++; } _system->copyRectToScreen(_screenBuf + y * SCREEN_WIDTH + x, SCREEN_WIDTH, x, y, (destX - x) + 3, 28); @@ -917,12 +916,12 @@ void Control::renderVolumeBar(uint8 id, uint8 volL, uint8 volR) { FrameHeader *frHead = _resMan->fetchFrame(_resMan->openFetchRes(SR_VLIGHT), (vol + 15) >> 4); uint8 *destMem = _screenBuf + destY * SCREEN_WIDTH + destX; uint8 *srcMem = (uint8*)frHead + sizeof(FrameHeader); - for (uint16 cnty = 0; cnty < FROM_LE_16(frHead->height); cnty++) { - memcpy(destMem, srcMem, FROM_LE_16(frHead->width)); - srcMem += FROM_LE_16(frHead->width); + for (uint16 cnty = 0; cnty < _resMan->getUint16(frHead->height); cnty++) { + memcpy(destMem, srcMem, _resMan->getUint16(frHead->width)); + srcMem += _resMan->getUint16(frHead->width); destMem += SCREEN_WIDTH; } - _system->copyRectToScreen(_screenBuf + destY * SCREEN_WIDTH + destX, SCREEN_WIDTH, destX, destY, FROM_LE_16(frHead->width), FROM_LE_16(frHead->height)); + _system->copyRectToScreen(_screenBuf + destY * SCREEN_WIDTH + destX, SCREEN_WIDTH, destX, destY, _resMan->getUint16(frHead->width), _resMan->getUint16(frHead->height)); _resMan->resClose(SR_VLIGHT); destX += 32; } diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp index 13b2e1afb0..105646cb5f 100644 --- a/engines/sword1/logic.cpp +++ b/engines/sword1/logic.cpp @@ -355,7 +355,7 @@ int Logic::speechDriver(Object *compact) { } if (compact->o_anim_resource) { uint8 *animData = ((uint8*)_resMan->openFetchRes(compact->o_anim_resource)) + sizeof(Header); - int32 numFrames = READ_LE_UINT32(animData); + int32 numFrames = _resMan->readUint32(animData); animData += 4; compact->o_anim_pc++; // go to next frame of anim @@ -365,10 +365,10 @@ int Logic::speechDriver(Object *compact) { AnimUnit *animPtr = (AnimUnit*)(animData + sizeof(AnimUnit) * compact->o_anim_pc); if (!(compact->o_status & STAT_SHRINK)) { - compact->o_anim_x = FROM_LE_32(animPtr->animX); - compact->o_anim_y = FROM_LE_32(animPtr->animY); + compact->o_anim_x = _resMan->getUint32(animPtr->animX); + compact->o_anim_y = _resMan->getUint32(animPtr->animY); } - compact->o_frame = FROM_LE_32(animPtr->animFrame); + compact->o_frame = _resMan->getUint32(animPtr->animFrame); _resMan->resClose(compact->o_anim_resource); } return 0; @@ -380,13 +380,13 @@ int Logic::fullAnimDriver(Object *compact) { return 1; } uint8 *data = ((uint8*)_resMan->openFetchRes(compact->o_anim_resource)) + sizeof(Header); - uint32 numFrames = READ_LE_UINT32(data); + uint32 numFrames = _resMan->readUint32(data); data += 4; AnimUnit *animPtr = (AnimUnit*)(data + compact->o_anim_pc * sizeof(AnimUnit)); - compact->o_anim_x = compact->o_xcoord = FROM_LE_32(animPtr->animX); - compact->o_anim_y = compact->o_ycoord = FROM_LE_32(animPtr->animY); - compact->o_frame = FROM_LE_32(animPtr->animFrame); + compact->o_anim_x = compact->o_xcoord = _resMan->getUint32(animPtr->animX); + compact->o_anim_y = compact->o_ycoord = _resMan->getUint32(animPtr->animY); + compact->o_frame = _resMan->getUint32(animPtr->animFrame); compact->o_anim_pc++; if (compact->o_anim_pc == (int)numFrames) @@ -402,15 +402,15 @@ int Logic::animDriver(Object *compact) { return 1; } uint8 *data = ((uint8*)_resMan->openFetchRes(compact->o_anim_resource)) + sizeof(Header); - uint32 numFrames = READ_LE_UINT32(data); + uint32 numFrames = _resMan->readUint32(data); AnimUnit *animPtr = (AnimUnit*)(data + 4 + compact->o_anim_pc * sizeof(AnimUnit)); if (!(compact->o_status & STAT_SHRINK)) { - compact->o_anim_x = FROM_LE_32(animPtr->animX); - compact->o_anim_y = FROM_LE_32(animPtr->animY); + compact->o_anim_x = _resMan->getUint32(animPtr->animX); + compact->o_anim_y = _resMan->getUint32(animPtr->animY); } - compact->o_frame = FROM_LE_32(animPtr->animFrame); + compact->o_frame = _resMan->getUint32(animPtr->animFrame); compact->o_anim_pc++; if (compact->o_anim_pc == (int)numFrames) compact->o_logic = LOGIC_script; @@ -828,8 +828,8 @@ int Logic::fnAnim(Object *cpt, int32 id, int32 cdt, int32 spr, int32 e, int32 f, animTab = (AnimSet*)((uint8*)_resMan->openFetchRes(cdt) + sizeof(Header)); animTab += cpt->o_dir; - cpt->o_anim_resource = FROM_LE_32(animTab->cdt); - cpt->o_resource = FROM_LE_32(animTab->spr); + cpt->o_anim_resource = _resMan->getUint32(animTab->cdt); + cpt->o_resource = _resMan->getUint32(animTab->spr); _resMan->resClose(cdt); } else { cpt->o_anim_resource = cdt; @@ -862,14 +862,14 @@ int Logic::fnSetFrame(Object *cpt, int32 id, int32 cdt, int32 spr, int32 frameNo uint8 *data = (uint8*)_resMan->openFetchRes(cdt); data += sizeof(Header); if (frameNo == LAST_FRAME) - frameNo = READ_LE_UINT32(data) - 1; + frameNo = _resMan->readUint32(data) - 1; data += 4; animPtr = (AnimUnit*)(data + frameNo * sizeof(AnimUnit)); - cpt->o_anim_x = FROM_LE_32(animPtr->animX); - cpt->o_anim_y = FROM_LE_32(animPtr->animY); - cpt->o_frame = FROM_LE_32(animPtr->animFrame); + cpt->o_anim_x = _resMan->getUint32(animPtr->animX); + cpt->o_anim_y = _resMan->getUint32(animPtr->animY); + cpt->o_frame = _resMan->getUint32(animPtr->animFrame); cpt->o_resource = spr; cpt->o_status &= ~STAT_SHRINK; @@ -892,13 +892,13 @@ int Logic::fnFullSetFrame(Object *cpt, int32 id, int32 cdt, int32 spr, int32 fra uint8 *data = (uint8*)_resMan->openFetchRes(cdt) + sizeof(Header); if (frameNo == LAST_FRAME) - frameNo = READ_LE_UINT32(data) - 1; + frameNo = _resMan->readUint32(data) - 1; data += 4; AnimUnit *animPtr = (AnimUnit*)(data + sizeof(AnimUnit) * frameNo); - cpt->o_anim_x = cpt->o_xcoord = FROM_LE_32(animPtr->animX); - cpt->o_anim_y = cpt->o_ycoord = FROM_LE_32(animPtr->animY); - cpt->o_frame = FROM_LE_32(animPtr->animFrame); + cpt->o_anim_x = cpt->o_xcoord = _resMan->getUint32(animPtr->animX); + cpt->o_anim_y = cpt->o_ycoord = _resMan->getUint32(animPtr->animY); + cpt->o_frame = _resMan->getUint32(animPtr->animFrame); cpt->o_resource = spr; cpt->o_status &= ~STAT_SHRINK; @@ -1116,9 +1116,9 @@ int Logic::fnISpeak(Object *cpt, int32 id, int32 cdt, int32 textNo, int32 spr, i AnimSet *animTab = (AnimSet*)((uint8*)_resMan->openFetchRes(cdt) + sizeof(Header)); animTab += cpt->o_dir; - cpt->o_anim_resource = FROM_LE_32(animTab->cdt); + cpt->o_anim_resource = _resMan->getUint32(animTab->cdt); if (animTab->cdt) - cpt->o_resource = FROM_LE_32(animTab->spr); + cpt->o_resource = _resMan->getUint32(animTab->spr); _resMan->resClose(cdt); } else { cpt->o_anim_resource = cdt; @@ -1158,8 +1158,8 @@ int Logic::fnISpeak(Object *cpt, int32 id, int32 cdt, int32 textNo, int32 spr, i textCpt->o_target = textCptId; // the graphic is a property of Text, so we don't lock/unlock it. - uint16 textSpriteWidth = FROM_LE_16(_textMan->giveSpriteData(textCpt->o_target)->width); - uint16 textSpriteHeight = FROM_LE_16(_textMan->giveSpriteData(textCpt->o_target)->height); + uint16 textSpriteWidth = _resMan->getUint16(_textMan->giveSpriteData(textCpt->o_target)->width); + uint16 textSpriteHeight = _resMan->getUint16(_textMan->giveSpriteData(textCpt->o_target)->height); cpt->o_text_id = textCptId; @@ -1717,6 +1717,8 @@ void Logic::startPosCallFn(uint8 fnId, uint32 param1, uint32 param2, uint32 para } void Logic::runStartScript(const uint8 *data) { + // Here data is a static resource defined in staticres.cpp + // It is always in little endian uint16 varId = 0; uint8 fnId = 0; uint32 param1 = 0; diff --git a/engines/sword1/mouse.cpp b/engines/sword1/mouse.cpp index eefdf99466..6e4923c304 100644 --- a/engines/sword1/mouse.cpp +++ b/engines/sword1/mouse.cpp @@ -21,7 +21,6 @@ */ #include "common/stdafx.h" -#include "common/endian.h" #include "common/system.h" #include "graphics/cursorman.h" @@ -199,33 +198,33 @@ void Mouse::createPointer(uint32 ptrId, uint32 luggageId) { if (ptrId) { MousePtr *lugg = NULL; MousePtr *ptr = (MousePtr*)_resMan->openFetchRes(ptrId); - uint16 resSizeX = FROM_LE_16(ptr->sizeX); - uint16 resSizeY = FROM_LE_16(ptr->sizeY); - uint16 noFrames = FROM_LE_16(ptr->numFrames); + uint16 resSizeX = _resMan->getLEUint16(ptr->sizeX); + uint16 resSizeY = _resMan->getLEUint16(ptr->sizeY); + uint16 noFrames = _resMan->getLEUint16(ptr->numFrames); if (luggageId) { lugg = (MousePtr*)_resMan->openFetchRes(luggageId); - resSizeX = MAX(resSizeX, (uint16)((resSizeX / 2) + FROM_LE_16(lugg->sizeX))); - resSizeY = MAX(resSizeY, (uint16)((resSizeY / 2) + FROM_LE_16(lugg->sizeY))); + resSizeX = MAX(resSizeX, (uint16)((resSizeX / 2) + _resMan->getLEUint16(lugg->sizeX))); + resSizeY = MAX(resSizeY, (uint16)((resSizeY / 2) + _resMan->getLEUint16(lugg->sizeY))); } _currentPtr = (MousePtr*)malloc(sizeof(MousePtr) + resSizeX * resSizeY * noFrames); - _currentPtr->hotSpotX = FROM_LE_16(ptr->hotSpotX); - _currentPtr->hotSpotY = FROM_LE_16(ptr->hotSpotY); + _currentPtr->hotSpotX = _resMan->getLEUint16(ptr->hotSpotX); + _currentPtr->hotSpotY = _resMan->getLEUint16(ptr->hotSpotY); _currentPtr->numFrames = noFrames; _currentPtr->sizeX = resSizeX; _currentPtr->sizeY = resSizeY; uint8 *ptrData = (uint8*)_currentPtr + sizeof(MousePtr); memset(ptrData, 255, resSizeX * resSizeY * noFrames); if (luggageId) { - uint8 *dstData = ptrData + resSizeX - FROM_LE_16(lugg->sizeX); + uint8 *dstData = ptrData + resSizeX - _resMan->getLEUint16(lugg->sizeX); for (uint32 frameCnt = 0; frameCnt < noFrames; frameCnt++) { uint8 *luggSrc = (uint8*)lugg + sizeof(MousePtr); - dstData += (resSizeY - FROM_LE_16(lugg->sizeY)) * resSizeX; - for (uint32 cnty = 0; cnty < FROM_LE_16(lugg->sizeY); cnty++) { - for (uint32 cntx = 0; cntx < FROM_LE_16(lugg->sizeX); cntx++) + dstData += (resSizeY - _resMan->getLEUint16(lugg->sizeY)) * resSizeX; + for (uint32 cnty = 0; cnty < _resMan->getLEUint16(lugg->sizeY); cnty++) { + for (uint32 cntx = 0; cntx < _resMan->getLEUint16(lugg->sizeX); cntx++) if (luggSrc[cntx]) dstData[cntx] = luggSrc[cntx]; dstData += resSizeX; - luggSrc += FROM_LE_16(lugg->sizeX); + luggSrc += _resMan->getLEUint16(lugg->sizeX); } } _resMan->resClose(luggageId); @@ -233,14 +232,14 @@ void Mouse::createPointer(uint32 ptrId, uint32 luggageId) { uint8 *dstData = ptrData; uint8 *srcData = (uint8*)ptr + sizeof(MousePtr); for (uint32 frameCnt = 0; frameCnt < noFrames; frameCnt++) { - for (uint32 cnty = 0; cnty < FROM_LE_16(ptr->sizeY); cnty++) { - for (uint32 cntx = 0; cntx < FROM_LE_16(ptr->sizeX); cntx++) + for (uint32 cnty = 0; cnty < _resMan->getLEUint16(ptr->sizeY); cnty++) { + for (uint32 cntx = 0; cntx < _resMan->getLEUint16(ptr->sizeX); cntx++) if (srcData[cntx]) dstData[cntx] = srcData[cntx]; - srcData += FROM_LE_16(ptr->sizeX); + srcData += _resMan->getLEUint16(ptr->sizeX); dstData += resSizeX; } - dstData += (resSizeY - FROM_LE_16(ptr->sizeY)) * resSizeX; + dstData += (resSizeY - _resMan->getLEUint16(ptr->sizeY)) * resSizeX; } _resMan->resClose(ptrId); } diff --git a/engines/sword1/objectman.cpp b/engines/sword1/objectman.cpp index bb21f25b13..5aab4859be 100644 --- a/engines/sword1/objectman.cpp +++ b/engines/sword1/objectman.cpp @@ -21,7 +21,6 @@ */ #include "common/stdafx.h" -#include "common/endian.h" #include "common/util.h" #include "sword1/objectman.h" @@ -88,7 +87,7 @@ uint8 ObjectMan::fnCheckForTextLine(uint32 textId) { uint8 lang = SwordEngine::_systemVars.language; uint32 *textData = (uint32*)((uint8*)_resMan->openFetchRes(_textList[textId / ITM_PER_SEC][lang]) + sizeof(Header)); - if ((textId & ITM_ID) < READ_LE_UINT32(textData)) { + if ((textId & ITM_ID) < _resMan->readUint32(textData)) { textData++; if (textData[textId & ITM_ID]) retVal = 1; @@ -100,11 +99,11 @@ uint8 ObjectMan::fnCheckForTextLine(uint32 textId) { char *ObjectMan::lockText(uint32 textId) { uint8 lang = SwordEngine::_systemVars.language; char *addr = (char*)_resMan->openFetchRes(_textList[textId / ITM_PER_SEC][lang]) + sizeof(Header); - if ((textId & ITM_ID) >= READ_LE_UINT32(addr)) { - warning("ObjectMan::lockText(%d): only %d texts in file", textId & ITM_ID, READ_LE_UINT32(addr)); + if ((textId & ITM_ID) >= _resMan->readUint32(addr)) { + warning("ObjectMan::lockText(%d): only %d texts in file", textId & ITM_ID, _resMan->readUint32(addr)); textId = 0; // get first line instead } - uint32 offset = READ_LE_UINT32(addr + ((textId & ITM_ID) + 1)* 4); + uint32 offset = _resMan->readUint32(addr + ((textId & ITM_ID) + 1)* 4); if (offset == 0) { warning("ObjectMan::lockText(%d): text number has no text lines", textId); return _errorStr; @@ -118,7 +117,7 @@ void ObjectMan::unlockText(uint32 textId) { uint32 ObjectMan::lastTextNumber(int section) { uint8 *data = (uint8*)_resMan->openFetchRes(_textList[section][SwordEngine::_systemVars.language]) + sizeof(Header); - uint32 result = READ_LE_UINT32(data) - 1; + uint32 result = _resMan->readUint32(data) - 1; _resMan->resClose(_textList[section][SwordEngine::_systemVars.language]); return result; } diff --git a/engines/sword1/resman.cpp b/engines/sword1/resman.cpp index 1397a5506e..1abc91a2e1 100644 --- a/engines/sword1/resman.cpp +++ b/engines/sword1/resman.cpp @@ -21,7 +21,6 @@ */ #include "common/stdafx.h" -#include "common/endian.h" #include "common/config-manager.h" #include "common/util.h" #include "common/str.h" @@ -49,9 +48,10 @@ namespace Sword1 { #define MAX_PATH_LEN 260 -ResMan::ResMan(const char *fileName) { +ResMan::ResMan(const char *fileName, bool isMacFile) { _openCluStart = _openCluEnd = NULL; _openClus = 0; + _isBigEndian = isMacFile; _memMan = new MemMan(); loadCluDescript(fileName); } @@ -82,6 +82,7 @@ ResMan::~ResMan(void) { } void ResMan::loadCluDescript(const char *fileName) { + // The cluster description file is always little endian (even on the mac version, whose cluster files are big endian) Common::File file; file.open(fileName); @@ -223,13 +224,9 @@ Header *ResMan::lockScript(uint32 scrID) { error("Script id %d not found.\n", scrID); scrID = _scriptList[scrID / ITM_PER_SEC]; #ifdef SCUMM_BIG_ENDIAN - MemHandle *memHandle = resHandle(scrID); - if (memHandle->cond == MEM_FREED) - openScriptResourceBigEndian(scrID); - else - resOpen(scrID); + openScriptResourceBigEndian(scrID); #else - resOpen(scrID); + openScriptResourceLittleEndian(scrID); #endif return (Header*)resHandle(scrID)->data; } @@ -240,13 +237,9 @@ void ResMan::unlockScript(uint32 scrID) { void *ResMan::cptResOpen(uint32 id) { #ifdef SCUMM_BIG_ENDIAN - MemHandle *memHandle = resHandle(id); - if (memHandle->cond == MEM_FREED) - openCptResourceBigEndian(id); - else - resOpen(id); + openCptResourceBigEndian(id); #else - resOpen(id); + openCptResourceLittleEndian(id); #endif return resHandle(id)->data; } @@ -286,9 +279,15 @@ void ResMan::resClose(uint32 id) { FrameHeader *ResMan::fetchFrame(void *resourceData, uint32 frameNo) { uint8 *frameFile = (uint8*)resourceData; uint8 *idxData = frameFile + sizeof(Header); - if (frameNo >= READ_LE_UINT32(idxData)) - error("fetchFrame:: frame %d doesn't exist in resource.", frameNo); - frameFile += READ_LE_UINT32(idxData + (frameNo+1) * 4); + if (_isBigEndian) { + if (frameNo >= READ_BE_UINT32(idxData)) + error("fetchFrame:: frame %d doesn't exist in resource.", frameNo); + frameFile += READ_BE_UINT32(idxData + (frameNo+1) * 4); + } else { + if (frameNo >= READ_LE_UINT32(idxData)) + error("fetchFrame:: frame %d doesn't exist in resource.", frameNo); + frameFile += READ_LE_UINT32(idxData + (frameNo+1) * 4); + } return (FrameHeader*)frameFile; } @@ -304,7 +303,12 @@ Common::File *ResMan::resFile(uint32 id) { } cluster->file = new Common::File(); char fileName[15]; - sprintf(fileName, "%s.CLU", _prj.clu[(id >> 24)-1].label); + // Supposes that big endian means mac cluster file and little endian means PC cluster file. + // This works, but we may want to separate the file name from the endianess or try .CLM extension if opening.clu file fail. + if (_isBigEndian) + sprintf(fileName, "%s.CLM", _prj.clu[(id >> 24)-1].label); + else + sprintf(fileName, "%s.CLU", _prj.clu[(id >> 24)-1].label); cluster->file->open(fileName); if (!cluster->file->isOpen()) { @@ -355,39 +359,114 @@ uint32 ResMan::resOffset(uint32 id) { } void ResMan::openCptResourceBigEndian(uint32 id) { + bool needByteSwap = false; + if (!_isBigEndian) { + // Cluster files are in little endian fomat. + // If the resource are not in memory anymore, and therefore will be read + // from disk, they will need to be byte swaped. + MemHandle *memHandle = resHandle(id); + needByteSwap = (memHandle->cond == MEM_FREED); + } resOpen(id); - MemHandle *handle = resHandle(id); - uint32 totSize = handle->size; - uint32 *data = (uint32*)((uint8*)handle->data + sizeof(Header)); - totSize -= sizeof(Header); - if (totSize & 3) - error("Illegal compact size for id %d: %d", id, totSize); - totSize /= 4; - for (uint32 cnt = 0; cnt < totSize; cnt++) { - *data = READ_LE_UINT32(data); - data++; + if (needByteSwap) { + MemHandle *handle = resHandle(id); + uint32 totSize = handle->size; + uint32 *data = (uint32*)((uint8*)handle->data + sizeof(Header)); + totSize -= sizeof(Header); + if (totSize & 3) + error("Illegal compact size for id %d: %d", id, totSize); + totSize /= 4; + for (uint32 cnt = 0; cnt < totSize; cnt++) { + *data = READ_LE_UINT32(data); + data++; + } + } +} + +void ResMan::openCptResourceLittleEndian(uint32 id) { + bool needByteSwap = false; + if (_isBigEndian) { + // Cluster files are in big endian fomat. + // If the resource are not in memory anymore, and therefore will be read + // from disk, they will need to be byte swaped. + MemHandle *memHandle = resHandle(id); + needByteSwap = (memHandle->cond == MEM_FREED); + } + resOpen(id); + if (needByteSwap) { + MemHandle *handle = resHandle(id); + uint32 totSize = handle->size; + uint32 *data = (uint32*)((uint8*)handle->data + sizeof(Header)); + totSize -= sizeof(Header); + if (totSize & 3) + error("Illegal compact size for id %d: %d", id, totSize); + totSize /= 4; + for (uint32 cnt = 0; cnt < totSize; cnt++) { + *data = READ_BE_UINT32(data); + data++; + } } } void ResMan::openScriptResourceBigEndian(uint32 id) { + bool needByteSwap = false; + if (!_isBigEndian) { + // Cluster files are in little endian fomat. + // If the resource are not in memory anymore, and therefore will be read + // from disk, they will need to be byte swaped. + MemHandle *memHandle = resHandle(id); + needByteSwap = (memHandle->cond == MEM_FREED); + } resOpen(id); - MemHandle *handle = resHandle(id); - // uint32 totSize = handle->size; - Header *head = (Header*)handle->data; - head->comp_length = FROM_LE_32(head->comp_length); - head->decomp_length = FROM_LE_32(head->decomp_length); - head->version = FROM_LE_16(head->version); - uint32 *data = (uint32*)((uint8*)handle->data + sizeof(Header)); - uint32 size = handle->size - sizeof(Header); - if (size & 3) - error("Odd size during script endian conversion. Resource ID =%d, size = %d", id, size); - size >>= 2; - for (uint32 cnt = 0; cnt < size; cnt++) { - *data = READ_LE_UINT32(data); - data++; + if (needByteSwap) { + MemHandle *handle = resHandle(id); + // uint32 totSize = handle->size; + Header *head = (Header*)handle->data; + head->comp_length = FROM_LE_32(head->comp_length); + head->decomp_length = FROM_LE_32(head->decomp_length); + head->version = FROM_LE_16(head->version); + uint32 *data = (uint32*)((uint8*)handle->data + sizeof(Header)); + uint32 size = handle->size - sizeof(Header); + if (size & 3) + error("Odd size during script endian conversion. Resource ID =%d, size = %d", id, size); + size >>= 2; + for (uint32 cnt = 0; cnt < size; cnt++) { + *data = READ_LE_UINT32(data); + data++; + } + } +} + +void ResMan::openScriptResourceLittleEndian(uint32 id) { + bool needByteSwap = false; + if (_isBigEndian) { + // Cluster files are in big endian fomat. + // If the resource are not in memory anymore, and therefore will be read + // from disk, they will need to be byte swaped. + MemHandle *memHandle = resHandle(id); + needByteSwap = (memHandle->cond == MEM_FREED); + } + resOpen(id); + if (needByteSwap) { + MemHandle *handle = resHandle(id); + // uint32 totSize = handle->size; + Header *head = (Header*)handle->data; + head->comp_length = FROM_BE_32(head->comp_length); + head->decomp_length = FROM_BE_32(head->decomp_length); + head->version = FROM_BE_16(head->version); + uint32 *data = (uint32*)((uint8*)handle->data + sizeof(Header)); + uint32 size = handle->size - sizeof(Header); + if (size & 3) + error("Odd size during script endian conversion. Resource ID =%d, size = %d", id, size); + size >>= 2; + for (uint32 cnt = 0; cnt < size; cnt++) { + *data = READ_BE_UINT32(data); + data++; + } } } + uint32 ResMan::_srIdList[29] = { // the file numbers differ for the control panel file IDs, so we need this array OTHER_SR_FONT, // SR_FONT 0x04050000, // SR_BUTTON diff --git a/engines/sword1/resman.h b/engines/sword1/resman.h index e2920b0a81..05cc54f92f 100644 --- a/engines/sword1/resman.h +++ b/engines/sword1/resman.h @@ -26,6 +26,7 @@ #include "sword1/memman.h" #include "common/file.h" #include "sword1/sworddefs.h" +#include "common/endian.h" namespace Sword1 { @@ -62,7 +63,7 @@ struct Prj { class ResMan { public: - ResMan(const char *fileName); + ResMan(const char *fileName, bool isMacFile); ~ResMan(void); void flush(void); void resClose(uint32 id); @@ -74,6 +75,36 @@ public: Header *lockScript(uint32 scrID); void unlockScript(uint32 scrID); FrameHeader *fetchFrame(void *resourceData, uint32 frameNo); + + uint16 getUint16(uint16 value) { + return (_isBigEndian) ? FROM_BE_16(value): FROM_LE_16(value); + } + uint32 getUint32(uint32 value) { + return (_isBigEndian) ? FROM_BE_32(value): FROM_LE_32(value); + } + uint16 getLEUint16(uint16 value) { + return FROM_LE_16(value); + } + uint32 getLEUint32(uint32 value) { + return FROM_LE_32(value); + } + uint16 readUint16(const void *ptr) { + return (_isBigEndian) ? READ_BE_UINT16(ptr): READ_LE_UINT16(ptr); + } + uint32 readUint32(const void *ptr) { + return (_isBigEndian) ? READ_BE_UINT32(ptr):READ_LE_UINT32(ptr); + } + uint32 readLEUint32(const void *ptr) { + return READ_LE_UINT32(ptr); + } + uint16 toUint16(uint16 value) { + return (_isBigEndian) ? TO_BE_16(value): TO_LE_16(value); + } + uint32 toUint32(uint32 value) { + return (_isBigEndian) ? TO_BE_32(value): TO_LE_32(value); + } + + private: uint32 resLength(uint32 id); MemHandle *resHandle(uint32 id); @@ -82,6 +113,8 @@ private: void openCptResourceBigEndian(uint32 id); void openScriptResourceBigEndian(uint32 id); + void openCptResourceLittleEndian(uint32 id); + void openScriptResourceLittleEndian(uint32 id); void loadCluDescript(const char *fileName); void freeCluDescript(void); @@ -91,6 +124,7 @@ private: static uint32 _srIdList[29]; Clu *_openCluStart, *_openCluEnd; int _openClus; + bool _isBigEndian; }; } // End of namespace Sword1 diff --git a/engines/sword1/router.cpp b/engines/sword1/router.cpp index 8b263758fb..7ca917326b 100644 --- a/engines/sword1/router.cpp +++ b/engines/sword1/router.cpp @@ -21,7 +21,6 @@ */ #include "common/stdafx.h" -#include "common/endian.h" #include "common/util.h" #include "sword1/router.h" @@ -1911,7 +1910,7 @@ int32 Router::LoadWalkResources(Object *megaObject, int32 x, int32 y, int32 dir) fPolygrid += sizeof(Header); memcpy(&floorHeader,fPolygrid,sizeof(WalkGridHeader)); fPolygrid += sizeof(WalkGridHeader); - _nBars = FROM_LE_32(floorHeader.numBars); + _nBars = _resMan->getUint32(floorHeader.numBars); if (_nBars >= O_GRID_SIZE) { @@ -1921,7 +1920,7 @@ int32 Router::LoadWalkResources(Object *megaObject, int32 x, int32 y, int32 dir) _nBars = 0; } - _nNodes = FROM_LE_32(floorHeader.numNodes)+1; //array starts at 0 begins at a start _node has nnodes nodes and a target _node + _nNodes = _resMan->getUint32(floorHeader.numNodes)+1; //array starts at 0 begins at a start _node has nnodes nodes and a target _node if (_nNodes >= O_GRID_SIZE) { @@ -1934,17 +1933,17 @@ int32 Router::LoadWalkResources(Object *megaObject, int32 x, int32 y, int32 dir) /*memmove(&_bars[0],fPolygrid,_nBars*sizeof(BarData)); fPolygrid += _nBars*sizeof(BarData);//move pointer to start of _node data*/ for (cnt = 0; cnt < _nBars; cnt++) { - _bars[cnt].x1 = READ_LE_UINT16(fPolygrid); fPolygrid += 2; - _bars[cnt].y1 = READ_LE_UINT16(fPolygrid); fPolygrid += 2; - _bars[cnt].x2 = READ_LE_UINT16(fPolygrid); fPolygrid += 2; - _bars[cnt].y2 = READ_LE_UINT16(fPolygrid); fPolygrid += 2; - _bars[cnt].xmin = READ_LE_UINT16(fPolygrid); fPolygrid += 2; - _bars[cnt].ymin = READ_LE_UINT16(fPolygrid); fPolygrid += 2; - _bars[cnt].xmax = READ_LE_UINT16(fPolygrid); fPolygrid += 2; - _bars[cnt].ymax = READ_LE_UINT16(fPolygrid); fPolygrid += 2; - _bars[cnt].dx = READ_LE_UINT16(fPolygrid); fPolygrid += 2; - _bars[cnt].dy = READ_LE_UINT16(fPolygrid); fPolygrid += 2; - _bars[cnt].co = READ_LE_UINT32(fPolygrid); fPolygrid += 4; + _bars[cnt].x1 = _resMan->readUint16(fPolygrid); fPolygrid += 2; + _bars[cnt].y1 = _resMan->readUint16(fPolygrid); fPolygrid += 2; + _bars[cnt].x2 = _resMan->readUint16(fPolygrid); fPolygrid += 2; + _bars[cnt].y2 = _resMan->readUint16(fPolygrid); fPolygrid += 2; + _bars[cnt].xmin = _resMan->readUint16(fPolygrid); fPolygrid += 2; + _bars[cnt].ymin = _resMan->readUint16(fPolygrid); fPolygrid += 2; + _bars[cnt].xmax = _resMan->readUint16(fPolygrid); fPolygrid += 2; + _bars[cnt].ymax = _resMan->readUint16(fPolygrid); fPolygrid += 2; + _bars[cnt].dx = _resMan->readUint16(fPolygrid); fPolygrid += 2; + _bars[cnt].dy = _resMan->readUint16(fPolygrid); fPolygrid += 2; + _bars[cnt].co = _resMan->readUint32(fPolygrid); fPolygrid += 4; } /*j = 1;// leave _node 0 for start _node @@ -1954,8 +1953,8 @@ int32 Router::LoadWalkResources(Object *megaObject, int32 x, int32 y, int32 dir) j ++; } while (j < _nNodes);//array starts at 0*/ for (cnt = 1; cnt < _nNodes; cnt++) { - _node[cnt].x = READ_LE_UINT16(fPolygrid); fPolygrid += 2; - _node[cnt].y = READ_LE_UINT16(fPolygrid); fPolygrid += 2; + _node[cnt].x = _resMan->readUint16(fPolygrid); fPolygrid += 2; + _node[cnt].y = _resMan->readUint16(fPolygrid); fPolygrid += 2; } //ResUnlock(walkGridResourceId); // mouse wiggle @@ -1980,17 +1979,17 @@ int32 Router::LoadWalkResources(Object *megaObject, int32 x, int32 y, int32 dir) //ResOpen(megaObject->o_mega_resource); // mouse wiggle //fMegaWalkData = ResLock(megaObject->o_mega_resource); // mouse wiggle fMegaWalkData = (uint8*)_resMan->openFetchRes(megaObject->o_mega_resource); + // Apparently this resource is in little endian in both the Mac and the PC version _nWalkFrames = fMegaWalkData[0]; _nTurnFrames = fMegaWalkData[1]; fMegaWalkData += 2; - for (cnt = 0; cnt < NO_DIRECTIONS * (_nWalkFrames + 1 + _nTurnFrames); cnt++) { - _dx[cnt] = (int32)READ_LE_UINT32(fMegaWalkData); + _dx[cnt] = (int32)_resMan->readLEUint32(fMegaWalkData); fMegaWalkData += 4; } for (cnt = 0; cnt < NO_DIRECTIONS * (_nWalkFrames + 1 + _nTurnFrames); cnt++) { - _dy[cnt] = (int32)READ_LE_UINT32(fMegaWalkData); + _dy[cnt] = (int32)_resMan->readLEUint32(fMegaWalkData); fMegaWalkData += 4; } /*memmove(&_dx[0],fMegaWalkData,NO_DIRECTIONS*(_nWalkFrames+1+_nTurnFrames)*sizeof(int32)); @@ -1999,11 +1998,11 @@ int32 Router::LoadWalkResources(Object *megaObject, int32 x, int32 y, int32 dir) fMegaWalkData += NO_DIRECTIONS*(_nWalkFrames+1+_nTurnFrames)*sizeof(int32);*/ for (cntu = 0; cntu < NO_DIRECTIONS; cntu++) { - _modX[cntu] = (int32)READ_LE_UINT32(fMegaWalkData); + _modX[cntu] = (int32)_resMan->readLEUint32(fMegaWalkData); fMegaWalkData += 4; } for (cntu = 0; cntu < NO_DIRECTIONS; cntu++) { - _modY[cntu] = (int32)READ_LE_UINT32(fMegaWalkData); + _modY[cntu] = (int32)_resMan->readLEUint32(fMegaWalkData); fMegaWalkData += 4; } /*memmove(&_modX[0],fMegaWalkData,NO_DIRECTIONS*sizeof(int32)); diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp index ba04d03d84..a3045440f5 100644 --- a/engines/sword1/screen.cpp +++ b/engines/sword1/screen.cpp @@ -21,7 +21,6 @@ */ #include "common/stdafx.h" -#include "common/endian.h" #include "common/system.h" #include "common/util.h" @@ -407,40 +406,40 @@ void Screen::processImage(uint32 id) { uint16 spriteY = compact->o_anim_y; if (compact->o_status & STAT_SHRINK) { scale = (compact->o_scale_a * compact->o_ycoord + compact->o_scale_b) / 256; - spriteX += ((int16)READ_LE_UINT16(&frameHead->offsetX) * scale) / 256; - spriteY += ((int16)READ_LE_UINT16(&frameHead->offsetY) * scale) / 256; + spriteX += ((int16)_resMan->readUint16(&frameHead->offsetX) * scale) / 256; + spriteY += ((int16)_resMan->readUint16(&frameHead->offsetY) * scale) / 256; } else { scale = 256; - spriteX += (int16)READ_LE_UINT16(&frameHead->offsetX); - spriteY += (int16)READ_LE_UINT16(&frameHead->offsetY); + spriteX += (int16)_resMan->readUint16(&frameHead->offsetX); + spriteY += (int16)_resMan->readUint16(&frameHead->offsetY); } uint8 *tonyBuf = NULL; if (frameHead->runTimeComp[3] == '7') { // RLE7 encoded? - decompressRLE7(sprData, READ_LE_UINT32(&frameHead->compSize), _rleBuffer); + decompressRLE7(sprData, _resMan->readUint32(&frameHead->compSize), _rleBuffer); sprData = _rleBuffer; } else if (frameHead->runTimeComp[3] == '0') { // RLE0 encoded? - decompressRLE0(sprData, READ_LE_UINT32(&frameHead->compSize), _rleBuffer); + decompressRLE0(sprData, _resMan->readUint32(&frameHead->compSize), _rleBuffer); sprData = _rleBuffer; } else if (frameHead->runTimeComp[1] == 'I') { // new type - tonyBuf = (uint8*)malloc(READ_LE_UINT16(&frameHead->width) * READ_LE_UINT16(&frameHead->height)); - decompressTony(sprData, READ_LE_UINT32(&frameHead->compSize), tonyBuf); + tonyBuf = (uint8*)malloc(_resMan->readUint16(&frameHead->width) * _resMan->readUint16(&frameHead->height)); + decompressTony(sprData, _resMan->readUint32(&frameHead->compSize), tonyBuf); sprData = tonyBuf; } uint16 sprSizeX, sprSizeY; if (compact->o_status & STAT_SHRINK) { - sprSizeX = (scale * READ_LE_UINT16(&frameHead->width)) / 256; - sprSizeY = (scale * READ_LE_UINT16(&frameHead->height)) / 256; - fastShrink(sprData, READ_LE_UINT16(&frameHead->width), READ_LE_UINT16(&frameHead->height), scale, _shrinkBuffer); + sprSizeX = (scale * _resMan->readUint16(&frameHead->width)) / 256; + sprSizeY = (scale * _resMan->readUint16(&frameHead->height)) / 256; + fastShrink(sprData, _resMan->readUint16(&frameHead->width), _resMan->readUint16(&frameHead->height), scale, _shrinkBuffer); sprData = _shrinkBuffer; } else { - sprSizeX = READ_LE_UINT16(&frameHead->width); - sprSizeY = READ_LE_UINT16(&frameHead->height); + sprSizeX = _resMan->readUint16(&frameHead->width); + sprSizeY = _resMan->readUint16(&frameHead->height); } if (!(compact->o_status & STAT_OVERRIDE)) { //mouse size linked to exact size & coordinates of sprite box - shrink friendly - if (READ_LE_UINT16(&frameHead->offsetX) || READ_LE_UINT16(&frameHead->offsetY)) { + if (_resMan->readUint16(&frameHead->offsetX) || _resMan->readUint16(&frameHead->offsetY)) { //for megas the mouse area is reduced to account for sprite not //filling the box size is reduced to 1/2 width, 4/5 height compact->o_mouse_x1 = spriteX + sprSizeX / 4; @@ -495,7 +494,7 @@ void Screen::verticalMask(uint16 x, uint16 y, uint16 bWidth, uint16 bHeight) { uint16 *grid = _layerGrid[level] + gridX + blkx + gridY * lGridSizeX; for (int16 blky = bHeight - 1; blky >= 0; blky--) { if (*grid) { - uint8 *blkData = _layerBlocks[level + 1] + (READ_LE_UINT16(grid) - 1) * 128; + uint8 *blkData = _layerBlocks[level + 1] + (_resMan->readUint16(grid) - 1) * 128; blitBlockClear(x + blkx, y + blky, blkData); } else break; @@ -520,7 +519,7 @@ void Screen::blitBlockClear(uint16 x, uint16 y, uint8 *data) { void Screen::renderParallax(uint8 *data) { ParallaxHeader *header = (ParallaxHeader*)data; uint32 *lineIndexes = (uint32*)(data + sizeof(ParallaxHeader)); - assert((FROM_LE_16(header->sizeX) >= SCREEN_WIDTH) && (FROM_LE_16(header->sizeY) >= SCREEN_DEPTH)); + assert((_resMan->getUint16(header->sizeX) >= SCREEN_WIDTH) && (_resMan->getUint16(header->sizeY) >= SCREEN_DEPTH)); uint16 paraScrlX, paraScrlY; uint16 scrnScrlX, scrnScrlY; @@ -533,19 +532,19 @@ void Screen::renderParallax(uint8 *data) { scrnHeight = SCREEN_DEPTH + ABS((int32)_oldScrollY - (int32)Logic::_scriptVars[SCROLL_OFFSET_Y]); if (_scrnSizeX != SCREEN_WIDTH) { - double scrlfx = (FROM_LE_16(header->sizeX) - SCREEN_WIDTH) / ((double)(_scrnSizeX - SCREEN_WIDTH)); + double scrlfx = (_resMan->getUint16(header->sizeX) - SCREEN_WIDTH) / ((double)(_scrnSizeX - SCREEN_WIDTH)); paraScrlX = (uint16)(scrnScrlX * scrlfx); } else paraScrlX = 0; if (_scrnSizeY != SCREEN_DEPTH) { - double scrlfy = (FROM_LE_16(header->sizeY) - SCREEN_DEPTH) / ((double)(_scrnSizeY - SCREEN_DEPTH)); + double scrlfy = (_resMan->getUint16(header->sizeY) - SCREEN_DEPTH) / ((double)(_scrnSizeY - SCREEN_DEPTH)); paraScrlY = (uint16)(scrnScrlY * scrlfy); } else paraScrlY = 0; for (uint16 cnty = 0; cnty < scrnHeight; cnty++) { - uint8 *src = data + READ_LE_UINT32(lineIndexes + cnty + paraScrlY); + uint8 *src = data + _resMan->readUint32(lineIndexes + cnty + paraScrlY); uint8 *dest = _screenBuf + scrnScrlX + (cnty + scrnScrlY) * _scrnSizeX; uint16 remain = paraScrlX; uint16 xPos = 0; @@ -655,7 +654,7 @@ void Screen::addToGraphicList(uint8 listId, uint32 objId) { if (!(cpt->o_status & STAT_SHRINK)) { // not a boxed mega using shrinking Header *frameRaw = (Header*)_resMan->openFetchRes(cpt->o_resource); FrameHeader *frameHead = _resMan->fetchFrame(frameRaw, cpt->o_frame); - _sortList[_sortLength].y += READ_LE_UINT16(&frameHead->height) - 1; // now pointing to base of sprite + _sortList[_sortLength].y += _resMan->readUint16(&frameHead->height) - 1; // now pointing to base of sprite _resMan->resClose(cpt->o_resource); } _sortLength++; @@ -803,9 +802,9 @@ void Screen::showFrame(uint16 x, uint16 y, uint32 resId, uint32 frameNo, const b FrameHeader *frameHead = _resMan->fetchFrame(_resMan->openFetchRes(resId), frameNo); uint8 *frameData = ((uint8*)frameHead) + sizeof(FrameHeader); - for (i = 0; i < FROM_LE_16(frameHead->height); i++) { - for (j = 0; j < FROM_LE_16(frameHead->height); j++) { - frame[(i + 4) * 40 + j + 2] = frameData[i * FROM_LE_16(frameHead->width) + j]; + for (i = 0; i < _resMan->getUint16(frameHead->height); i++) { + for (j = 0; j < _resMan->getUint16(frameHead->height); j++) { + frame[(i + 4) * 40 + j + 2] = frameData[i * _resMan->getUint16(frameHead->width) + j]; } } diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp index 88c8063c08..485091bece 100644 --- a/engines/sword1/sword1.cpp +++ b/engines/sword1/sword1.cpp @@ -51,16 +51,27 @@ static const PlainGameDescriptor sword1FullSettings = {"sword1", "Broken Sword 1: The Shadow of the Templars"}; static const PlainGameDescriptor sword1DemoSettings = {"sword1demo", "Broken Sword 1: The Shadow of the Templars (Demo)"}; +static const PlainGameDescriptor sword1MacFullSettings = + {"sword1mac", "Broken Sword 1: The Shadow of the Templars (Mac)"}; +static const PlainGameDescriptor sword1MacDemoSettings = + {"sword1macdemo", "Broken Sword 1: The Shadow of the Templars (Mac demo)"}; // check these subdirectories (if present) static const char *g_dirNames[] = { "clusters", "speech" }; -#define NUM_FILES_TO_CHECK 5 +#define NUM_COMMON_FILES_TO_CHECK 1 +#define NUM_PC_FILES_TO_CHECK 3 +#define NUM_MAC_FILES_TO_CHECK 3 +#define NUM_DEMO_FILES_TO_CHECK 1 +#define NUM_FILES_TO_CHECK NUM_COMMON_FILES_TO_CHECK + NUM_PC_FILES_TO_CHECK + NUM_MAC_FILES_TO_CHECK + NUM_DEMO_FILES_TO_CHECK static const char *g_filesToCheck[NUM_FILES_TO_CHECK] = { // these files have to be found - "swordres.rif", - "general.clu", - "compacts.clu", - "scripts.clu", + "swordres.rif", // Mac and PC version + "general.clu", // PC version only + "compacts.clu", // PC version only + "scripts.clu", // PC version only + "general.clm", // Mac version only + "compacts.clm", // Mac version only + "scripts.clm", // Mac version only "cows.mad", // this one should only exist in the demo version // the engine needs several more files to work, but checking these should be sufficient }; @@ -69,6 +80,8 @@ GameList Engine_SWORD1_gameIDList() { GameList games; games.push_back(sword1FullSettings); games.push_back(sword1DemoSettings); + games.push_back(sword1MacFullSettings); + //games.push_back(sword1MacDemoSettings); return games; } @@ -77,6 +90,10 @@ GameDescriptor Engine_SWORD1_findGameID(const char *gameid) { return sword1FullSettings; if (0 == scumm_stricmp(gameid, sword1DemoSettings.gameid)) return sword1DemoSettings; + if (0 == scumm_stricmp(gameid, sword1MacFullSettings.gameid)) + return sword1MacFullSettings; + //if (0 == scumm_stricmp(gameid, sword1MacDemoSettings.gameid)) + // return sword1MacDemoSettings; return GameDescriptor(); } @@ -99,22 +116,38 @@ void Sword1CheckDirectory(const FSList &fslist, bool *filesFound) { } DetectedGameList Engine_SWORD1_detectGames(const FSList &fslist) { - int i; + int i, j; DetectedGameList detectedGames; bool filesFound[NUM_FILES_TO_CHECK]; for (i = 0; i < NUM_FILES_TO_CHECK; i++) filesFound[i] = false; - + Sword1CheckDirectory(fslist, filesFound); bool mainFilesFound = true; - for (i = 0; i < NUM_FILES_TO_CHECK -1; i++) + bool pcFilesFound = true; + bool macFilesFound = true; + bool demoFilesFound = true; + for (i = 0; i < NUM_COMMON_FILES_TO_CHECK; i++) if (!filesFound[i]) mainFilesFound = false; + for (j = 0; j < NUM_PC_FILES_TO_CHECK; i++, j++) + if (!filesFound[i]) + pcFilesFound = false; + for (j = 0; j < NUM_MAC_FILES_TO_CHECK; i++, j++) + if (!filesFound[i]) + macFilesFound = false; + for (j = 0; j < NUM_DEMO_FILES_TO_CHECK; i++, j++) + if (!filesFound[i]) + demoFilesFound = false; - if (mainFilesFound && filesFound[NUM_FILES_TO_CHECK - 1]) + if (mainFilesFound && pcFilesFound && demoFilesFound) detectedGames.push_back(sword1DemoSettings); - else if (mainFilesFound) + else if (mainFilesFound && pcFilesFound) detectedGames.push_back(sword1FullSettings); + //else if (mainFilesFound && macFilesFound && demoFilesFound) + // detectedGames.push_back(sword1MacDemoSettings); + else if (mainFilesFound && macFilesFound) + detectedGames.push_back(sword1MacFullSettings); return detectedGames; } @@ -134,11 +167,11 @@ SystemVars SwordEngine::_systemVars; SwordEngine::SwordEngine(OSystem *syst) : Engine(syst) { - if (0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1demo")) + if ( 0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1demo") || + 0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1macdemo") ) _features = GF_DEMO; else - _features = 0; - + _features = 0; if (!_mixer->isReady()) warning("Sound initialization failed"); @@ -172,11 +205,17 @@ int SwordEngine::init() { initCommonGFX(true); _system->initSize(640, 480); _system->endGFXTransaction(); + + if ( 0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1mac") || + 0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1macdemo") ) + _systemVars.isMac = true; + else + _systemVars.isMac = false; checkCdFiles(); debug(5, "Starting resource manager"); - _resMan = new ResMan("swordres.rif"); + _resMan = new ResMan("swordres.rif", _systemVars.isMac); debug(5, "Starting object manager"); _objectMan = new ObjectMan(_resMan); _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, Audio::Mixer::kMaxMixerVolume); @@ -287,7 +326,7 @@ static const char *errorMsgs[] = { "Please copy these files from their corresponding CDs:\n" }; -const CdFile SwordEngine::_cdFileList[] = { +const CdFile SwordEngine::_pcCdFileList[] = { { "paris2.clu", FLAG_CD1 }, { "ireland.clu", FLAG_CD2 }, { "paris3.clu", FLAG_CD1 }, @@ -316,29 +355,84 @@ const CdFile SwordEngine::_cdFileList[] = { #endif }; +const CdFile SwordEngine::_macCdFileList[] = { + { "paris2.clm", FLAG_CD1 }, + { "ireland.clm", FLAG_CD2 }, + { "paris3.clm", FLAG_CD1 }, + { "paris4.clm", FLAG_CD1 }, + { "scotland.clm", FLAG_CD2 }, + { "spain.clm", FLAG_CD2 }, + { "syria.clm", FLAG_CD2 }, + { "train.clm", FLAG_CD2 }, + { "compacts.clm", FLAG_CD1 | FLAG_DEMO | FLAG_IMMED }, + { "general.clm", FLAG_CD1 | FLAG_DEMO | FLAG_IMMED }, + { "maps.clm", FLAG_CD1 | FLAG_DEMO }, + { "paris1.clm", FLAG_CD1 | FLAG_DEMO }, + { "scripts.clm", FLAG_CD1 | FLAG_DEMO | FLAG_IMMED }, + { "swordres.rif", FLAG_CD1 | FLAG_DEMO | FLAG_IMMED }, + { "text.clm", FLAG_CD1 | FLAG_DEMO }, + { "cows.mad", FLAG_DEMO }, + { "speech1.clu", FLAG_SPEECH1 }, + { "speech2.clu", FLAG_SPEECH2 } +#ifdef USE_MAD + ,{ "speech1.cl3", FLAG_SPEECH1 }, + { "speech2.cl3", FLAG_SPEECH2 } +#endif +#ifdef USE_VORBIS + ,{ "speech1.clv", FLAG_SPEECH1 }, + { "speech2.clv", FLAG_SPEECH2 } +#endif +}; + + void SwordEngine::showFileErrorMsg(uint8 type, bool *fileExists) { char msg[1024]; int missCnt = 0, missNum = 0; - for (int i = 0; i < ARRAYSIZE(_cdFileList); i++) - if (!fileExists[i]) { - missCnt++; - missNum = i; + + if (_systemVars.isMac) { + for (int i = 0; i < ARRAYSIZE(_macCdFileList); i++) + if (!fileExists[i]) { + missCnt++; + missNum = i; + } + assert(missCnt > 0); // this function shouldn't get called if there's nothing missing. + warning("%d files missing", missCnt); + int msgId = (type == TYPE_IMMED) ? 0 : 2; + if (missCnt == 1) { + sprintf(msg, errorMsgs[msgId], + _macCdFileList[missNum].name, (_macCdFileList[missNum].flags & FLAG_CD2) ? 2 : 1); + warning(msg); + } else { + char *pos = msg + sprintf(msg, errorMsgs[msgId + 1], missCnt); + warning(msg); + for (int i = 0; i < ARRAYSIZE(_macCdFileList); i++) + if (!fileExists[i]) { + warning("\"%s\" (CD %d)", _macCdFileList[i].name, (_macCdFileList[i].flags & FLAG_CD2) ? 2 : 1); + pos += sprintf(pos, "\"%s\" (CD %d)\n", _macCdFileList[i].name, (_macCdFileList[i].flags & FLAG_CD2) ? 2 : 1); + } } - assert(missCnt > 0); // this function shouldn't get called if there's nothing missing. - warning("%d files missing", missCnt); - int msgId = (type == TYPE_IMMED) ? 0 : 2; - if (missCnt == 1) { - sprintf(msg, errorMsgs[msgId], - _cdFileList[missNum].name, (_cdFileList[missNum].flags & FLAG_CD2) ? 2 : 1); - warning(msg); } else { - char *pos = msg + sprintf(msg, errorMsgs[msgId + 1], missCnt); - warning(msg); - for (int i = 0; i < ARRAYSIZE(_cdFileList); i++) + for (int i = 0; i < ARRAYSIZE(_pcCdFileList); i++) if (!fileExists[i]) { - warning("\"%s\" (CD %d)", _cdFileList[i].name, (_cdFileList[i].flags & FLAG_CD2) ? 2 : 1); - pos += sprintf(pos, "\"%s\" (CD %d)\n", _cdFileList[i].name, (_cdFileList[i].flags & FLAG_CD2) ? 2 : 1); + missCnt++; + missNum = i; } + assert(missCnt > 0); // this function shouldn't get called if there's nothing missing. + warning("%d files missing", missCnt); + int msgId = (type == TYPE_IMMED) ? 0 : 2; + if (missCnt == 1) { + sprintf(msg, errorMsgs[msgId], + _pcCdFileList[missNum].name, (_pcCdFileList[missNum].flags & FLAG_CD2) ? 2 : 1); + warning(msg); + } else { + char *pos = msg + sprintf(msg, errorMsgs[msgId + 1], missCnt); + warning(msg); + for (int i = 0; i < ARRAYSIZE(_pcCdFileList); i++) + if (!fileExists[i]) { + warning("\"%s\" (CD %d)", _pcCdFileList[i].name, (_pcCdFileList[i].flags & FLAG_CD2) ? 2 : 1); + pos += sprintf(pos, "\"%s\" (CD %d)\n", _pcCdFileList[i].name, (_pcCdFileList[i].flags & FLAG_CD2) ? 2 : 1); + } + } } GUI::MessageDialog dialog(msg); dialog.runModal(); @@ -356,17 +450,33 @@ void SwordEngine::checkCdFiles(void) { // check if we're running from cd, hdd or _systemVars.playSpeech = true; // check all files and look out if we can find a file that wouldn't exist if this was the demo version - for (int fcnt = 0; fcnt < ARRAYSIZE(_cdFileList); fcnt++) { - if (Common::File::exists(_cdFileList[fcnt].name)) { - fileExists[fcnt] = true; - flagsToBool(foundTypes, _cdFileList[fcnt].flags); - if (!(_cdFileList[fcnt].flags & FLAG_DEMO)) - isFullVersion = true; - if (_cdFileList[fcnt].flags & FLAG_CD2) - cd2FilesFound = true; - } else { - flagsToBool(missingTypes, _cdFileList[fcnt].flags); - fileExists[fcnt] = false; + if (_systemVars.isMac) { + for (int fcnt = 0; fcnt < ARRAYSIZE(_macCdFileList); fcnt++) { + if (Common::File::exists(_macCdFileList[fcnt].name)) { + fileExists[fcnt] = true; + flagsToBool(foundTypes, _macCdFileList[fcnt].flags); + if (!(_macCdFileList[fcnt].flags & FLAG_DEMO)) + isFullVersion = true; + if (_macCdFileList[fcnt].flags & FLAG_CD2) + cd2FilesFound = true; + } else { + flagsToBool(missingTypes, _macCdFileList[fcnt].flags); + fileExists[fcnt] = false; + } + } + } else { + for (int fcnt = 0; fcnt < ARRAYSIZE(_pcCdFileList); fcnt++) { + if (Common::File::exists(_pcCdFileList[fcnt].name)) { + fileExists[fcnt] = true; + flagsToBool(foundTypes, _pcCdFileList[fcnt].flags); + if (!(_pcCdFileList[fcnt].flags & FLAG_DEMO)) + isFullVersion = true; + if (_pcCdFileList[fcnt].flags & FLAG_CD2) + cd2FilesFound = true; + } else { + flagsToBool(missingTypes, _pcCdFileList[fcnt].flags); + fileExists[fcnt] = false; + } } } @@ -388,13 +498,23 @@ void SwordEngine::checkCdFiles(void) { // check if we're running from cd, hdd or somethingMissing |= missingTypes[i]; if (somethingMissing) { // okay, there *are* files missing // first, update the fileExists[] array depending on our changed missingTypes - for (int fileCnt = 0; fileCnt < ARRAYSIZE(_cdFileList); fileCnt++) - if (!fileExists[fileCnt]) { - fileExists[fileCnt] = true; - for (int flagCnt = 0; flagCnt < 8; flagCnt++) - if (missingTypes[flagCnt] && ((_cdFileList[fileCnt].flags & (1 << flagCnt)) != 0)) - fileExists[fileCnt] = false; // this is one of the files we were looking for - } + if (_systemVars.isMac) { + for (int fileCnt = 0; fileCnt < ARRAYSIZE(_macCdFileList); fileCnt++) + if (!fileExists[fileCnt]) { + fileExists[fileCnt] = true; + for (int flagCnt = 0; flagCnt < 8; flagCnt++) + if (missingTypes[flagCnt] && ((_macCdFileList[fileCnt].flags & (1 << flagCnt)) != 0)) + fileExists[fileCnt] = false; // this is one of the files we were looking for + } + } else { + for (int fileCnt = 0; fileCnt < ARRAYSIZE(_pcCdFileList); fileCnt++) + if (!fileExists[fileCnt]) { + fileExists[fileCnt] = true; + for (int flagCnt = 0; flagCnt < 8; flagCnt++) + if (missingTypes[flagCnt] && ((_pcCdFileList[fileCnt].flags & (1 << flagCnt)) != 0)) + fileExists[fileCnt] = false; // this is one of the files we were looking for + } + } if (missingTypes[TYPE_IMMED]) { // important files missing, can't start the game without them showFileErrorMsg(TYPE_IMMED, fileExists); diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h index 798e26d541..0052c576ec 100644 --- a/engines/sword1/sword1.h +++ b/engines/sword1/sword1.h @@ -63,6 +63,7 @@ struct SystemVars { uint8 showText; uint8 language; bool isDemo; + bool isMac; uint8 cutscenePackVersion; }; @@ -100,7 +101,8 @@ private: Music *_music; Control *_control; static const uint8 _cdList[TOTAL_SECTIONS]; - static const CdFile _cdFileList[]; + static const CdFile _pcCdFileList[]; + static const CdFile _macCdFileList[]; }; } // End of namespace Sword1 diff --git a/engines/sword1/text.cpp b/engines/sword1/text.cpp index f227ca11f9..3b28ed5691 100644 --- a/engines/sword1/text.cpp +++ b/engines/sword1/text.cpp @@ -48,7 +48,7 @@ Text::Text(ObjectMan *pObjMan, ResMan *pResMan, bool czechVersion) { _font = (uint8*)_resMan->openFetchRes(_fontId); _joinWidth = charWidth( SPACE ) - 2 * OVERLAP; - _charHeight = FROM_LE_16(_resMan->fetchFrame(_font, 0)->height); // all chars have the same height + _charHeight = _resMan->getUint16(_resMan->fetchFrame(_font, 0)->height); // all chars have the same height _textBlocks[0] = _textBlocks[1] = NULL; } @@ -92,8 +92,8 @@ void Text::makeTextSprite(uint8 slot, uint8 *text, uint16 maxWidth, uint8 pen) { memcpy( _textBlocks[slot]->runTimeComp, "Nu ", 4); _textBlocks[slot]->compSize = 0; - _textBlocks[slot]->width = TO_LE_16(sprWidth); - _textBlocks[slot]->height = TO_LE_16(sprHeight); + _textBlocks[slot]->width = _resMan->toUint16(sprWidth); + _textBlocks[slot]->height = _resMan->toUint16(sprHeight); _textBlocks[slot]->offsetX = 0; _textBlocks[slot]->offsetY = 0; @@ -111,7 +111,7 @@ void Text::makeTextSprite(uint8 slot, uint8 *text, uint16 maxWidth, uint8 pen) { uint16 Text::charWidth(uint8 ch) { if (ch < SPACE) ch = 64; - return FROM_LE_16(_resMan->fetchFrame(_font, ch - SPACE)->width); + return _resMan->getUint16(_resMan->fetchFrame(_font, ch - SPACE)->width); } uint16 Text::analyzeSentence(uint8 *text, uint16 maxWidth, LineInfo *line) { @@ -158,8 +158,8 @@ uint16 Text::copyChar(uint8 ch, uint8 *sprPtr, uint16 sprWidth, uint8 pen) { FrameHeader *chFrame = _resMan->fetchFrame(_font, ch - SPACE); uint8 *chData = ((uint8*)chFrame) + sizeof(FrameHeader); uint8 *dest = sprPtr; - for (uint16 cnty = 0; cnty < FROM_LE_16(chFrame->height); cnty++) { - for (uint16 cntx = 0; cntx < FROM_LE_16(chFrame->width); cntx++) { + for (uint16 cnty = 0; cnty < _resMan->getUint16(chFrame->height); cnty++) { + for (uint16 cntx = 0; cntx < _resMan->getUint16(chFrame->width); cntx++) { if (*chData == LETTER_COL) dest[cntx] = pen; else if ((*chData == BORDER_COL) && (!dest[cntx])) // don't do a border if there's already a color underneath (chars can overlap) @@ -168,7 +168,7 @@ uint16 Text::copyChar(uint8 ch, uint8 *sprPtr, uint16 sprWidth, uint8 pen) { } dest += sprWidth; } - return FROM_LE_16(chFrame->width); + return _resMan->getUint16(chFrame->width); } FrameHeader *Text::giveSpriteData(uint32 textTarget) { -- cgit v1.2.3