MADS: Implemented resource manager using ScummVM Archive interface
This commit is contained in:
parent
de384bae2e
commit
4581b26b12
7 changed files with 294 additions and 37 deletions
|
@ -46,9 +46,9 @@ MadsPack::MadsPack(Common::SeekableReadStream *stream) {
|
|||
}
|
||||
|
||||
MadsPack::MadsPack(const Common::String &resourceName, MADSEngine *vm) {
|
||||
Common::SeekableReadStream *stream = vm->_resources->get(resourceName);
|
||||
Common::SeekableReadStream *stream = nullptr; //vm->_resources->get(resourceName);
|
||||
initialise(stream);
|
||||
vm->_resources->toss(resourceName);
|
||||
// vm->_resources->toss(resourceName);
|
||||
}
|
||||
|
||||
void MadsPack::initialise(Common::SeekableReadStream *stream) {
|
||||
|
|
|
@ -233,7 +233,7 @@ void FontM4::setFont(const Common::String &filename) {
|
|||
_sysFont = false;
|
||||
_filename = filename;
|
||||
|
||||
Common::SeekableReadStream *fontFile = _vm->_resources->openFile(filename);
|
||||
Common::SeekableReadStream *fontFile = nullptr; //_vm->_resources->openFile(filename);
|
||||
|
||||
if (fontFile->readUint32LE() != MKTAG('F', 'O', 'N', 'T')) {
|
||||
warning("Font: FONT tag expected");
|
||||
|
@ -272,7 +272,7 @@ void FontM4::setFont(const Common::String &filename) {
|
|||
_charData = new uint8[fontSize];
|
||||
fontFile->read(_charData, fontSize);
|
||||
|
||||
_vm->_resources->toss(filename);
|
||||
// _vm->_resources->toss(filename);
|
||||
}
|
||||
|
||||
int FontM4::getBpp(int charWidth) {
|
||||
|
|
|
@ -72,10 +72,10 @@ void MADSEngine::initialise() {
|
|||
MSurface::setVm(this);
|
||||
MSprite::setVm(this);
|
||||
|
||||
ResourcesManager::init(this);
|
||||
_events = new EventsManager(this);
|
||||
_palette = Palette::init(this);
|
||||
_font = Font::init(this);
|
||||
_resources = new ResourcesManager(this);
|
||||
_screen = MSurface::init(true);
|
||||
_sound = new SoundManager(this, _mixer);
|
||||
_userInterface = UserInterface::init(this);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "mads/mads.h"
|
||||
#include "mads/msprite.h"
|
||||
#include "mads/msurface.h"
|
||||
#include "mads/resources.h"
|
||||
|
||||
namespace MADS {
|
||||
|
||||
|
@ -412,14 +413,14 @@ void MSurfaceMADS::loadBackground(int roomNumber, RGBList **palData) {
|
|||
tileMap[i] = mapStream->readUint16LE();
|
||||
delete mapStream;
|
||||
|
||||
_vm->_resources->toss(resourceName);
|
||||
// _vm->_resources->toss(resourceName);
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// Tile map data, which needs to be kept compressed, as the tile offsets refer to
|
||||
// the compressed data. Each tile is then uncompressed separately
|
||||
sprintf(resourceName, "rm%d.tt", roomNumber);
|
||||
Common::SeekableReadStream *tileDataComp = _vm->_resources->get(resourceName);
|
||||
Common::SeekableReadStream *tileDataComp = nullptr; //_vm->_resources->get(resourceName);
|
||||
MadsPack tileData(tileDataComp);
|
||||
Common::SeekableReadStream *tileDataUncomp = tileData.getItemStream(0);
|
||||
|
||||
|
@ -499,7 +500,7 @@ void MSurfaceMADS::loadBackground(int roomNumber, RGBList **palData) {
|
|||
}
|
||||
}
|
||||
tileSet.clear();
|
||||
_vm->_resources->toss(resourceName);
|
||||
// _vm->_resources->toss(resourceName);
|
||||
}
|
||||
|
||||
void MSurfaceMADS::loadInterface(int index, RGBList **palData) {
|
||||
|
@ -534,10 +535,10 @@ void MSurfaceNebular::loadBackground(int roomNumber, RGBList **palData) {
|
|||
empty();
|
||||
|
||||
Common::String resourceName = Common::String::format("rm%d.art", roomNumber);
|
||||
Common::SeekableReadStream *stream = _vm->_resources->get(resourceName);
|
||||
Common::SeekableReadStream *stream = nullptr; //_vm->_resources->get(resourceName);
|
||||
loadBackgroundStream(stream, palData);
|
||||
|
||||
_vm->_resources->toss(resourceName);
|
||||
// _vm->_resources->toss(resourceName);
|
||||
}
|
||||
|
||||
void MSurfaceNebular::loadBackgroundStream(Common::SeekableReadStream *source, RGBList **palData) {
|
||||
|
@ -597,10 +598,10 @@ void MSurfaceM4::loadBackground(int roomNumber, RGBList **palData) {
|
|||
if (palData)
|
||||
*palData = NULL;
|
||||
Common::String resourceName = Common::String::format("%i.tt", roomNumber);
|
||||
Common::SeekableReadStream *stream = _vm->_resources->get(resourceName);
|
||||
Common::SeekableReadStream *stream = nullptr;//_vm->_resources->get(resourceName);
|
||||
loadBackgroundStream(stream);
|
||||
|
||||
_vm->_resources->toss(resourceName);
|
||||
// _vm->_resources->toss(resourceName);
|
||||
}
|
||||
|
||||
void MSurfaceM4::loadBackgroundStream(Common::SeekableReadStream *source) {
|
||||
|
@ -663,15 +664,11 @@ void MSurfaceM4::loadBackgroundStream(Common::SeekableReadStream *source) {
|
|||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void MSurfaceRiddle::loadBackground(const Common::String &sceneName) {
|
||||
char resourceName[20];
|
||||
Common::SeekableReadStream *stream;
|
||||
// Loads a Riddle scene
|
||||
Common::String resName = Common::String::format("%s.tt", sceneName.c_str());
|
||||
stream = _vm->_resources->get(resourceName);
|
||||
File stream(resName);
|
||||
|
||||
loadBackgroundStream(stream);
|
||||
|
||||
_vm->_resources->toss(resourceName);
|
||||
loadBackgroundStream(&stream);
|
||||
}
|
||||
|
||||
} // End of namespace MADS
|
||||
|
|
|
@ -31,6 +31,8 @@ namespace MADS {
|
|||
namespace Nebular {
|
||||
|
||||
class CopyProtectionDialog {
|
||||
private:
|
||||
|
||||
public:
|
||||
static bool show() { return false; }
|
||||
};
|
||||
|
|
|
@ -21,12 +21,267 @@
|
|||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/archive.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "mads/mads.h"
|
||||
#include "mads/resources.h"
|
||||
|
||||
namespace MADS {
|
||||
|
||||
ResourcesManager::ResourcesManager(MADSEngine *vm) {
|
||||
_vm = vm;
|
||||
enum ResourceType {RESTYPE_ROOM, RESTYPE_SC, RESTYPE_TEXT, RESTYPE_QUO, RESTYPE_I,
|
||||
RESTYPE_OB, RESTYPE_FONT, RESTYPE_SOUND, RESTYPE_SPEECH, RESTYPE_HAS_EXT, RESTYPE_NO_EXT};
|
||||
|
||||
/**
|
||||
* HAG Archives implementation
|
||||
*/
|
||||
class HagArchive : public Common::Archive {
|
||||
private:
|
||||
/**
|
||||
* Details of a single entry in a HAG file index
|
||||
*/
|
||||
struct HagEntry {
|
||||
Common::String _resourceName;
|
||||
uint32 _offset;
|
||||
uint32 _size;
|
||||
|
||||
HagEntry(): _offset(0), _size(0) {}
|
||||
HagEntry(Common::String resourceName, uint32 offset, uint32 size):
|
||||
_resourceName(resourceName), _offset(offset), _size(size) {}
|
||||
};
|
||||
|
||||
class HagIndex {
|
||||
public:
|
||||
Common::List<HagEntry> _entries;
|
||||
Common::String _filename;
|
||||
};
|
||||
|
||||
Common::Array<HagIndex> _index;
|
||||
|
||||
/**
|
||||
* Load the index of all the game's HAG files
|
||||
*/
|
||||
void loadIndex();
|
||||
|
||||
/**
|
||||
* Given a resource name, opens up the correct HAG file and returns whether
|
||||
* an entry with the given name exists.
|
||||
*/
|
||||
bool getHeaderEntry(const Common::String &resourceName, HagIndex &hagIndex, HagEntry &hagEntry) const;
|
||||
|
||||
/**
|
||||
* Returns the HAG resource filename that will contain a given resource
|
||||
*/
|
||||
Common::String getResourceFilename(const Common::String &resourceName) const;
|
||||
|
||||
/**
|
||||
* Return a resource type given a resource name
|
||||
*/
|
||||
ResourceType getResourceType(const Common::String &resourceName) const;
|
||||
public:
|
||||
HagArchive();
|
||||
virtual ~HagArchive();
|
||||
|
||||
// Archive implementation
|
||||
virtual bool hasFile(const Common::String &name) const;
|
||||
virtual int listMembers(Common::ArchiveMemberList &list) const;
|
||||
virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
|
||||
virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
|
||||
};
|
||||
|
||||
void ResourcesManager::init(MADSEngine *vm) {
|
||||
if (vm->getGameFeatures() & GF_MADS)
|
||||
SearchMan.add("HAG", new HagArchive());
|
||||
else
|
||||
error("Unsupported game engine");
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void File::openFile(const Common::String &filename) {
|
||||
if (!Common::File::open(filename))
|
||||
error("Could not open file - %s", filename.c_str());
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
const char *const MADSCONCAT_STRING = "MADSCONCAT";
|
||||
|
||||
HagArchive::HagArchive() {
|
||||
loadIndex();
|
||||
}
|
||||
|
||||
HagArchive::~HagArchive() {
|
||||
}
|
||||
|
||||
// Archive implementation
|
||||
bool HagArchive::hasFile(const Common::String &name) const {
|
||||
HagIndex hagIndex;
|
||||
HagEntry hagEntry;
|
||||
return getHeaderEntry(name, hagIndex, hagEntry);
|
||||
}
|
||||
|
||||
int HagArchive::listMembers(Common::ArchiveMemberList &list) const {
|
||||
int members = 0;
|
||||
|
||||
for (uint hagCtr = 0; hagCtr < _index.size(); ++hagCtr) {
|
||||
HagIndex hagIndex = _index[hagCtr];
|
||||
Common::List<HagEntry>::iterator i;
|
||||
|
||||
for (i = hagIndex._entries.begin(); i != hagIndex._entries.end(); ++i) {
|
||||
list.push_back(Common::ArchiveMemberList::value_type(
|
||||
new Common::GenericArchiveMember((*i)._resourceName, this)));
|
||||
++members;
|
||||
}
|
||||
}
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
const Common::ArchiveMemberPtr HagArchive::getMember(const Common::String &name) const {
|
||||
if (!hasFile(name))
|
||||
return Common::ArchiveMemberPtr();
|
||||
|
||||
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *HagArchive::createReadStreamForMember(const Common::String &name) const {
|
||||
HagIndex hagIndex;
|
||||
HagEntry hagEntry;
|
||||
|
||||
if (getHeaderEntry(name, hagIndex, hagEntry)) {
|
||||
// Entry found. If the correct file is not already open, open it
|
||||
Common::File f;
|
||||
if (!f.open(hagIndex._filename))
|
||||
error("Could not open HAG file");
|
||||
|
||||
// Return a substream for the specific resource
|
||||
return new Common::SeekableSubReadStream(&f,
|
||||
hagEntry._offset, hagEntry._size, DisposeAfterUse::YES);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void HagArchive::loadIndex() {
|
||||
Common::File hagFile;
|
||||
|
||||
for (int sectionIndex = -1; sectionIndex < 10; ++sectionIndex) {
|
||||
Common::String filename = (sectionIndex == -1) ? "GLOBAL.HAG" :
|
||||
Common::String::format("SECTION%d.HAG", sectionIndex);
|
||||
if (!hagFile.open(filename))
|
||||
error("Could not locate HAG file - %s", filename.c_str());
|
||||
|
||||
// Check for header
|
||||
char headerBuffer[16];
|
||||
if ((hagFile.read(headerBuffer, 16) != 16) ||
|
||||
(strncmp(headerBuffer, MADSCONCAT_STRING, 10) != 0))
|
||||
error("Invalid HAG file opened");
|
||||
|
||||
// Scan through the HAG index
|
||||
int numEntries = hagFile.readUint16LE();
|
||||
|
||||
HagIndex hagIndex;
|
||||
for (int idx = 0; idx < numEntries; ++idx) {
|
||||
// Read in the details of the next resource
|
||||
char resourceBuffer[14];
|
||||
uint32 offset = hagFile.readUint32LE();
|
||||
uint32 size = hagFile.readUint32LE();
|
||||
hagFile.read(resourceBuffer, 14);
|
||||
|
||||
hagIndex._entries.push_back(HagEntry(resourceBuffer, offset, size));
|
||||
}
|
||||
|
||||
hagFile.close();
|
||||
_index.push_back(hagIndex);
|
||||
}
|
||||
}
|
||||
|
||||
bool HagArchive::getHeaderEntry(const Common::String &resourceName,
|
||||
HagIndex &hagIndex, HagEntry &hagEntry) const {
|
||||
Common::String resName = resourceName;
|
||||
resName.toUppercase();
|
||||
if (resName[0] == '*')
|
||||
resName.deleteChar(0);
|
||||
|
||||
Common::String hagFilename = getResourceFilename(resName);
|
||||
|
||||
// Find the index for the given file
|
||||
for (uint hagCtr = 0; hagCtr < _index.size(); ++hagCtr) {
|
||||
hagIndex = _index[hagCtr];
|
||||
|
||||
if (hagIndex._filename == hagFilename) {
|
||||
Common::List<HagEntry>::iterator ei;
|
||||
for (ei = hagIndex._entries.begin(); ei != hagIndex._entries.end(); ++ei) {
|
||||
hagEntry = *ei;
|
||||
if (hagEntry._resourceName == resName)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::String HagArchive::getResourceFilename(const Common::String &resourceName) const {
|
||||
ResourceType resType = getResourceType(resourceName);
|
||||
Common::String outputFilename = "GLOBAL.HAG";
|
||||
|
||||
if ((resType == RESTYPE_ROOM) || (resType == RESTYPE_SC)) {
|
||||
int value = atoi(resourceName.c_str() + 2);
|
||||
int hagFileNum = (resType == RESTYPE_ROOM) ? value / 100 : value;
|
||||
|
||||
if (hagFileNum > 0)
|
||||
outputFilename = Common::String::format("SECTION%d.HAG", hagFileNum);
|
||||
}
|
||||
|
||||
if (resType == RESTYPE_SPEECH)
|
||||
outputFilename = "SPEECH.HAG";
|
||||
|
||||
return outputFilename;
|
||||
}
|
||||
|
||||
ResourceType HagArchive::getResourceType(const Common::String &resourceName) const {
|
||||
if (resourceName.hasPrefix("RM")) {
|
||||
// Room resource
|
||||
return RESTYPE_ROOM;
|
||||
} else if (resourceName.hasPrefix("SC")) {
|
||||
// SC resource
|
||||
return RESTYPE_SC;
|
||||
} else if (resourceName.hasSuffix(".TXT")) {
|
||||
// Text resource
|
||||
return RESTYPE_TEXT;
|
||||
} else if (resourceName.hasSuffix(".QUO")) {
|
||||
// QUO resource
|
||||
return RESTYPE_QUO;
|
||||
} else if (resourceName.hasPrefix("I")) {
|
||||
// I resource
|
||||
return RESTYPE_I;
|
||||
} else if (resourceName.hasPrefix("OB")) {
|
||||
// OB resource
|
||||
return RESTYPE_OB;
|
||||
} else if (resourceName.hasPrefix("FONT")) {
|
||||
// FONT resource
|
||||
return RESTYPE_FONT;
|
||||
} else if (resourceName.hasPrefix("SOUND")) {
|
||||
// SOUND resource
|
||||
return RESTYPE_SOUND;
|
||||
} else if (resourceName.hasPrefix("SPCHC")) {
|
||||
// SPEECH resource
|
||||
return RESTYPE_SPEECH;
|
||||
}
|
||||
|
||||
// Check for a known extension
|
||||
const char *extPos = strchr(resourceName.c_str(), '.');
|
||||
if (extPos) {
|
||||
++extPos;
|
||||
if (!strcmp(extPos, "FL") || !strcmp(extPos, "LBM") || !strcmp(extPos, "ANM") ||
|
||||
!strcmp(extPos, "AA") || !strcmp(extPos, "SS")) {
|
||||
return RESTYPE_HAS_EXT;
|
||||
}
|
||||
}
|
||||
|
||||
return RESTYPE_NO_EXT;
|
||||
}
|
||||
|
||||
} // End of namespace MADS
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#define MADS_RESOURCES_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/file.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MADS {
|
||||
|
@ -32,29 +32,32 @@ namespace MADS {
|
|||
class MADSEngine;
|
||||
|
||||
class ResourcesManager {
|
||||
private:
|
||||
MADSEngine *_vm;
|
||||
public:
|
||||
ResourcesManager(MADSEngine *vm);
|
||||
/**
|
||||
* Instantiates the resource manager
|
||||
*/
|
||||
static void init(MADSEngine *vm);
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived file class
|
||||
*/
|
||||
class File: public Common::File {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
File(): Common::File() {}
|
||||
|
||||
/**
|
||||
* Return a named resource
|
||||
* Constructor
|
||||
*/
|
||||
Common::SeekableReadStream *get(const Common::String &resourceName, bool loadFlag = false) {
|
||||
// TODO
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *openFile(const Common::String &resourceName) {
|
||||
return get(resourceName, false);
|
||||
}
|
||||
File(const Common::String &filename) { openFile(filename); }
|
||||
|
||||
/**
|
||||
* Release a previously loaded resource
|
||||
* Opens the given file, throwing an error if it can't be opened
|
||||
*/
|
||||
void toss(const Common::String &resourceName) {
|
||||
// TODO
|
||||
}
|
||||
void openFile(const Common::String &filename);
|
||||
};
|
||||
|
||||
} // End of namespace MADS
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue