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
This commit is contained in:
Eugene Sandulenko 2006-11-12 19:05:51 +00:00
parent 6e66bf5051
commit 3e6414a55f
12 changed files with 451 additions and 213 deletions

View file

@ -91,6 +91,9 @@ FORCEINLINE uint16 SWAP_BYTES_16(uint16 a) {
#define FROM_LE_32(a) ((uint32)(a))
#define FROM_LE_16(a) ((uint16)(a))
#define FROM_BE_32(a) SWAP_BYTES_32(a)
#define FROM_BE_16(a) SWAP_BYTES_16(a)
#define TO_LE_32(a) ((uint32)(a))
#define TO_LE_16(a) ((uint16)(a))
@ -111,6 +114,9 @@ FORCEINLINE uint16 SWAP_BYTES_16(uint16 a) {
#define FROM_LE_32(a) SWAP_BYTES_32(a)
#define FROM_LE_16(a) SWAP_BYTES_16(a)
#define FROM_BE_32(a) ((uint32)(a))
#define FROM_BE_16(a) ((uint16)(a))
#define TO_LE_32(a) SWAP_BYTES_32(a)
#define TO_LE_16(a) SWAP_BYTES_16(a)

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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);
#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);
#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 (_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,6 +303,11 @@ Common::File *ResMan::resFile(uint32 id) {
}
cluster->file = new Common::File();
char fileName[15];
// 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);
@ -355,7 +359,16 @@ 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);
if (needByteSwap) {
MemHandle *handle = resHandle(id);
uint32 totSize = handle->size;
uint32 *data = (uint32*)((uint8*)handle->data + sizeof(Header));
@ -368,9 +381,44 @@ void ResMan::openCptResourceBigEndian(uint32 id) {
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);
if (needByteSwap) {
MemHandle *handle = resHandle(id);
// uint32 totSize = handle->size;
Header *head = (Header*)handle->data;
@ -387,6 +435,37 @@ void ResMan::openScriptResourceBigEndian(uint32 id) {
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

View file

@ -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

View file

@ -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));

View file

@ -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];
}
}

View file

@ -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,7 +116,7 @@ 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++)
@ -107,14 +124,30 @@ DetectedGameList Engine_SWORD1_detectGames(const FSList &fslist) {
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,12 +167,12 @@ 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;
if (!_mixer->isReady())
warning("Sound initialization failed");
@ -173,10 +206,16 @@ int SwordEngine::init() {
_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,10 +355,42 @@ 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 (_systemVars.isMac) {
for (int i = 0; i < ARRAYSIZE(_macCdFileList); i++)
if (!fileExists[i]) {
missCnt++;
missNum = i;
@ -329,15 +400,38 @@ void SwordEngine::showFileErrorMsg(uint8 type, bool *fileExists) {
int msgId = (type == TYPE_IMMED) ? 0 : 2;
if (missCnt == 1) {
sprintf(msg, errorMsgs[msgId],
_cdFileList[missNum].name, (_cdFileList[missNum].flags & FLAG_CD2) ? 2 : 1);
_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(_cdFileList); i++)
for (int i = 0; i < ARRAYSIZE(_macCdFileList); 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);
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);
}
}
} else {
for (int i = 0; i < ARRAYSIZE(_pcCdFileList); 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],
_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);
@ -356,19 +450,35 @@ 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)) {
if (_systemVars.isMac) {
for (int fcnt = 0; fcnt < ARRAYSIZE(_macCdFileList); fcnt++) {
if (Common::File::exists(_macCdFileList[fcnt].name)) {
fileExists[fcnt] = true;
flagsToBool(foundTypes, _cdFileList[fcnt].flags);
if (!(_cdFileList[fcnt].flags & FLAG_DEMO))
flagsToBool(foundTypes, _macCdFileList[fcnt].flags);
if (!(_macCdFileList[fcnt].flags & FLAG_DEMO))
isFullVersion = true;
if (_cdFileList[fcnt].flags & FLAG_CD2)
if (_macCdFileList[fcnt].flags & FLAG_CD2)
cd2FilesFound = true;
} else {
flagsToBool(missingTypes, _cdFileList[fcnt].flags);
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;
}
}
}
if (((_features & GF_DEMO) == 0) != isFullVersion) // shouldn't happen...
warning("Your Broken Sword 1 version looks like a %s version but you are starting it as a %s version", isFullVersion ? "full" : "demo", (_features & GF_DEMO) ? "demo" : "full");
@ -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 (_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] && ((_cdFileList[fileCnt].flags & (1 << flagCnt)) != 0))
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);

View file

@ -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

View file

@ -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) {