- Removed _gameVersion, engine versions are set in the game detection entries now
- Renamed ProjectReader -> ResourceReader - Added some WIP code for the EGA version of the Manhole (still not working/disabled) - The resource reader now closes the files it has opened correctly when it's deleted svn-id: r35877
This commit is contained in:
parent
d53a340a4d
commit
68a20e2aba
5 changed files with 177 additions and 66 deletions
|
@ -92,7 +92,7 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_RTZ,
|
||||
0,
|
||||
GF_CD,
|
||||
0,
|
||||
3,
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -109,7 +109,7 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_RTZ,
|
||||
0,
|
||||
GF_CD_COMPRESSED,
|
||||
0,
|
||||
3,
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -125,7 +125,7 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_RTZ,
|
||||
0,
|
||||
GF_CD,
|
||||
0,
|
||||
3,
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -141,7 +141,7 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_RTZ,
|
||||
0,
|
||||
GF_CD_COMPRESSED,
|
||||
0,
|
||||
3,
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -158,7 +158,7 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_RTZ,
|
||||
0,
|
||||
GF_CD,
|
||||
0,
|
||||
3,
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -174,7 +174,7 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_RTZ,
|
||||
0,
|
||||
GF_CD_COMPRESSED,
|
||||
0,
|
||||
3,
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -192,7 +192,7 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_RTZ,
|
||||
0,
|
||||
GF_CD,
|
||||
0,
|
||||
3,
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -210,7 +210,7 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_RTZ,
|
||||
0,
|
||||
GF_CD_COMPRESSED,
|
||||
0,
|
||||
3,
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -226,7 +226,7 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_RTZ,
|
||||
0,
|
||||
GF_FLOPPY,
|
||||
0,
|
||||
3,
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -242,7 +242,7 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_RTZ,
|
||||
0,
|
||||
GF_DEMO,
|
||||
0,
|
||||
3,
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -258,9 +258,27 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_MANHOLE,
|
||||
0,
|
||||
GF_CD,
|
||||
0,
|
||||
2,
|
||||
},
|
||||
|
||||
#if 0
|
||||
{
|
||||
// The Manhole (EGA, 5.25")
|
||||
{
|
||||
"manhole",
|
||||
"EGA",
|
||||
AD_ENTRY1("manhole.dat", "2b1658292599a861c4cd3cf6cdb3c581"),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformPC,
|
||||
Common::ADGF_NO_FLAGS
|
||||
},
|
||||
GID_MANHOLE,
|
||||
0,
|
||||
GF_FLOPPY,
|
||||
1,
|
||||
},
|
||||
#endif
|
||||
|
||||
{
|
||||
// Leather Goddesses of Phobos 2
|
||||
{
|
||||
|
@ -274,7 +292,7 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_LGOP2,
|
||||
0,
|
||||
GF_FLOPPY,
|
||||
0,
|
||||
2,
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -290,7 +308,7 @@ static const MadeGameDescription gameDescriptions[] = {
|
|||
GID_RODNEY,
|
||||
0,
|
||||
GF_FLOPPY,
|
||||
0,
|
||||
2,
|
||||
},
|
||||
|
||||
{ AD_TABLE_END_MARKER, 0, 0, 0, 0 }
|
||||
|
@ -382,7 +400,7 @@ const Common::ADGameDescription *MadeMetaEngine::fallbackDetect(const Common::FS
|
|||
// Set default values for the fallback descriptor's MadeGameDescription part.
|
||||
Made::g_fallbackDesc.gameID = 0;
|
||||
Made::g_fallbackDesc.features = 0;
|
||||
Made::g_fallbackDesc.version = 0;
|
||||
Made::g_fallbackDesc.version = 3;
|
||||
|
||||
//return (const Common::ADGameDescription *)&Made::g_fallbackDesc;
|
||||
return NULL;
|
||||
|
|
|
@ -81,7 +81,7 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng
|
|||
_system->openCD(cd_num);
|
||||
|
||||
_pmvPlayer = new PmvPlayer(this, _mixer);
|
||||
_res = new ProjectReader();
|
||||
_res = new ResourceReader();
|
||||
_screen = new Screen(this);
|
||||
|
||||
if (getGameID() == GID_LGOP2 || getGameID() == GID_MANHOLE || getGameID() == GID_RODNEY) {
|
||||
|
@ -107,15 +107,22 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng
|
|||
//_music->setAdlib(adlib);
|
||||
|
||||
// Set default sound frequency
|
||||
// Return to Zork sets it itself via a script funtion
|
||||
if (getGameID() == GID_MANHOLE || getGameID() == GID_RODNEY) {
|
||||
switch (getGameID()) {
|
||||
case GID_RODNEY:
|
||||
_soundRate = 11025;
|
||||
} else {
|
||||
break;
|
||||
case GID_MANHOLE:
|
||||
_soundRate = getVersion() == 2 ? 11025 : 4000;
|
||||
break;
|
||||
case GID_LGOP2:
|
||||
_soundRate = 8000;
|
||||
break;
|
||||
case GID_RTZ:
|
||||
// Return to Zork sets it itself via a script funtion
|
||||
break;
|
||||
}
|
||||
|
||||
syncSoundSettings();
|
||||
|
||||
}
|
||||
|
||||
MadeEngine::~MadeEngine() {
|
||||
|
@ -245,7 +252,6 @@ Common::Error MadeEngine::go() {
|
|||
resetAllTimers();
|
||||
|
||||
if (getGameID() == GID_RTZ) {
|
||||
_engineVersion = 3;
|
||||
if (getFeatures() & GF_DEMO) {
|
||||
_dat->open("demo.dat");
|
||||
_res->open("demo.prj");
|
||||
|
@ -262,15 +268,17 @@ Common::Error MadeEngine::go() {
|
|||
error("Unknown RTZ game features");
|
||||
}
|
||||
} else if (getGameID() == GID_MANHOLE) {
|
||||
_engineVersion = 2;
|
||||
_dat->open("manhole.dat");
|
||||
|
||||
if (getVersion() == 2) {
|
||||
_res->open("manhole.prj");
|
||||
} else {
|
||||
_res->openResourceBlocks();
|
||||
}
|
||||
} else if (getGameID() == GID_LGOP2) {
|
||||
_engineVersion = 2;
|
||||
_dat->open("lgop2.dat");
|
||||
_res->open("lgop2.prj");
|
||||
} else if (getGameID() == GID_RODNEY) {
|
||||
_engineVersion = 2;
|
||||
_dat->open("rodneys.dat");
|
||||
_res->open("rodneys.prj");
|
||||
} else {
|
||||
|
@ -280,6 +288,22 @@ Common::Error MadeEngine::go() {
|
|||
_autoStopSound = false;
|
||||
_eventNum = _eventKey = _eventMouseX = _eventMouseY = 0;
|
||||
|
||||
#if 0
|
||||
// V1 test code
|
||||
if (getVersion() == 1) {
|
||||
// Music test (works)
|
||||
_music->playSMF(_res->getMidi(1));
|
||||
|
||||
// SFX test (not working)
|
||||
Audio::SoundHandle audioStreamHandle;
|
||||
SoundResource *soundRes = _res->getSound(1);
|
||||
_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &audioStreamHandle,
|
||||
soundRes->getAudioStream(_soundRate, false));
|
||||
|
||||
quitGame();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DUMP_SCRIPTS
|
||||
_script->dumpAllScripts();
|
||||
#else
|
||||
|
|
|
@ -67,7 +67,7 @@ const uint32 kTimerResolution = 40;
|
|||
|
||||
struct MadeGameDescription;
|
||||
|
||||
class ProjectReader;
|
||||
class ResourceReader;
|
||||
class PmvPlayer;
|
||||
class Screen;
|
||||
class ScriptInterpreter;
|
||||
|
@ -105,7 +105,7 @@ public:
|
|||
private:
|
||||
public:
|
||||
PmvPlayer *_pmvPlayer;
|
||||
ProjectReader *_res;
|
||||
ResourceReader *_res;
|
||||
Screen *_screen;
|
||||
GameDatabase *_dat;
|
||||
ScriptInterpreter *_script;
|
||||
|
@ -120,10 +120,6 @@ public:
|
|||
uint _soundEnergyIndex;
|
||||
SoundEnergyArray *_soundEnergyArray;
|
||||
|
||||
// 2 = LGOP2, Manhole N&E
|
||||
// 3 = Return to Zork
|
||||
int _engineVersion;
|
||||
|
||||
int32 _timers[50];
|
||||
int16 getTicks();
|
||||
int16 getTimer(int16 timerNum);
|
||||
|
|
|
@ -103,7 +103,6 @@ AnimationResource::~AnimationResource() {
|
|||
}
|
||||
|
||||
void AnimationResource::load(byte *source, int size) {
|
||||
|
||||
Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size);
|
||||
|
||||
sourceS->readUint32LE();
|
||||
|
@ -148,7 +147,6 @@ void AnimationResource::load(byte *source, int size) {
|
|||
}
|
||||
|
||||
delete sourceS;
|
||||
|
||||
}
|
||||
|
||||
/* SoundResource */
|
||||
|
@ -162,7 +160,6 @@ SoundResource::~SoundResource() {
|
|||
}
|
||||
|
||||
void SoundResource::load(byte *source, int size) {
|
||||
|
||||
uint16 chunkCount = READ_LE_UINT16(source + 8);
|
||||
uint16 chunkSize = READ_LE_UINT16(source + 12);
|
||||
|
||||
|
@ -172,7 +169,6 @@ void SoundResource::load(byte *source, int size) {
|
|||
_soundEnergyArray = new SoundEnergyArray;
|
||||
|
||||
decompressSound(source + 14, _soundData, chunkSize, chunkCount, _soundEnergyArray);
|
||||
|
||||
}
|
||||
|
||||
Audio::AudioStream *SoundResource::getAudioStream(int soundRate, bool loop) {
|
||||
|
@ -183,6 +179,14 @@ Audio::AudioStream *SoundResource::getAudioStream(int soundRate, bool loop) {
|
|||
return Audio::makeLinearInputStream(_soundData, _soundSize, soundRate, flags, 0, 0);
|
||||
}
|
||||
|
||||
void SoundResourceV1::load(byte *source, int size) {
|
||||
// TODO: This is all wrong. Seems like the sound is compressed
|
||||
// but where is the compression info? (chunks, chunk size)
|
||||
_soundSize = size;
|
||||
_soundData = new byte[_soundSize];
|
||||
memcpy(_soundData, source, _soundSize);
|
||||
}
|
||||
|
||||
/* MenuResource */
|
||||
|
||||
MenuResource::MenuResource() {
|
||||
|
@ -281,16 +285,24 @@ void GenericResource::load(byte *source, int size) {
|
|||
memcpy(_data, source, size);
|
||||
}
|
||||
|
||||
/* ProjectReader */
|
||||
/* ResourceReader */
|
||||
|
||||
ProjectReader::ProjectReader() {
|
||||
ResourceReader::ResourceReader() {
|
||||
_isV1 = false;
|
||||
}
|
||||
|
||||
ProjectReader::~ProjectReader() {
|
||||
ResourceReader::~ResourceReader() {
|
||||
if (!_isV1) {
|
||||
delete _fd;
|
||||
} else {
|
||||
delete _fdPics;
|
||||
delete _fdSounds;
|
||||
delete _fdMusic;
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectReader::open(const char *filename) {
|
||||
|
||||
// V2
|
||||
void ResourceReader::open(const char *filename) {
|
||||
_fd = new Common::File();
|
||||
_fd->open(filename);
|
||||
|
||||
|
@ -326,38 +338,72 @@ void ProjectReader::open(const char *filename) {
|
|||
}
|
||||
|
||||
_cacheCount = 0;
|
||||
|
||||
}
|
||||
|
||||
PictureResource *ProjectReader::getPicture(int index) {
|
||||
// V1
|
||||
void ResourceReader::openResourceBlocks() {
|
||||
_isV1 = true;
|
||||
_fdPics = new Common::File();
|
||||
_fdSounds = new Common::File();
|
||||
_fdMusic = new Common::File();
|
||||
|
||||
openResourceBlock("pics.blk", _fdPics, kResFLEX);
|
||||
openResourceBlock("snds.blk", _fdSounds, kResSNDS);
|
||||
openResourceBlock("music.blk", _fdMusic, kResMIDI);
|
||||
}
|
||||
|
||||
void ResourceReader::openResourceBlock(const char *filename, Common::File *blockFile, uint32 resType) {
|
||||
blockFile->open(filename);
|
||||
|
||||
blockFile->readUint16LE(); // Skip unused
|
||||
uint16 count = blockFile->readUint16LE();
|
||||
blockFile->readUint16LE(); // Skip unused
|
||||
uint32 type = blockFile->readUint32BE();
|
||||
if (type != kResFLEX)
|
||||
warning("openResourceBlocks: resource header is not 'FLEX'");
|
||||
|
||||
_resSlots[resType] = new ResourceSlots();
|
||||
|
||||
for (uint16 i = 0; i < count; i++) {
|
||||
uint32 offset = blockFile->readUint32LE();
|
||||
blockFile->readUint32LE();
|
||||
uint32 size = blockFile->readUint32LE();
|
||||
_resSlots[resType]->push_back(ResourceSlot(offset, size));
|
||||
}
|
||||
}
|
||||
|
||||
PictureResource *ResourceReader::getPicture(int index) {
|
||||
return createResource<PictureResource>(kResFLEX, index);
|
||||
}
|
||||
|
||||
AnimationResource *ProjectReader::getAnimation(int index) {
|
||||
AnimationResource *ResourceReader::getAnimation(int index) {
|
||||
return createResource<AnimationResource>(kResANIM, index);
|
||||
}
|
||||
|
||||
SoundResource *ProjectReader::getSound(int index) {
|
||||
SoundResource *ResourceReader::getSound(int index) {
|
||||
if (!_isV1)
|
||||
return createResource<SoundResource>(kResSNDS, index);
|
||||
else
|
||||
return createResource<SoundResourceV1>(kResSNDS, index);
|
||||
}
|
||||
|
||||
MenuResource *ProjectReader::getMenu(int index) {
|
||||
MenuResource *ResourceReader::getMenu(int index) {
|
||||
return createResource<MenuResource>(kResMENU, index);
|
||||
}
|
||||
|
||||
FontResource *ProjectReader::getFont(int index) {
|
||||
FontResource *ResourceReader::getFont(int index) {
|
||||
return createResource<FontResource>(kResFONT, index);
|
||||
}
|
||||
|
||||
GenericResource *ProjectReader::getXmidi(int index) {
|
||||
GenericResource *ResourceReader::getXmidi(int index) {
|
||||
return createResource<GenericResource>(kResXMID, index);
|
||||
}
|
||||
|
||||
GenericResource *ProjectReader::getMidi(int index) {
|
||||
GenericResource *ResourceReader::getMidi(int index) {
|
||||
return createResource<GenericResource>(kResMIDI, index);
|
||||
}
|
||||
|
||||
void ProjectReader::loadIndex(ResourceSlots *slots) {
|
||||
void ResourceReader::loadIndex(ResourceSlots *slots) {
|
||||
_fd->readUint32LE(); // skip INDX
|
||||
_fd->readUint32LE(); // skip index size
|
||||
_fd->readUint32LE(); // skip unknown
|
||||
|
@ -372,16 +418,17 @@ void ProjectReader::loadIndex(ResourceSlots *slots) {
|
|||
}
|
||||
}
|
||||
|
||||
void ProjectReader::freeResource(Resource *resource) {
|
||||
void ResourceReader::freeResource(Resource *resource) {
|
||||
tossResourceFromCache(resource->slot);
|
||||
}
|
||||
|
||||
bool ProjectReader::loadResource(ResourceSlot *slot, byte *&buffer, uint32 &size) {
|
||||
bool ResourceReader::loadResource(ResourceSlot *slot, byte *&buffer, uint32 &size) {
|
||||
int offset = !_isV1 ? 62 : 0;
|
||||
if (slot && slot->size > 0) {
|
||||
size = slot->size - 62;
|
||||
size = slot->size - offset;
|
||||
buffer = new byte[size];
|
||||
debug(2, "ProjectReader::loadResource() %08X", slot->offs + 62);
|
||||
_fd->seek(slot->offs + 62);
|
||||
debug(2, "ResourceReader::loadResource() %08X", slot->offs + offset);
|
||||
_fd->seek(slot->offs + offset);
|
||||
_fd->read(buffer, size);
|
||||
return true;
|
||||
} else {
|
||||
|
@ -389,7 +436,7 @@ bool ProjectReader::loadResource(ResourceSlot *slot, byte *&buffer, uint32 &size
|
|||
}
|
||||
}
|
||||
|
||||
ResourceSlot *ProjectReader::getResourceSlot(uint32 resType, uint index) {
|
||||
ResourceSlot *ResourceReader::getResourceSlot(uint32 resType, uint index) {
|
||||
ResourceSlots *slots = _resSlots[resType];
|
||||
if (index >= 1 && index < slots->size()) {
|
||||
return &slots->operator[](index);
|
||||
|
@ -398,13 +445,13 @@ ResourceSlot *ProjectReader::getResourceSlot(uint32 resType, uint index) {
|
|||
}
|
||||
}
|
||||
|
||||
Resource *ProjectReader::getResourceFromCache(ResourceSlot *slot) {
|
||||
Resource *ResourceReader::getResourceFromCache(ResourceSlot *slot) {
|
||||
if (slot->res)
|
||||
slot->refCount++;
|
||||
return slot->res;
|
||||
}
|
||||
|
||||
void ProjectReader::addResourceToCache(ResourceSlot *slot, Resource *res) {
|
||||
void ResourceReader::addResourceToCache(ResourceSlot *slot, Resource *res) {
|
||||
if (_cacheCount >= kMaxResourceCacheCount)
|
||||
purgeCache();
|
||||
slot->res = res;
|
||||
|
@ -412,13 +459,13 @@ void ProjectReader::addResourceToCache(ResourceSlot *slot, Resource *res) {
|
|||
_cacheCount++;
|
||||
}
|
||||
|
||||
void ProjectReader::tossResourceFromCache(ResourceSlot *slot) {
|
||||
void ResourceReader::tossResourceFromCache(ResourceSlot *slot) {
|
||||
if (slot->res)
|
||||
slot->refCount--;
|
||||
}
|
||||
|
||||
void ProjectReader::purgeCache() {
|
||||
debug(2, "ProjectReader::purgeCache()");
|
||||
void ResourceReader::purgeCache() {
|
||||
debug(2, "ResourceReader::purgeCache()");
|
||||
for (ResMap::const_iterator resTypeIter = _resSlots.begin(); resTypeIter != _resSlots.end(); ++resTypeIter) {
|
||||
ResourceSlots *slots = (*resTypeIter)._value;
|
||||
for (ResourceSlots::iterator slotIter = slots->begin(); slotIter != slots->end(); ++slotIter) {
|
||||
|
|
|
@ -103,8 +103,8 @@ protected:
|
|||
class SoundResource : public Resource {
|
||||
public:
|
||||
SoundResource();
|
||||
~SoundResource();
|
||||
void load(byte *source, int size);
|
||||
virtual ~SoundResource();
|
||||
virtual void load(byte *source, int size);
|
||||
Audio::AudioStream *getAudioStream(int soundRate, bool loop = false);
|
||||
SoundEnergyArray *getSoundEnergyArray() const { return _soundEnergyArray; }
|
||||
protected:
|
||||
|
@ -113,6 +113,13 @@ protected:
|
|||
SoundEnergyArray *_soundEnergyArray;
|
||||
};
|
||||
|
||||
class SoundResourceV1 : public SoundResource {
|
||||
public:
|
||||
SoundResourceV1() {}
|
||||
~SoundResourceV1() {}
|
||||
void load(byte *source, int size);
|
||||
};
|
||||
|
||||
class MenuResource : public Resource {
|
||||
public:
|
||||
MenuResource();
|
||||
|
@ -162,13 +169,13 @@ struct ResourceSlot {
|
|||
}
|
||||
};
|
||||
|
||||
class ProjectReader {
|
||||
class ResourceReader {
|
||||
public:
|
||||
|
||||
ProjectReader();
|
||||
~ProjectReader();
|
||||
ResourceReader();
|
||||
~ResourceReader();
|
||||
|
||||
void open(const char *filename);
|
||||
void openResourceBlocks();
|
||||
|
||||
PictureResource *getPicture(int index);
|
||||
AnimationResource *getAnimation(int index);
|
||||
|
@ -183,9 +190,12 @@ public:
|
|||
protected:
|
||||
|
||||
Common::File *_fd;
|
||||
Common::File *_fdPics, *_fdSounds, *_fdMusic; // V1
|
||||
bool _isV1;
|
||||
|
||||
typedef Common::Array<ResourceSlot> ResourceSlots;
|
||||
typedef Common::HashMap<uint32, ResourceSlots*> ResMap;
|
||||
void openResourceBlock(const char *filename, Common::File *blockFile, uint32 resType);
|
||||
|
||||
ResMap _resSlots;
|
||||
int _cacheCount;
|
||||
|
@ -201,6 +211,22 @@ protected:
|
|||
if (!res) {
|
||||
byte *buffer;
|
||||
uint32 size;
|
||||
|
||||
// Read from the correct file for V1 games
|
||||
if (_isV1) {
|
||||
switch (resType) {
|
||||
case kResSNDS:
|
||||
_fd = _fdSounds;
|
||||
break;
|
||||
case kResMIDI:
|
||||
_fd = _fdMusic;
|
||||
break;
|
||||
default:
|
||||
_fd = _fdPics;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (loadResource(slot, buffer, size)) {
|
||||
res = new T();
|
||||
res->slot = slot;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue