ADL: Bring hires6 in line with hires5
This commit is contained in:
parent
a938942f03
commit
441f940069
6 changed files with 124 additions and 308 deletions
|
@ -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 §or, 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;
|
||||||
|
|
|
@ -60,12 +60,24 @@ protected:
|
||||||
// AdlEngine_v2
|
// AdlEngine_v2
|
||||||
virtual void adjustDataBlockPtr(byte &track, byte §or, byte &offset, byte &size) const;
|
virtual void adjustDataBlockPtr(byte &track, byte §or, 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 §or) const;
|
void fixupDiskOffset(byte &track, byte §or) 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);
|
||||||
|
|
|
@ -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 §or) const {
|
|
||||||
sector += _diskOffsets[_curDisk].sector;
|
|
||||||
if (sector >= 16) {
|
|
||||||
sector -= 16;
|
|
||||||
++track;
|
|
||||||
}
|
|
||||||
|
|
||||||
track += _diskOffsets[_curDisk].track;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdlEngine_v5::adjustDataBlockPtr(byte &track, byte §or, 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
|
||||||
|
|
||||||
|
|
|
@ -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 §or, byte &offset, byte &size) const;
|
virtual RegionChunkType getRegionChunkType(const uint16 addr) const;
|
||||||
|
|
||||||
void applyDiskOffset(byte &track, byte §or) 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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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');
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue