MACVENTURE: Complete text decoding

This commit is contained in:
Borja Lorente 2016-06-25 17:38:15 +02:00
parent 499ebc0b54
commit 8dd52b6cce
10 changed files with 167 additions and 74 deletions

View file

@ -174,6 +174,7 @@ void Gui::setWindowTitle(WindowReference winID, Common::String string) {
void Gui::updateWindowInfo(WindowReference ref, ObjID objID, const Common::Array<ObjID> &children) { void Gui::updateWindowInfo(WindowReference ref, ObjID objID, const Common::Array<ObjID> &children) {
WindowData &data = findWindowData(ref); WindowData &data = findWindowData(ref);
data.children.clear(); data.children.clear();
data.objRef = objID;
uint32 originx = 0x7fff; uint32 originx = 0x7fff;
uint32 originy = 0x7fff; uint32 originy = 0x7fff;
for (uint i = 0; i < children.size(); i++) { for (uint i = 0; i < children.size(); i++) {
@ -224,6 +225,8 @@ void Gui::initGUI() {
initWindows(); initWindows();
assignObjReferences();
if (!loadControls()) if (!loadControls())
error("Could not load controls"); error("Could not load controls");
@ -238,51 +241,55 @@ void Gui::initWindows() {
_controlsWindow->setDimensions(getWindowData(kCommandsWindow).bounds); _controlsWindow->setDimensions(getWindowData(kCommandsWindow).bounds);
_controlsWindow->setActive(false); _controlsWindow->setActive(false);
_controlsWindow->setCallback(commandsWindowCallback, this); _controlsWindow->setCallback(commandsWindowCallback, this);
loadBorder(_controlsWindow, "border_command.bmp", false); //loadBorder(_controlsWindow, "border_command.bmp", false);
loadBorder(_controlsWindow, "border_command.bmp", true); //loadBorder(_controlsWindow, "border_command.bmp", true);
// Main Game Window // Main Game Window
_mainGameWindow = _wm.addWindow(false, false, false); _mainGameWindow = _wm.addWindow(false, false, false);
_mainGameWindow->setDimensions(getWindowData(kMainGameWindow).bounds); _mainGameWindow->setDimensions(getWindowData(kMainGameWindow).bounds);
_mainGameWindow->setActive(false); _mainGameWindow->setActive(false);
_mainGameWindow->setCallback(mainGameWindowCallback, this); _mainGameWindow->setCallback(mainGameWindowCallback, this);
loadBorder(_mainGameWindow, "border_no_scroll_inac.bmp", false); //loadBorder(_mainGameWindow, "border_no_scroll_inac.bmp", false);
loadBorder(_mainGameWindow, "border_no_scroll_act.bmp", true); //loadBorder(_mainGameWindow, "border_no_scroll_act.bmp", true);
findWindowData(kMainGameWindow).objRef = 3;
// In-game Output Console // In-game Output Console
_outConsoleWindow = _wm.addWindow(false, true, true); _outConsoleWindow = _wm.addWindow(false, true, true);
_outConsoleWindow->setDimensions(Common::Rect(20, 20, 120, 120)); _outConsoleWindow->setDimensions(Common::Rect(20, 20, 120, 120));
_outConsoleWindow->setActive(false); _outConsoleWindow->setActive(false);
_outConsoleWindow->setCallback(outConsoleWindowCallback, this); _outConsoleWindow->setCallback(outConsoleWindowCallback, this);
loadBorder(_outConsoleWindow, "border_left_scroll_inac.bmp", false); //loadBorder(_outConsoleWindow, "border_left_scroll_inac.bmp", false);
loadBorder(_outConsoleWindow, "border_left_scroll_inac.bmp", true); //loadBorder(_outConsoleWindow, "border_left_scroll_inac.bmp", true);
// Self Window // Self Window
_selfWindow = _wm.addWindow(false, true, true); _selfWindow = _wm.addWindow(false, true, true);
_selfWindow->setDimensions(getWindowData(kSelfWindow).bounds); _selfWindow->setDimensions(getWindowData(kSelfWindow).bounds);
_selfWindow->setActive(false); _selfWindow->setActive(false);
_selfWindow->setCallback(selfWindowCallback, this); _selfWindow->setCallback(selfWindowCallback, this);
loadBorder(_selfWindow, "border_no_scroll_inac.bmp", false); //loadBorder(_selfWindow, "border_no_scroll_inac.bmp", false);
loadBorder(_selfWindow, "border_no_scroll_inac.bmp", true); //loadBorder(_selfWindow, "border_no_scroll_inac.bmp", true);
findWindowData(kMainGameWindow).objRef = 0;
// Exits Window // Exits Window
_exitsWindow = _wm.addWindow(false, true, true); _exitsWindow = _wm.addWindow(false, true, true);
_exitsWindow->setDimensions(getWindowData(kExitsWindow).bounds); _exitsWindow->setDimensions(getWindowData(kExitsWindow).bounds);
_exitsWindow->setActive(false); _exitsWindow->setActive(false);
_exitsWindow->setCallback(exitsWindowCallback, this); _exitsWindow->setCallback(exitsWindowCallback, this);
loadBorder(_exitsWindow, "border_no_scroll_inac.bmp", false); //loadBorder(_exitsWindow, "border_no_scroll_inac.bmp", false);
loadBorder(_exitsWindow, "border_no_scroll_act.bmp", true); //loadBorder(_exitsWindow, "border_no_scroll_act.bmp", true);
} }
void Gui::assignObjReferences() {
findWindowData(kSelfWindow).objRef = 0;
}
WindowReference Gui::createInventoryWindow(ObjID objRef) { WindowReference Gui::createInventoryWindow(ObjID objRef) {
Graphics::MacWindow *newWindow = _wm.addWindow(true, true, true); Graphics::MacWindow *newWindow = _wm.addWindow(true, true, true);
WindowData newData; WindowData newData;
GlobalSettings settings = _engine->getGlobalSettings(); GlobalSettings settings = _engine->getGlobalSettings();
newData.refcon = (WindowReference)ABS(_inventoryWindows.size()); // This is a hack newData.refcon = (WindowReference)ABS(_inventoryWindows.size()); // This is a HACK
if (_windowData->back().refcon < 0x80) { // There is already another inventory window if (_windowData->back().refcon < 0x80) { // There is already another inventory window
newData.bounds = _windowData->back().bounds; // Inventory windows are always last newData.bounds = _windowData->back().bounds; // Inventory windows are always last
@ -303,8 +310,8 @@ WindowReference Gui::createInventoryWindow(ObjID objRef) {
newWindow->setDimensions(newData.bounds); newWindow->setDimensions(newData.bounds);
newWindow->setCallback(inventoryWindowCallback, this); newWindow->setCallback(inventoryWindowCallback, this);
loadBorder(newWindow, "border_no_scroll_inac.bmp", false); //loadBorder(newWindow, "border_no_scroll_inac.bmp", false);
loadBorder(newWindow, "border_no_scroll_act.bmp", true); //loadBorder(newWindow, "border_no_scroll_act.bmp", true);
_inventoryWindows.push_back(newWindow); _inventoryWindows.push_back(newWindow);
debug("Create new inventory window. Reference: %d", newData.refcon); debug("Create new inventory window. Reference: %d", newData.refcon);
@ -587,7 +594,7 @@ void Gui::drawExitsWindow() {
srf->w + border.rightOffset, srf->w + border.rightOffset,
srf->h + border.bottomOffset), kColorWhite); srf->h + border.bottomOffset), kColorWhite);
drawObjectsInWindow(kExitsWindow, _exitsWindow->getSurface()); drawObjectsInWindow(kMainGameWindow, _exitsWindow->getSurface());
} }
void Gui::drawObjectsInWindow(WindowReference target, Graphics::ManagedSurface * surface) { void Gui::drawObjectsInWindow(WindowReference target, Graphics::ManagedSurface * surface) {
@ -792,12 +799,6 @@ void Gui::updateWindow(WindowReference winID, bool containerOpen) {
it->unselect(); it->unselect();
} }
} }
if (winID == kMainGameWindow) {
drawMainGameWindow();
} else {
Graphics::MacWindow *winRef = findWindow(winID);
winRef->getSurface()->fillRect(data.bounds, kColorGray);
}
Common::Array<DrawableObject> &children = data.children; Common::Array<DrawableObject> &children = data.children;
for (uint i = 0; i < children.size(); i++) { for (uint i = 0; i < children.size(); i++) {
uint flag = 0; uint flag = 0;
@ -812,8 +813,17 @@ void Gui::updateWindow(WindowReference winID, bool containerOpen) {
mode = kBlitOR; mode = kBlitOR;
} }
children[i] = DrawableObject(child, mode); children[i] = DrawableObject(child, mode);
} else {
children[i] = DrawableObject(child, kBlitXOR);
} }
} }
if (winID == kMainGameWindow) {
drawMainGameWindow();
}
else {
Graphics::MacWindow *winRef = findWindow(winID);
winRef->getSurface()->fillRect(data.bounds, kColorGray);
}
if (data.type == kZoomDoc && data.updateScroll) { if (data.type == kZoomDoc && data.updateScroll) {
warning("Unimplemented: update scroll"); warning("Unimplemented: update scroll");
} }

View file

@ -221,6 +221,7 @@ private: // Methods
// Initializers // Initializers
void initGUI(); void initGUI();
void initWindows(); void initWindows();
void assignObjReferences(); // Mainly guesswork
// Loaders // Loaders
bool loadMenus(); bool loadMenus();

View file

@ -37,6 +37,7 @@ enum BlitMode {
kBlitBIC = 1, kBlitBIC = 1,
kBlitOR = 2, kBlitOR = 2,
kBlitXOR = 3 kBlitXOR = 3
//kBlitNONE = 4,
}; };
enum GraphicsEncoding { enum GraphicsEncoding {

View file

@ -59,8 +59,14 @@ MacVentureEngine::~MacVentureEngine() {
if (_filenames) if (_filenames)
delete _filenames; delete _filenames;
if (_decodingArticles) if (_decodingDirectArticles)
delete _decodingArticles; delete _decodingDirectArticles;
if (_decodingNamingArticles)
delete _decodingNamingArticles;
if (_decodingIndirectArticles)
delete _decodingIndirectArticles;
if (_textHuffman) if (_textHuffman)
delete _textHuffman; delete _textHuffman;
@ -88,7 +94,9 @@ Common::Error MacVentureEngine::run() {
_oldTextEncoding = !loadTextHuffman(); _oldTextEncoding = !loadTextHuffman();
_filenames = new StringTable(this, _resourceManager, kFilenamesStringTableID); _filenames = new StringTable(this, _resourceManager, kFilenamesStringTableID);
_decodingArticles = new StringTable(this, _resourceManager, kCommonArticlesStringTableID); _decodingDirectArticles = new StringTable(this, _resourceManager, kCommonArticlesStringTableID);
_decodingNamingArticles = new StringTable(this, _resourceManager, kNamingArticlesStringTableID);
_decodingDirectArticles = new StringTable(this, _resourceManager, kIndirectArticlesStringTableID);
// Big class instantiation // Big class instantiation
_gui = new Gui(this, _resourceManager); _gui = new Gui(this, _resourceManager);
@ -251,7 +259,6 @@ void MacVentureEngine::enqueueText(TextQueueID type, ObjID target, ObjID source,
} }
bool MacVentureEngine::printTexts() { bool MacVentureEngine::printTexts() {
warning("printTexts: unimplemented");
for (uint i = 0; i < _textQueue.size(); i++) { for (uint i = 0; i < _textQueue.size(); i++) {
QueuedText text = _textQueue.front(); QueuedText text = _textQueue.front();
_textQueue.remove_at(0); _textQueue.remove_at(0);
@ -265,7 +272,7 @@ bool MacVentureEngine::printTexts() {
gameChanged(); gameChanged();
break; break;
case kTextPlain: case kTextPlain:
debug("Print Plain Text: %s", _world->getText(text.asset).c_str()); debug("Print Plain Text: %s", _world->getText(text.asset, text.source, text.destination).c_str());
gameChanged(); gameChanged();
break; break;
} }
@ -401,11 +408,7 @@ bool MacVenture::MacVentureEngine::runScriptEngine() {
if (_selectedControl == 1) if (_selectedControl == 1)
_gameChanged = false; _gameChanged = false;
<<<<<<< HEAD
else if (_gameState == kGameStateInit || _gameState == kGameStatePlaying){
=======
else if (_gameState == kGameStateInit || _gameState == kGameStatePlaying) { else if (_gameState == kGameStateInit || _gameState == kGameStatePlaying) {
>>>>>>> 088fc4d... MACVENTURE: Script engine fixes
if (_scriptEngine->runControl(kTick, _selectedControl, _destObject, _deltaPoint)) { if (_scriptEngine->runControl(kTick, _selectedControl, _destObject, _deltaPoint)) {
_haltedAtEnd = true; _haltedAtEnd = true;
return true; return true;
@ -493,7 +496,6 @@ void MacVentureEngine::resetVars() {
void MacVentureEngine::unselectAll() { void MacVentureEngine::unselectAll() {
while (!_currentSelection.empty()) { while (!_currentSelection.empty()) {
unselectObject(_currentSelection.front()); unselectObject(_currentSelection.front());
//_currentSelection.remove_at(0);
} }
} }
@ -532,6 +534,22 @@ int MacVentureEngine::findObjectInArray(ObjID objID, const Common::Array<ObjID>
return found ? i : -1; return found ? i : -1;
} }
uint MacVentureEngine::getPrefixNdx(ObjID obj) {
return _world->getObjAttr(obj, kAttrPrefixes);
}
Common::String MacVentureEngine::getPrefixString(uint flag, ObjID obj) {
uint ndx = _world->getObjAttr(obj, kAttrPrefixes); // HACK should check the type of that one
ndx = ((ndx) >> flag) & 3;
if (ndx) {
return (*_decodingNamingArticles->getStrings())[ndx];
}
}
Common::String MacVentureEngine::getNoun(ObjID ndx) {
return (*_decodingIndirectArticles->getStrings())[ndx];
}
void MacVentureEngine::highlightExit(ObjID objID) { void MacVentureEngine::highlightExit(ObjID objID) {
warning("highlightExit: unimplemented"); warning("highlightExit: unimplemented");
} }
@ -541,7 +559,7 @@ void MacVentureEngine::selectPrimaryObject(ObjID objID) {
int idx; int idx;
if (_destObject > 0 && if (_destObject > 0 &&
(idx = findObjectInArray(_destObject, _selectedObjs)) != -1 && (idx = findObjectInArray(_destObject, _selectedObjs)) != -1 &&
findObjectInArray(_destObject, _currentSelection) == -1) findObjectInArray(_destObject, _currentSelection) == -1)
{ {
_selectedObjs.remove_at(idx); _selectedObjs.remove_at(idx);
highlightExit(_destObject); highlightExit(_destObject);
@ -570,13 +588,13 @@ void MacVentureEngine::openObject(ObjID objID) {
_gui->updateWindowInfo(kMainGameWindow, objID, _world->getChildren(objID, true)); _gui->updateWindowInfo(kMainGameWindow, objID, _world->getChildren(objID, true));
_gui->updateWindow(kMainGameWindow, _world->getObjAttr(objID, kAttrContainerOpen)); _gui->updateWindow(kMainGameWindow, _world->getObjAttr(objID, kAttrContainerOpen));
//_gui->drawExits(); //_gui->drawExits();
_gui->setWindowTitle(kMainGameWindow, _world->getText(objID)); _gui->setWindowTitle(kMainGameWindow, _world->getText(objID, objID, objID)); // it ignores source and target in the original
} else { // Open inventory window } else { // Open inventory window
Common::Point p(_world->getObjAttr(objID, kAttrPosX), _world->getObjAttr(objID, kAttrPosY)); Common::Point p(_world->getObjAttr(objID, kAttrPosX), _world->getObjAttr(objID, kAttrPosY));
//getParentWin(obj).localToGlobal(p); //getParentWin(obj).localToGlobal(p);
//globalToDesktop(p); //globalToDesktop(p);
WindowReference invID = _gui->createInventoryWindow(objID); WindowReference invID = _gui->createInventoryWindow(objID);
_gui->setWindowTitle(invID, _world->getText(objID)); _gui->setWindowTitle(invID, _world->getText(objID, objID, objID));
_gui->updateWindowInfo(invID, objID, _world->getChildren(objID, true)); _gui->updateWindowInfo(invID, objID, _world->getChildren(objID, true));
_gui->updateWindow(invID, _world->getObjAttr(objID, kAttrContainerOpen)); _gui->updateWindow(invID, _world->getObjAttr(objID, kAttrContainerOpen));
} }
@ -664,7 +682,7 @@ void MacVentureEngine::reflectSwap(ObjID fromID, ObjID toID) {
tmp = from; tmp = from;
} }
if (tmp) { if (tmp) {
Common::String newTitle = _world->getText(toID); Common::String newTitle = _world->getText(toID, 0, 0); // Ignores src and targ in the original
_gui->setWindowTitle(tmp, newTitle); _gui->setWindowTitle(tmp, newTitle);
_gui->updateWindowInfo(tmp, toID, _world->getChildren(toID, true)); _gui->updateWindowInfo(tmp, toID, _world->getChildren(toID, true));
updateWindow(tmp); updateWindow(tmp);
@ -677,7 +695,7 @@ void MacVentureEngine::toggleExits() {
_selectedObjs.remove_at(0); _selectedObjs.remove_at(0);
highlightExit(obj); highlightExit(obj);
updateWindow(findParentWindow(obj)); updateWindow(findParentWindow(obj));
} }
} }
void MacVentureEngine::zoomObject(ObjID objID) { void MacVentureEngine::zoomObject(ObjID objID) {
@ -775,13 +793,13 @@ Common::Rect MacVentureEngine::getObjBounds(ObjID objID) {
uint MacVentureEngine::getOverlapPercent(ObjID one, ObjID other) { uint MacVentureEngine::getOverlapPercent(ObjID one, ObjID other) {
//not the same parent? 0 overlap //not the same parent? 0 overlap
if (_world->getObjAttr(one, kAttrParentObject) != if (_world->getObjAttr(one, kAttrParentObject) !=
_world->getObjAttr(other, kAttrParentObject)) _world->getObjAttr(other, kAttrParentObject))
return 0; return 0;
Common::Rect oneBounds = getObjBounds(one); Common::Rect oneBounds = getObjBounds(one);
Common::Rect otherBounds = getObjBounds(other); Common::Rect otherBounds = getObjBounds(other);
if (otherBounds.intersects(oneBounds) || if (otherBounds.intersects(oneBounds) ||
oneBounds.intersects(otherBounds)) oneBounds.intersects(otherBounds))
{ {
uint areaOne = oneBounds.width() * oneBounds.height(); uint areaOne = oneBounds.width() * oneBounds.height();
uint areaOther = otherBounds.width() * otherBounds.height(); uint areaOther = otherBounds.width() * otherBounds.height();
@ -805,7 +823,7 @@ WindowReference MacVentureEngine::findObjWindow(ObjID objID) {
// This is a bit of a hack, we take advantage of the consecutive nature of references // This is a bit of a hack, we take advantage of the consecutive nature of references
for (uint i = kCommandsWindow; i <= kDiplomaWindow; i++) { for (uint i = kCommandsWindow; i <= kDiplomaWindow; i++) {
const WindowData &data = _gui->getWindowData((WindowReference)i); const WindowData &data = _gui->getWindowData((WindowReference)i);
if (data.refcon == objID) { return data.refcon; } if (data.objRef == objID) { return data.refcon; }
} }
return kNoWindow; return kNoWindow;
} }

View file

@ -194,6 +194,10 @@ public:
const HuffmanLists *getDecodingHuffman() const; const HuffmanLists *getDecodingHuffman() const;
uint32 randBetween(uint32 min, uint32 max); uint32 randBetween(uint32 min, uint32 max);
uint32 getInvolvedObjects(); uint32 getInvolvedObjects();
int findObjectInArray(ObjID objID, const Common::Array<ObjID> &list);
uint getPrefixNdx(ObjID obj);
Common::String getPrefixString(uint flag, ObjID obj);
Common::String getNoun(ObjID ndx);
// Attributes consult // Attributes consult
Common::Point getObjPosition(ObjID objID); Common::Point getObjPosition(ObjID objID);
@ -224,7 +228,6 @@ private:
void unselectAll(); void unselectAll();
void selectObject(ObjID objID); void selectObject(ObjID objID);
void unselectObject(ObjID objID); void unselectObject(ObjID objID);
int findObjectInArray(ObjID objID, const Common::Array<ObjID> &list);
void highlightExit(ObjID objID); void highlightExit(ObjID objID);
void selectPrimaryObject(ObjID objID); void selectPrimaryObject(ObjID objID);
@ -261,7 +264,9 @@ private: // Attributes
// String tables // String tables
StringTable *_filenames; StringTable *_filenames;
StringTable *_decodingArticles; StringTable *_decodingDirectArticles;
StringTable *_decodingNamingArticles;
StringTable *_decodingIndirectArticles;
// Engine state // Engine state
GameState _gameState; GameState _gameState;

View file

@ -794,21 +794,21 @@ void ScriptEngine::opacEQ(EngineState * state, EngineFrame * frame) {
} }
void ScriptEngine::opadEQS(EngineState * state, EngineFrame * frame) { void ScriptEngine::opadEQS(EngineState * state, EngineFrame * frame) {
Common::String b = _world->getText(state->pop()); Common::String b = _world->getText(state->pop(), 0, 0); // HACK, these destinations might be wrong
Common::String a = _world->getText(state->pop()); Common::String a = _world->getText(state->pop(), 0, 0);
state->push((a == b) ? 1 : 0); state->push((a == b) ? 1 : 0);
} }
void ScriptEngine::opaeCONT(EngineState * state, EngineFrame * frame) { void ScriptEngine::opaeCONT(EngineState * state, EngineFrame * frame) {
Common::String needle = _world->getText(state->pop()); Common::String needle = _world->getText(state->pop(), 0, 0);
Common::String haystack = _world->getText(state->pop()); Common::String haystack = _world->getText(state->pop(), 0, 0);
haystack.toLowercase(); haystack.toLowercase();
state->push(haystack.contains(needle) ? 1 : 0); state->push(haystack.contains(needle) ? 1 : 0);
} }
void ScriptEngine::opafCONTW(EngineState * state, EngineFrame * frame) { void ScriptEngine::opafCONTW(EngineState * state, EngineFrame * frame) {
Common::String needle = _world->getText(state->pop()); Common::String needle = _world->getText(state->pop(), 0, 0);
Common::String haystack = _world->getText(state->pop()); Common::String haystack = _world->getText(state->pop(), 0, 0);
haystack.toLowercase(); haystack.toLowercase();
state->push(haystack.contains(needle) ? 1 : 0); state->push(haystack.contains(needle) ? 1 : 0);
} }

View file

@ -23,11 +23,14 @@
#include "macventure/text.h" #include "macventure/text.h"
namespace MacVenture { namespace MacVenture {
TextAsset::TextAsset(ObjID objid, Container *container, bool isOld, const HuffmanLists *huffman) { TextAsset::TextAsset(MacVentureEngine *engine, ObjID objid, ObjID source, ObjID target, Container *container, bool isOld, const HuffmanLists *huffman) {
_id = objid; _id = objid;
_sourceObj = source;
_targetObj = target;
_container = container; _container = container;
_huffman = huffman; _huffman = huffman;
_isOld = isOld; _isOld = isOld;
_engine = engine;
if (_isOld) { if (_isOld) {
decodeOld(); decodeOld();
@ -77,8 +80,20 @@ void TextAsset::decodeOld() {
lowercase = true; lowercase = true;
} }
else if (val == 0x1D) { // Composite else if (val == 0x1D) { // Composite
warning("Composite strings not implemented"); ObjID subval = stream.getBits(16);
stream.getBits(16); Common::String child;
if (subval & 0x8000) {
// Composite object id
subval ^= 0xFFFF;
child = getNoun(subval);
} else {
// Just another id
// HACK, see below in getNoun()
child = *TextAsset(_engine, subval, _sourceObj, _targetObj, _container, _isOld, _huffman).decode();
}
if (child.size() > 0) {
c = '?'; // HACK Will fix later, should append
}
lowercase = true; lowercase = true;
} }
else if (val == 0x1E) { else if (val == 0x1E) {
@ -102,7 +117,7 @@ void TextAsset::decodeOld() {
void TextAsset::decodeHuffman() { void TextAsset::decodeHuffman() {
_decoded = Common::String(""); _decoded = Common::String("");
Common::SeekableReadStream *res = _container->getItem(_id); Common::SeekableReadStream *res = _container->getItem(_id);
Common::BitStream32BEMSB stream(res); Common::BitStream8MSB stream(res);
uint16 strLen = 0; uint16 strLen = 0;
if (stream.getBit()) { if (stream.getBit()) {
strLen = stream.getBits(15); strLen = stream.getBits(15);
@ -110,12 +125,13 @@ void TextAsset::decodeHuffman() {
else { else {
strLen = stream.getBits(7); strLen = stream.getBits(7);
} }
// OK up to here
uint32 mask = 0; uint32 mask = 0;
uint32 symbol = 0; uint32 symbol = 0;
char c; char c;
for (uint16 i = 0; i < strLen; i++) { for (uint16 i = 0; i < strLen; i++) {
mask = stream.peekBits(16); // The mask is OK, so it means that I don't know how to use the huffman mask = stream.peekBits(16); // The mask is OK
uint32 entry; uint32 entry;
// Find the length index // Find the length index
for (entry = 0; entry < _huffman->getNumEntries(); entry++) { for (entry = 0; entry < _huffman->getNumEntries(); entry++) {
@ -128,24 +144,63 @@ void TextAsset::decodeHuffman() {
if (symbol == 1) { // 7-bit ascii if (symbol == 1) { // 7-bit ascii
c = stream.getBits(7); c = stream.getBits(7);
} _decoded += c;
else if (symbol == 2) { // Composite } else if (symbol == 2) { // Composite
warning("Composite huffman strings not tested");
if (stream.getBit()) { // TextID if (stream.getBit()) { // TextID
ObjID embedId = stream.getBits(15); ObjID embedId = stream.getBits(15);
TextAsset embedded(embedId, _container, _isOld, _huffman); uint pos = stream.pos(); // HACK, part 1
_decoded += *embedded.decode(); TextAsset embedded(_engine, embedId, _sourceObj, _targetObj, _container, _isOld, _huffman);
} else { //Composite obj string stream.rewind();// HACK, part 2
_decoded += Common::String("Unimplemented"); stream.skip(pos);
}
}
else { // Plain ascii
c = symbol & 0xFF;
}
_decoded += c; _decoded.replace(_decoded.end(), _decoded.end(), *embedded.decode());
// Another HACK, to get around that EOS char I insert at the end
_decoded.replace(_decoded.end() - 1, _decoded.end(), "");
} else { //Composite obj string
ObjID embedId = stream.getBits(8);
_decoded.replace(_decoded.end(), _decoded.end(), getNoun(embedId));
// Another HACK, to get around that EOS char I insert at the end
_decoded.replace(_decoded.end() - 1, _decoded.end(), "");
}
} else { // Plain ascii
c = symbol & 0xFF;
_decoded.replace(_decoded.end(), _decoded.end(), Common::String(c));
}
} }
_decoded += '\0'; _decoded += '\0';
debug(7, "Decoded %d'th string (new): %s", _id, _decoded.c_str()); debug(7, "Decoded %d'th string (new): %s", _id, _decoded.c_str());
} }
Common::String TextAsset::getNoun(ObjID subval) {
ObjID obj;
Common::String name;
if (subval & 8)
obj = _targetObj;
else
obj = _sourceObj;
if ((subval & 3) == 1)
{
uint idx = _engine->getPrefixNdx(obj);
idx = ((idx >> 4) & 3) + 1;
name = _engine->getNoun(idx);
}
else
{
// HACK, there should be a pool of assets or something like in the GUI
name = *TextAsset(_engine, obj, _sourceObj, _targetObj, _container, _isOld, _huffman).decode();
switch (subval & 3)
{
case 2:
name = _engine->getPrefixString(0, obj) + name;
break;
case 3:
name = _engine->getPrefixString(2, obj) + name;
break;
}
}
if (name.size() && (subval & 4))
name.toUppercase(); // HACK, should only capitalize first char?
return name;
}
} // End of namespace MacVenture } // End of namespace MacVenture

View file

@ -31,7 +31,7 @@ typedef uint32 ObjID;
class TextAsset { class TextAsset {
public: public:
TextAsset(ObjID objid, Container *container, bool isOld, const HuffmanLists *huffman); TextAsset(MacVentureEngine *engine, ObjID objid, ObjID source, ObjID target, Container *container, bool isOld, const HuffmanLists *huffman);
~TextAsset() {} ~TextAsset() {}
const Common::String *decode() { const Common::String *decode() {
@ -42,9 +42,15 @@ private:
void decodeOld(); void decodeOld();
void decodeHuffman(); void decodeHuffman();
Common::String getNoun(ObjID id);
private: private:
MacVentureEngine *_engine;
Container *_container; Container *_container;
ObjID _id; ObjID _id;
ObjID _targetObj;
ObjID _sourceObj;
const HuffmanLists *_huffman; const HuffmanLists *_huffman;
bool _isOld; bool _isOld;

View file

@ -25,9 +25,6 @@ World::World(MacVentureEngine *engine, Common::MacResManager *resMan) {
warning("Test functions about to happen"); warning("Test functions about to happen");
_gameText = new Container("Shadowgate II/Shadow Text"); _gameText = new Container("Shadowgate II/Shadow Text");
ObjID tid = (ObjID)1;
TextAsset test = TextAsset(tid, _gameText, _engine->isOldText(), _engine->getDecodingHuffman());
delete saveGameRes; delete saveGameRes;
saveGameFile.close(); saveGameFile.close();
@ -153,8 +150,8 @@ void World::captureChildren(ObjID objID) {
void World::releaseChildren(ObjID objID) { void World::releaseChildren(ObjID objID) {
} }
Common::String World::getText(ObjID objID) { Common::String World::getText(ObjID objID, ObjID source, ObjID target) {
TextAsset text = TextAsset(objID, _gameText, _engine->isOldText(), _engine->getDecodingHuffman()); TextAsset text = TextAsset(_engine, objID, source, target, _gameText, _engine->isOldText(), _engine->getDecodingHuffman());
return *text.decode(); return *text.decode();
} }

View file

@ -99,7 +99,7 @@ public:
uint32 getObjAttr(ObjID objID, uint32 attrID); uint32 getObjAttr(ObjID objID, uint32 attrID);
Attribute getGlobal(uint32 attrID); Attribute getGlobal(uint32 attrID);
Common::String getText(ObjID objID); Common::String getText(ObjID objID, ObjID source, ObjID target);
bool isObjActive(ObjID objID); bool isObjActive(ObjID objID);