ADL: Bring hires6 in line with hires5

This commit is contained in:
Walter van Niftrik 2017-02-09 19:36:28 +01:00
parent a938942f03
commit 441f940069
6 changed files with 124 additions and 308 deletions

View file

@ -190,24 +190,23 @@ Common::String AdlEngine_v4::getItemDescription(const Item &item) const {
return _itemDesc[item.id - 1]; return _itemDesc[item.id - 1];
} }
DiskImage *AdlEngine_v4::loadDisk(byte volume) const { Common::String AdlEngine_v4::getDiskImageName(byte volume) const {
const ADGameFileDescription *ag; const ADGameFileDescription *ag;
for (ag = _gameDescription->desc.filesDescriptions; ag->fileName; ag++) { for (ag = _gameDescription->desc.filesDescriptions; ag->fileName; ag++)
if (ag->fileType == volume) { if (ag->fileType == volume)
DiskImage *disk = new DiskImage(); return ag->fileName;
if (!disk->open(ag->fileName))
error("Failed to open %s", ag->fileName);
return disk;
}
}
error("Disk volume %d not found", volume); error("Disk volume %d not found", volume);
} }
void AdlEngine_v4::insertDisk(byte volume) { void AdlEngine_v4::insertDisk(byte volume) {
delete _disk; delete _disk;
_disk = loadDisk(volume); _disk = new DiskImage();
if (!_disk->open(getDiskImageName(volume)))
error("Failed to open disk volume %d", volume);
_currentVolume = volume; _currentVolume = volume;
} }
@ -274,6 +273,27 @@ void AdlEngine_v4::adjustDataBlockPtr(byte &track, byte &sector, byte &offset, b
fixupDiskOffset(track, sector); fixupDiskOffset(track, sector);
} }
AdlEngine_v4::RegionChunkType AdlEngine_v4::getRegionChunkType(const uint16 addr) const {
switch (addr) {
case 0x9000:
return kRegionChunkMessages;
case 0x4a80:
return kRegionChunkGlobalPics;
case 0x4000:
return kRegionChunkVerbs;
case 0x1800:
return kRegionChunkNouns;
case 0x0e00:
return kRegionChunkRooms;
case 0x7b00:
return kRegionChunkRoomCmds;
case 0x9500:
return kRegionChunkGlobalCmds;
default:
return kRegionChunkUnknown;
}
}
void AdlEngine_v4::loadRegion(byte region) { void AdlEngine_v4::loadRegion(byte region) {
if (_currentVolume != _regionInitDataOffsets[region - 1].volume) { if (_currentVolume != _regionInitDataOffsets[region - 1].volume) {
insertDisk(_regionInitDataOffsets[region - 1].volume); insertDisk(_regionInitDataOffsets[region - 1].volume);
@ -303,29 +323,29 @@ void AdlEngine_v4::loadRegion(byte region) {
stream.reset(_disk->createReadStream(track, sector, offset, size / 256 + 1)); stream.reset(_disk->createReadStream(track, sector, offset, size / 256 + 1));
stream->skip(4); stream->skip(4);
switch (addr) { switch (getRegionChunkType(addr)) {
case 0x9000: { case kRegionChunkMessages: {
// Messages // Messages
_messages.clear(); _messages.clear();
uint count = size / 4; uint count = size / 4;
loadMessages(*stream, count); loadMessages(*stream, count);
break; break;
} }
case 0x4a80: { case kRegionChunkGlobalPics: {
// Global pics // Global pics
_pictures.clear(); _pictures.clear();
loadPictures(*stream); loadPictures(*stream);
break; break;
} }
case 0x4000: case kRegionChunkVerbs:
// Verbs // Verbs
loadWords(*stream, _verbs, _priVerbs); loadWords(*stream, _verbs, _priVerbs);
break; break;
case 0x1800: case kRegionChunkNouns:
// Nouns // Nouns
loadWords(*stream, _nouns, _priNouns); loadWords(*stream, _nouns, _priNouns);
break; break;
case 0x0e00: { case kRegionChunkRooms: {
// Rooms // Rooms
uint count = size / 14 - 1; uint count = size / 14 - 1;
stream->skip(14); // Skip invalid room 0 stream->skip(14); // Skip invalid room 0
@ -334,12 +354,11 @@ void AdlEngine_v4::loadRegion(byte region) {
loadRooms(*stream, count); loadRooms(*stream, count);
break; break;
} }
case 0x7b00: case kRegionChunkRoomCmds:
// TODO: hires6 has global and room lists swapped
// Room commands // Room commands
readCommands(*stream, _roomCommands); readCommands(*stream, _roomCommands);
break; break;
case 0x9500: case kRegionChunkGlobalCmds:
// Global commands // Global commands
readCommands(*stream, _globalCommands); readCommands(*stream, _globalCommands);
break; break;

View file

@ -60,12 +60,24 @@ protected:
// AdlEngine_v2 // AdlEngine_v2
virtual void adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const; virtual void adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const;
DiskImage *loadDisk(byte volume) const; enum RegionChunkType {
kRegionChunkUnknown,
kRegionChunkMessages,
kRegionChunkGlobalPics,
kRegionChunkVerbs,
kRegionChunkNouns,
kRegionChunkRooms,
kRegionChunkRoomCmds,
kRegionChunkGlobalCmds
};
Common::String getDiskImageName(byte volume) const;
void insertDisk(byte volume); void insertDisk(byte volume);
void loadRegionLocations(Common::ReadStream &stream, uint regions); void loadRegionLocations(Common::ReadStream &stream, uint regions);
void loadRegionInitDataOffsets(Common::ReadStream &stream, uint regions); void loadRegionInitDataOffsets(Common::ReadStream &stream, uint regions);
void initRegions(const byte *roomsPerRegion, uint regions); void initRegions(const byte *roomsPerRegion, uint regions);
void fixupDiskOffset(byte &track, byte &sector) const; void fixupDiskOffset(byte &track, byte &sector) const;
virtual RegionChunkType getRegionChunkType(const uint16 addr) const;
void loadRegion(byte region); void loadRegion(byte region);
void loadItemPicIndex(Common::ReadStream &stream, uint items); void loadItemPicIndex(Common::ReadStream &stream, uint items);
void backupRoomState(byte room); void backupRoomState(byte room);

View file

@ -30,43 +30,24 @@
namespace Adl { namespace Adl {
AdlEngine_v5::AdlEngine_v5(OSystem *syst, const AdlGameDescription *gd) : AdlEngine_v5::AdlEngine_v5(OSystem *syst, const AdlGameDescription *gd) :
AdlEngine_v3(syst, gd), AdlEngine_v4(syst, gd) {
_curDisk(0) {
} }
Common::String AdlEngine_v5::loadMessage(uint idx) const { AdlEngine_v5::RegionChunkType AdlEngine_v5::getRegionChunkType(const uint16 addr) const {
Common::String str = AdlEngine_v2::loadMessage(idx); switch (addr) {
case 0x7b00:
for (uint i = 0; i < str.size(); ++i) { return kRegionChunkGlobalCmds;
const char *xorStr = "AVISDURGAN"; case 0x9500:
str.setChar(str[i] ^ xorStr[i % strlen(xorStr)], i); return kRegionChunkRoomCmds;
default:
return AdlEngine_v4::getRegionChunkType(addr);
} }
return str;
} }
Common::String AdlEngine_v5::getItemDescription(const Item &item) const { typedef Common::Functor1Mem<ScriptEnv &, int, AdlEngine_v5> OpcodeV5;
return _itemDesc[item.id - 1];
}
void AdlEngine_v5::applyDiskOffset(byte &track, byte &sector) const {
sector += _diskOffsets[_curDisk].sector;
if (sector >= 16) {
sector -= 16;
++track;
}
track += _diskOffsets[_curDisk].track;
}
void AdlEngine_v5::adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const {
applyDiskOffset(track, sector);
}
typedef Common::Functor1Mem<ScriptEnv &, int, AdlEngine_v5> OpcodeV4;
#define SetOpcodeTable(x) table = &x; #define SetOpcodeTable(x) table = &x;
#define Opcode(x) table->push_back(new OpcodeV4(this, &AdlEngine_v5::x)) #define Opcode(x) table->push_back(new OpcodeV5(this, &AdlEngine_v5::x))
#define OpcodeUnImpl() table->push_back(new OpcodeV4(this, 0)) #define OpcodeUnImpl() table->push_back(new OpcodeV5(this, 0))
void AdlEngine_v5::setupOpcodeTables() { void AdlEngine_v5::setupOpcodeTables() {
Common::Array<const Opcode *> *table = 0; Common::Array<const Opcode *> *table = 0;
@ -76,14 +57,14 @@ void AdlEngine_v5::setupOpcodeTables() {
OpcodeUnImpl(); OpcodeUnImpl();
Opcode(o2_isFirstTime); Opcode(o2_isFirstTime);
Opcode(o2_isRandomGT); Opcode(o2_isRandomGT);
Opcode(o5_isItemInRoom); Opcode(o4_isItemInRoom);
// 0x04 // 0x04
Opcode(o5_isNounNotInRoom); Opcode(o5_isNounNotInRoom);
Opcode(o1_isMovesGT); Opcode(o1_isMovesGT);
Opcode(o1_isVarEQ); Opcode(o1_isVarEQ);
Opcode(o2_isCarryingSomething); Opcode(o2_isCarryingSomething);
// 0x08 // 0x08
Opcode(o5_isVarGT); Opcode(o4_isVarGT);
Opcode(o1_isCurPicEQ); Opcode(o1_isCurPicEQ);
Opcode(o5_skipOneCommand); Opcode(o5_skipOneCommand);
@ -95,7 +76,7 @@ void AdlEngine_v5::setupOpcodeTables() {
Opcode(o1_varSet); Opcode(o1_varSet);
// 0x04 // 0x04
Opcode(o1_listInv); Opcode(o1_listInv);
Opcode(o5_moveItem); Opcode(o4_moveItem);
Opcode(o1_setRoom); Opcode(o1_setRoom);
Opcode(o2_setCurPic); Opcode(o2_setCurPic);
// 0x08 // 0x08
@ -111,7 +92,7 @@ void AdlEngine_v5::setupOpcodeTables() {
// 0x10 // 0x10
Opcode(o2_restore); Opcode(o2_restore);
Opcode(o1_restart); Opcode(o1_restart);
Opcode(o5_setDisk); Opcode(o5_setRegionRoom);
Opcode(o5_dummy); Opcode(o5_dummy);
// 0x14 // 0x14
Opcode(o1_resetPic); Opcode(o1_resetPic);
@ -126,45 +107,12 @@ void AdlEngine_v5::setupOpcodeTables() {
// 0x1c // 0x1c
Opcode(o1_dropItem); Opcode(o1_dropItem);
Opcode(o1_setRoomPic); Opcode(o1_setRoomPic);
Opcode(o5_sound); Opcode(o_winGame);
OpcodeUnImpl(); OpcodeUnImpl();
// 0x20 // 0x20
Opcode(o2_initDisk); Opcode(o2_initDisk);
} }
int AdlEngine_v5::o5_isVarGT(ScriptEnv &e) {
OP_DEBUG_2("\t&& VARS[%d] > %d", e.arg(1), e.arg(2));
if (getVar(e.arg(1)) > e.arg(2))
return 2;
return -1;
}
int AdlEngine_v5::o5_skipOneCommand(ScriptEnv &e) {
OP_DEBUG_0("\t&& SKIP_ONE_COMMAND()");
_skipOneCommand = true;
setVar(2, 0);
return -1;
}
// FIXME: Rename "isLineArt" and look at code duplication
int AdlEngine_v5::o5_isItemInRoom(ScriptEnv &e) {
OP_DEBUG_2("\t&& GET_ITEM_ROOM(%s) == %s", itemStr(e.arg(1)).c_str(), itemRoomStr(e.arg(2)).c_str());
const Item &item = getItem(e.arg(1));
if (e.arg(2) != IDI_ANY && item.isLineArt != _curDisk)
return -1;
if (item.room == roomArg(e.arg(2)))
return 2;
return -1;
}
int AdlEngine_v5::o5_isNounNotInRoom(ScriptEnv &e) { int AdlEngine_v5::o5_isNounNotInRoom(ScriptEnv &e) {
OP_DEBUG_1("\t&& NO_SUCH_ITEMS_IN_ROOM(%s)", itemRoomStr(e.arg(1)).c_str()); OP_DEBUG_1("\t&& NO_SUCH_ITEMS_IN_ROOM(%s)", itemRoomStr(e.arg(1)).c_str());
@ -183,23 +131,13 @@ int AdlEngine_v5::o5_isNounNotInRoom(ScriptEnv &e) {
return 1; return 1;
} }
int AdlEngine_v5::o5_moveItem(ScriptEnv &e) { int AdlEngine_v5::o5_skipOneCommand(ScriptEnv &e) {
OP_DEBUG_2("\tSET_ITEM_ROOM(%s, %s)", itemStr(e.arg(1)).c_str(), itemRoomStr(e.arg(2)).c_str()); OP_DEBUG_0("\t&& SKIP_ONE_COMMAND()");
byte room = roomArg(e.arg(2)); _skipOneCommand = true;
setVar(2, 0);
Item &item = getItem(e.arg(1)); return -1;
if (item.room == _roomOnScreen)
_picOnScreen = 0;
// Set items that move from inventory to a room to state "dropped"
if (item.room == IDI_ANY && room != IDI_VOID_ROOM)
item.state = IDI_ITEM_DROPPED;
item.room = room;
item.isLineArt = _curDisk;
return 2;
} }
int AdlEngine_v5::o5_dummy(ScriptEnv &e) { int AdlEngine_v5::o5_dummy(ScriptEnv &e) {
@ -225,18 +163,15 @@ int AdlEngine_v5::o5_setTextMode(ScriptEnv &e) {
return 1; return 1;
} }
int AdlEngine_v5::o5_setDisk(ScriptEnv &e) { int AdlEngine_v5::o5_setRegionRoom(ScriptEnv &e) {
OP_DEBUG_2("\tSET_DISK(%d, %d)", e.arg(1), e.arg(2)); OP_DEBUG_2("\tSET_REGION_ROOM(%d, %d)", e.arg(1), e.arg(2));
// TODO // TODO
// Arg 1: disk
// Arg 2: room
return 2; return 2;
} }
int AdlEngine_v5::o5_sound(ScriptEnv &e) { int AdlEngine_v5::o_winGame(ScriptEnv &e) {
OP_DEBUG_0("\tSOUND()"); OP_DEBUG_0("\tWIN_GAME()");
// TODO // TODO

View file

@ -23,21 +23,11 @@
#ifndef ADL_ADL_V5_H #ifndef ADL_ADL_V5_H
#define ADL_ADL_V5_H #define ADL_ADL_V5_H
#include "adl/adl_v3.h" #include "adl/adl_v4.h"
namespace Common {
class RandomSource;
}
struct DiskOffset {
byte track;
byte sector;
};
namespace Adl { namespace Adl {
// FIXME: Subclass _v4 when it is done class AdlEngine_v5 : public AdlEngine_v4 {
class AdlEngine_v5 : public AdlEngine_v3 {
public: public:
virtual ~AdlEngine_v5() { } virtual ~AdlEngine_v5() { }
@ -46,26 +36,16 @@ protected:
// AdlEngine // AdlEngine
virtual void setupOpcodeTables(); virtual void setupOpcodeTables();
virtual Common::String loadMessage(uint idx) const;
Common::String getItemDescription(const Item &item) const;
// AdlEngine_v2 // AdlEngine_v4
virtual void adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const; virtual RegionChunkType getRegionChunkType(const uint16 addr) const;
void applyDiskOffset(byte &track, byte &sector) const;
int o5_isVarGT(ScriptEnv &e);
int o5_isItemInRoom(ScriptEnv &e);
int o5_isNounNotInRoom(ScriptEnv &e); int o5_isNounNotInRoom(ScriptEnv &e);
int o5_skipOneCommand(ScriptEnv &e); int o5_skipOneCommand(ScriptEnv &e);
int o5_moveItem(ScriptEnv &e);
int o5_dummy(ScriptEnv &e); int o5_dummy(ScriptEnv &e);
int o5_setTextMode(ScriptEnv &e); int o5_setTextMode(ScriptEnv &e);
int o5_setDisk(ScriptEnv &e); int o5_setRegionRoom(ScriptEnv &e);
int o5_sound(ScriptEnv &e); int o_winGame(ScriptEnv &e);
byte _curDisk;
Common::Array<DiskOffset> _diskOffsets;
}; };
} // End of namespace Adl } // End of namespace Adl

View file

@ -188,9 +188,9 @@ static const AdlGameDescription gameDescriptions[] = {
"hires6", 0, "hires6", 0,
{ {
{ "DARK1A.DSK", 0, "00c2646d6943d1405717332a6f42d493", 143360 }, { "DARK1A.DSK", 0, "00c2646d6943d1405717332a6f42d493", 143360 },
{ "DARK2A.NIB", 0, "271eb92db107e8d5829437f8ba77991e", 232960 }, { "DARK1B.NIB", 3, "dbedd736617343ade0e6bead8bf2b10c", 232960 },
{ "DARK1B.NIB", 0, "dbedd736617343ade0e6bead8bf2b10c", 232960 }, { "DARK2A.NIB", 4, "271eb92db107e8d5829437f8ba77991e", 232960 },
{ "DARK2B.NIB", 0, "cb72044a9b391c4285f4752f746bea2e", 232960 }, { "DARK2B.NIB", 5, "cb72044a9b391c4285f4752f746bea2e", 232960 },
AD_LISTEND AD_LISTEND
}, },
Common::EN_ANY, Common::EN_ANY,

View file

@ -34,44 +34,19 @@
namespace Adl { namespace Adl {
#define IDI_HR6_NUM_ROOMS 35
#define IDI_HR6_NUM_MESSAGES 256
#define IDI_HR6_NUM_VARS 40
#define IDI_HR6_NUM_ITEM_DESCS 15
#define IDI_HR6_NUM_ITEM_PICS 15
#define IDI_HR6_NUM_ITEM_OFFSETS 16
// Messages used outside of scripts
#define IDI_HR6_MSG_CANT_GO_THERE 249
#define IDI_HR6_MSG_DONT_UNDERSTAND 247
#define IDI_HR6_MSG_ITEM_DOESNT_MOVE 253
#define IDI_HR6_MSG_ITEM_NOT_HERE 254
#define IDI_HR6_MSG_THANKS_FOR_PLAYING 252
struct DiskDataDesc {
byte track;
byte sector;
byte offset;
byte volume;
};
class HiRes6Engine : public AdlEngine_v5 { class HiRes6Engine : public AdlEngine_v5 {
public: public:
HiRes6Engine(OSystem *syst, const AdlGameDescription *gd) : HiRes6Engine(OSystem *syst, const AdlGameDescription *gd) :
AdlEngine_v5(syst, gd), AdlEngine_v5(syst, gd),
_boot(nullptr),
_currVerb(0), _currVerb(0),
_currNoun(0) { _currNoun(0) {
} }
~HiRes6Engine() { delete _boot; }
private: private:
// AdlEngine // AdlEngine
void runIntro(); void runIntro();
void init(); void init();
void initGameState(); void initGameState();
void printRoomDescription();
void showRoom(); void showRoom();
Common::String formatVerbError(const Common::String &verb) const; Common::String formatVerbError(const Common::String &verb) const;
Common::String formatNounError(const Common::String &verb, const Common::String &noun) const; Common::String formatNounError(const Common::String &verb, const Common::String &noun) const;
@ -79,15 +54,12 @@ private:
// AdlEngine_v2 // AdlEngine_v2
void printString(const Common::String &str); void printString(const Common::String &str);
void loadDisk(byte disk); static const uint kRegions = 3;
static const uint kItems = 15;
DiskImage *_boot;
byte _currVerb, _currNoun; byte _currVerb, _currNoun;
Common::Array<DiskDataDesc> _diskDataDesc;
}; };
static const char *disks[] = { "DARK1A.DSK", "DARK1B.NIB", "DARK2A.NIB", "DARK2B.NIB" };
#define SECTORS_PER_TRACK 16 #define SECTORS_PER_TRACK 16
#define BYTES_PER_SECTOR 256 #define BYTES_PER_SECTOR 256
@ -121,12 +93,9 @@ static Common::MemoryReadStream *loadSectors(DiskImage *disk, byte track, byte s
} }
void HiRes6Engine::runIntro() { void HiRes6Engine::runIntro() {
DiskImage *boot(new DiskImage()); insertDisk(0);
if (!boot->open(disks[0])) StreamPtr stream(loadSectors(_disk, 11, 1, 96));
error("Failed to open disk image '%s'", disks[0]);
StreamPtr stream(loadSectors(boot, 11, 1, 96));
_display->setMode(DISPLAY_MODE_HIRES); _display->setMode(DISPLAY_MODE_HIRES);
_display->loadFrameBuffer(*stream); _display->loadFrameBuffer(*stream);
@ -139,13 +108,11 @@ void HiRes6Engine::runIntro() {
_display->loadFrameBuffer(*stream); _display->loadFrameBuffer(*stream);
delete boot;
// Load copyright string from boot file // Load copyright string from boot file
Files_DOS33 *files(new Files_DOS33()); Files_DOS33 *files(new Files_DOS33());
if (!files->open(disks[0])) if (!files->open(getDiskImageName(0)))
error("Failed to open disk image '%s'", disks[0]); error("Failed to open disk volume 0");
stream.reset(files->createReadStream("\010\010\010\010\010\010")); stream.reset(files->createReadStream("\010\010\010\010\010\010"));
Common::String copyright(readStringAt(*stream, 0x103, APPLECHAR('\r'))); Common::String copyright(readStringAt(*stream, 0x103, APPLECHAR('\r')));
@ -161,20 +128,22 @@ void HiRes6Engine::runIntro() {
} }
void HiRes6Engine::init() { void HiRes6Engine::init() {
_boot = new DiskImage(); _graphics = new Graphics_v3(*_display);
_graphics = new Graphics_v2(*_display);
if (!_boot->open(disks[0])) insertDisk(0);
error("Failed to open disk image '%s'", disks[0]);
StreamPtr stream(loadSectors(_boot, 0x7)); StreamPtr stream(_disk->createReadStream(0x3, 0xf, 0x05));
loadRegionLocations(*stream, kRegions);
stream.reset(_disk->createReadStream(0x5, 0xa, 0x07));
loadRegionInitDataOffsets(*stream, kRegions);
stream.reset(loadSectors(_disk, 0x7));
// Read parser messages
_strings.verbError = readStringAt(*stream, 0x666); _strings.verbError = readStringAt(*stream, 0x666);
_strings.nounError = readStringAt(*stream, 0x6bd); _strings.nounError = readStringAt(*stream, 0x6bd);
_strings.enterCommand = readStringAt(*stream, 0x6e9); _strings.enterCommand = readStringAt(*stream, 0x6e9);
// Read line feeds
_strings.lineFeeds = readStringAt(*stream, 0x408); _strings.lineFeeds = readStringAt(*stream, 0x408);
// Read opcode strings (TODO) // Read opcode strings (TODO)
@ -185,137 +154,38 @@ void HiRes6Engine::init() {
// _strings_v2.restoreReplace // _strings_v2.restoreReplace
_strings.playAgain = readStringAt(*stream, 0xcdf, 0xff); _strings.playAgain = readStringAt(*stream, 0xcdf, 0xff);
_messageIds.cantGoThere = IDI_HR6_MSG_CANT_GO_THERE; _messageIds.cantGoThere = 249;
_messageIds.dontUnderstand = IDI_HR6_MSG_DONT_UNDERSTAND; _messageIds.dontUnderstand = 247;
_messageIds.itemDoesntMove = IDI_HR6_MSG_ITEM_DOESNT_MOVE; _messageIds.itemDoesntMove = 253;
_messageIds.itemNotHere = IDI_HR6_MSG_ITEM_NOT_HERE; _messageIds.itemNotHere = 254;
_messageIds.thanksForPlaying = IDI_HR6_MSG_THANKS_FOR_PLAYING; _messageIds.thanksForPlaying = 252;
// Item descriptions stream.reset(loadSectors(_disk, 0x6, 0xb, 2));
stream.reset(loadSectors(_boot, 0x6, 0xb, 2));
stream->seek(0x16); stream->seek(0x16);
loadItemDescriptions(*stream, IDI_HR6_NUM_ITEM_DESCS); loadItemDescriptions(*stream, kItems);
// Load dropped item offsets stream.reset(_disk->createReadStream(0x8, 0x9, 0x16));
stream.reset(_boot->createReadStream(0x8, 0x9, 0x16)); loadDroppedItemOffsets(*stream, 16);
loadDroppedItemOffsets(*stream, IDI_HR6_NUM_ITEM_OFFSETS);
// Location of game data for each disc stream.reset(_disk->createReadStream(0xb, 0xd, 0x08));
stream.reset(_boot->createReadStream(0x5, 0xa, 0x03)); loadItemPicIndex(*stream, kItems);
for (uint i = 0; i < sizeof(disks); ++i) {
DiskDataDesc desc;
desc.track = stream->readByte();
desc.sector = stream->readByte();
desc.offset = stream->readByte();
desc.volume = stream->readByte();
_diskDataDesc.push_back(desc);
}
// DataBlockPtr offsets for each disk
stream.reset(_boot->createReadStream(0x3, 0xf, 0x03));
for (uint i = 0; i < sizeof(disks); ++i) {
DiskOffset offset;
offset.track = stream->readByte();
offset.sector = stream->readByte();
_diskOffsets.push_back(offset);
}
}
void HiRes6Engine::loadDisk(byte disk) {
delete _disk;
_disk = new DiskImage();
if (!_disk->open(disks[disk]))
error("Failed to open disk image '%s'", disks[disk]);
_curDisk = 0;
// Load item picture data (indexed on boot disk)
StreamPtr stream(_boot->createReadStream(0xb, 0xd, 0x08));
_itemPics.clear();
loadItemPictures(*stream, IDI_HR6_NUM_ITEM_PICS);
_curDisk = disk;
byte track = _diskDataDesc[disk].track;
byte sector = _diskDataDesc[disk].sector;
uint offset = _diskDataDesc[disk].offset;
applyDiskOffset(track, sector);
for (uint block = 0; block < 7; ++block) {
stream.reset(_disk->createReadStream(track, sector, offset, 1));
uint16 addr = stream->readUint16LE();
uint16 size = stream->readUint16LE();
stream.reset(_disk->createReadStream(track, sector, offset, size / 256 + 1));
stream->skip(4);
switch (addr) {
case 0x9000: {
// Messages
_messages.clear();
uint count = size / 4;
loadMessages(*stream, count);
break;
}
case 0x4a80: {
// Global pics
_pictures.clear();
loadPictures(*stream);
break;
}
case 0x4000:
// Verbs
loadWords(*stream, _verbs, _priVerbs);
break;
case 0x1800:
// Nouns
loadWords(*stream, _nouns, _priNouns);
break;
case 0x0e00: {
// Rooms
uint count = size / 14 - 1;
stream->skip(14); // Skip invalid room 0
_state.rooms.clear();
loadRooms(*stream, count);
break;
}
case 0x7b00:
// Global commands
readCommands(*stream, _globalCommands);
break;
case 0x9500:
// Room commands
readCommands(*stream, _roomCommands);
break;
default:
error("Unknown data block found (addr %04x; size %04x)", addr, size);
}
offset += 4 + size;
while (offset >= 256) {
offset -= 256;
++sector;
if (sector >= 16) {
sector = 0;
++track;
}
}
}
} }
void HiRes6Engine::initGameState() { void HiRes6Engine::initGameState() {
_state.vars.resize(IDI_HR6_NUM_VARS); _state.vars.resize(40);
loadDisk(1); insertDisk(0);
StreamPtr stream(_boot->createReadStream(0x3, 0xe, 0x03));
StreamPtr stream(_disk->createReadStream(0x3, 0xe, 0x03));
loadItems(*stream); loadItems(*stream);
// A combined total of 91 rooms
static const byte rooms[kRegions] = { 35, 29, 27 };
initRegions(rooms, kRegions);
loadRegion(1);
_currVerb = _currNoun = 0; _currVerb = _currNoun = 0;
} }
@ -425,11 +295,11 @@ void HiRes6Engine::printString(const Common::String &str) {
} }
if (getVar(2) != 0xff) { if (getVar(2) != 0xff) {
AdlEngine_v2::printString(s); AdlEngine_v5::printString(s);
} else { } else {
if (getVar(26) == 0) { if (getVar(26) == 0) {
if (str.size() != 1 || APPLECHAR(str[0]) != APPLECHAR(' ')) if (str.size() != 1 || APPLECHAR(str[0]) != APPLECHAR(' '))
return AdlEngine_v2::printString(s); return AdlEngine_v5::printString(s);
setVar(2, APPLECHAR(' ')); setVar(2, APPLECHAR(' '));
} else if (getVar(26) != 0xff) { } else if (getVar(26) != 0xff) {
setVar(2, 'P'); setVar(2, 'P');