mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-16 14:50:17 +00:00
432 lines
9.6 KiB
C++
432 lines
9.6 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Based on ScottFree interpreter version 1.14 developed by Swansea
|
|
* University Computer Society without disassembly of any other game
|
|
* drivers, only of game databases as permitted by EEC law (for purposes
|
|
* of compatibility).
|
|
*
|
|
* Licensed under GPLv2
|
|
*
|
|
* https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
|
|
*/
|
|
|
|
#include "glk/scott/scott.h"
|
|
#include "glk/scott/definitions.h"
|
|
#include "glk/scott/resource.h"
|
|
#include "glk/scott/globals.h"
|
|
#include "glk/scott/types.h"
|
|
#include "glk/scott/hulk.h"
|
|
|
|
namespace Glk {
|
|
namespace Scott {
|
|
|
|
void hulkShowImageOnExamine(int noun) {
|
|
int image = 0;
|
|
switch (noun) {
|
|
case 55: // Dome
|
|
if (_G(_items)[11]._location == MY_LOC)
|
|
image = 28;
|
|
break;
|
|
case 108: // Natter energy egg
|
|
if (_G(_items)[17]._location == MY_LOC || _G(_items)[17]._location == CARRIED)
|
|
image = 30;
|
|
break;
|
|
case 124: // Bio-Gem
|
|
case 41:
|
|
if (_G(_items)[18]._location == MY_LOC || _G(_items)[18]._location == CARRIED)
|
|
image = 29;
|
|
break;
|
|
case 21: // Killer Bees
|
|
if (_G(_items)[24]._location == MY_LOC)
|
|
image = 31;
|
|
break;
|
|
case 83: // Iron ring
|
|
if (_G(_items)[33]._location == MY_LOC)
|
|
image = 32;
|
|
break;
|
|
case 121: // Cage
|
|
if (_G(_items)[47]._location == MY_LOC)
|
|
image = 33;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (image) {
|
|
g_scott->drawImage(image);
|
|
g_scott->output(_G(_sys)[HIT_ENTER]);
|
|
g_scott->hitEnter();
|
|
}
|
|
}
|
|
|
|
void hulkLook() {
|
|
g_scott->drawImage(_G(_rooms)[MY_LOC]._image);
|
|
for (int ct = 0; ct <= _G(_gameHeader)->_numItems; ct++) {
|
|
int image = _G(_items)[ct]._image;
|
|
if (_G(_items)[ct]._location == MY_LOC && image != 255) {
|
|
/* Don't draw bio gem in fuzzy area */
|
|
if ((ct == 18 && MY_LOC != 15) ||
|
|
/* Don't draw Dr. Strange until outlet is plugged */
|
|
(ct == 26 && _G(_items)[28]._location != MY_LOC))
|
|
continue;
|
|
g_scott->drawImage(image);
|
|
}
|
|
}
|
|
}
|
|
|
|
void drawHulkImage(int p) {
|
|
int image = 0;
|
|
switch (p) {
|
|
case 85:
|
|
image = 34;
|
|
break;
|
|
case 86:
|
|
image = 35;
|
|
break;
|
|
case 83:
|
|
image = 36;
|
|
break;
|
|
case 84:
|
|
image = 37;
|
|
break;
|
|
case 87:
|
|
image = 38;
|
|
break;
|
|
case 88:
|
|
image = 39;
|
|
break;
|
|
case 89:
|
|
image = 40;
|
|
break;
|
|
case 82:
|
|
image = 41;
|
|
break;
|
|
case 81:
|
|
image = 42;
|
|
break;
|
|
default:
|
|
|
|
error("drawHulkImage: Unhandled image number %d", p);
|
|
break;
|
|
}
|
|
|
|
if (image != 0) {
|
|
g_scott->drawImage(image);
|
|
g_scott->output(_G(_sys)[HIT_ENTER]);
|
|
g_scott->hitEnter();
|
|
}
|
|
}
|
|
|
|
uint8_t *readHulkDictionary(GameInfo info, uint8_t **pointer) {
|
|
uint8_t *ptr = *pointer;
|
|
char *dictword = new char[info._wordLength + 2];
|
|
char c = 0;
|
|
int wordnum = 0;
|
|
int charindex = 0;
|
|
|
|
int nv = info._numberOfVerbs;
|
|
int nn = info._numberOfNouns;
|
|
|
|
for (int i = 0; i < nn - nv; i++)
|
|
_G(_verbs)[nv + i] = ".\0";
|
|
|
|
for (int i = 0; i < nv - nn; i++)
|
|
_G(_nouns)[nn + i] = ".\0";
|
|
|
|
do {
|
|
for (int i = 0; i < info._wordLength; i++) {
|
|
c = *(ptr++);
|
|
if (c == 0) {
|
|
if (charindex == 0) {
|
|
c = *(ptr++);
|
|
}
|
|
}
|
|
dictword[charindex] = c;
|
|
if (c == '*')
|
|
i--;
|
|
charindex++;
|
|
|
|
dictword[charindex] = 0;
|
|
}
|
|
|
|
if (wordnum < nn) {
|
|
_G(_nouns)[wordnum] = Common::String(dictword, charindex + 1);
|
|
} else {
|
|
_G(_verbs)[wordnum - nn] = Common::String(dictword, charindex + 1);
|
|
}
|
|
wordnum++;
|
|
|
|
if (c != 0 && !isascii(c))
|
|
return ptr;
|
|
|
|
charindex = 0;
|
|
} while (wordnum <= nv + nn);
|
|
|
|
delete[] dictword;
|
|
return ptr;
|
|
}
|
|
|
|
int tryLoadingHulk(GameInfo info, int dictStart) {
|
|
int ni, na, nw, nr, mc, pr, tr, wl, lt, mn, trm;
|
|
int ct;
|
|
|
|
Action *ap;
|
|
Room *rp;
|
|
Item *ip;
|
|
|
|
/* Load the header */
|
|
uint8_t *ptr = _G(_entireFile);
|
|
|
|
_G(_fileBaselineOffset) = dictStart - info._startOfDictionary - 645;
|
|
|
|
int offset = info._startOfHeader + _G(_fileBaselineOffset);
|
|
ptr = seekToPos(_G(_entireFile), offset);
|
|
|
|
if (ptr == 0)
|
|
return 0;
|
|
|
|
readHeader(ptr);
|
|
|
|
parseHeader(_G(_header), info._headerStyle, &ni, &na, &nw, &nr, &mc, &pr, &tr, &wl, <, &mn, &trm);
|
|
|
|
_G(_gameHeader)->_numItems = ni;
|
|
_G(_items).resize(ni + 1);
|
|
_G(_gameHeader)->_numActions = na;
|
|
_G(_actions).resize(na + 1);
|
|
_G(_gameHeader)->_numWords = nw;
|
|
_G(_gameHeader)->_wordLength = wl;
|
|
_G(_verbs).resize(nw + 1);
|
|
_G(_nouns).resize(nw + 1);
|
|
_G(_gameHeader)->_numRooms = nr;
|
|
_G(_rooms).resize(nr + 1);
|
|
_G(_gameHeader)->_maxCarry = mc;
|
|
_G(_gameHeader)->_playerRoom = pr;
|
|
_G(_gameHeader)->_treasures = tr;
|
|
_G(_gameHeader)->_lightTime = lt;
|
|
_G(_lightRefill) = lt;
|
|
_G(_gameHeader)->_numMessages = mn;
|
|
_G(_messages).resize(mn + 1);
|
|
_G(_gameHeader)->_treasureRoom = trm;
|
|
|
|
if (_G(_header)[0] != info._wordLength || _G(_header)[1] != info._numberOfWords || _G(_header)[2] != info._numberOfActions || _G(_header)[3] != info._numberOfItems || _G(_header)[4] != info._numberOfMessages || _G(_header)[5] != info._numberOfRooms || _G(_header)[6] != info._maxCarried) {
|
|
return 0;
|
|
}
|
|
|
|
#pragma mark Dictionary
|
|
|
|
if (seekIfNeeded(info._startOfDictionary, &offset, &ptr) == 0)
|
|
return 0;
|
|
|
|
readHulkDictionary(info, &ptr);
|
|
|
|
#pragma mark Rooms
|
|
|
|
if (seekIfNeeded(info._startOfRoomDescriptions, &offset, &ptr) == 0)
|
|
return 0;
|
|
|
|
ct = 0;
|
|
|
|
uint8_t string_length = 0;
|
|
do {
|
|
rp = &_G(_rooms)[ct];
|
|
string_length = *(ptr++);
|
|
if (string_length == 0) {
|
|
rp->_text = ".\0";
|
|
} else {
|
|
for (int i = 0; i < string_length; i++) {
|
|
rp->_text += *(ptr++);
|
|
}
|
|
}
|
|
ct++;
|
|
} while (ct < nr + 1);
|
|
|
|
#pragma mark Messages
|
|
|
|
ct = 0;
|
|
const char *string;
|
|
|
|
do {
|
|
string_length = *(ptr++);
|
|
if (string_length == 0) {
|
|
string = ".\0";
|
|
_G(_messages)[ct] = string;
|
|
} else {
|
|
char *s = new char[string_length + 1];
|
|
for (int i = 0; i < string_length; i++) {
|
|
s[i] = *(ptr++);
|
|
}
|
|
s[string_length] = 0;
|
|
_G(_messages)[ct] = s;
|
|
}
|
|
ct++;
|
|
} while (ct < mn + 1);
|
|
|
|
#pragma mark Items
|
|
|
|
if (seekIfNeeded(info._startOfItemDescriptions, &offset, &ptr) == 0)
|
|
return 0;
|
|
|
|
ct = 0;
|
|
|
|
do {
|
|
ip = &_G(_items)[ct];
|
|
string_length = *(ptr++);
|
|
if (string_length == 0) {
|
|
ip->_text = ".\0";
|
|
} else {
|
|
for (int i = 0; i < string_length; i++) {
|
|
ip->_text += *(ptr++);
|
|
}
|
|
const char *p = strchr(ip->_text.c_str(), '/');
|
|
if (p) {
|
|
ip->_autoGet = Common::String(p);
|
|
|
|
/* Some games use // to mean no auto get/drop word! */
|
|
if (!(ip->_autoGet == "//") && !(ip->_autoGet == "/*")) {
|
|
ip->_text = Common::String(ip->_text.c_str(), p);
|
|
ip->_autoGet.deleteChar(0);
|
|
|
|
const char *t = strchr(ip->_autoGet.c_str(), '/');
|
|
if (t) {
|
|
ip->_autoGet = Common::String(ip->_autoGet.c_str(), t);
|
|
}
|
|
ptr++;
|
|
}
|
|
}
|
|
}
|
|
|
|
ct++;
|
|
} while (ct < ni + 1);
|
|
|
|
#pragma mark Room connections
|
|
|
|
if (seekIfNeeded(info._startOfRoomConnections, &offset, &ptr) == 0)
|
|
return 0;
|
|
|
|
/* The room connections are ordered by direction, not room, so all the North
|
|
* connections for all the rooms come first, then the South connections, and
|
|
* so on. */
|
|
for (int j = 0; j < 6; j++) {
|
|
ct = 0;
|
|
|
|
while (ct < nr + 1) {
|
|
rp = &_G(_rooms)[ct];
|
|
rp->_exits[j] = *(ptr++);
|
|
ptr++;
|
|
ct++;
|
|
}
|
|
}
|
|
|
|
#pragma mark item locations
|
|
|
|
if (seekIfNeeded(info._startOfItemLocations, &offset, &ptr) == 0)
|
|
return 0;
|
|
|
|
ct = 0;
|
|
while (ct < ni + 1) {
|
|
ip = &_G(_items)[ct];
|
|
ip->_location = *(ptr++);
|
|
ip->_location += *(ptr++) * 0x100;
|
|
ip->_initialLoc = ip->_location;
|
|
ct++;
|
|
}
|
|
|
|
#pragma mark room images
|
|
|
|
if (seekIfNeeded(info._startOfRoomImageList, &offset, &ptr) == 0)
|
|
return 0;
|
|
|
|
for (ct = 0; ct <= _G(_gameHeader)->_numRooms; ct++) {
|
|
rp = &_G(_rooms)[ct];
|
|
rp->_image = *(ptr++);
|
|
}
|
|
|
|
#pragma mark item images
|
|
|
|
if (seekIfNeeded(info._startOfItemImageList, &offset, &ptr) == 0)
|
|
return 0;
|
|
|
|
for (ct = 0; ct <= _G(_gameHeader)->_numItems; ct++) {
|
|
ip = &_G(_items)[ct];
|
|
ip->_image = 255;
|
|
}
|
|
|
|
int index, image = 10;
|
|
|
|
for (index = (*ptr++); index != 255; index = (*ptr++)) {
|
|
_G(_items)[index]._image = image++;
|
|
}
|
|
|
|
#pragma mark item flags
|
|
|
|
/* Hulk does not seem to use item flags */
|
|
|
|
#pragma mark Actions
|
|
|
|
if (seekIfNeeded(info._startOfActions, &offset, &ptr) == 0)
|
|
return 0;
|
|
|
|
ct = 0;
|
|
|
|
int verb, noun, value, value2, plus;
|
|
while (ct < na + 1) {
|
|
ap = &_G(_actions)[ct];
|
|
plus = na + 1;
|
|
verb = _G(_entireFile)[offset + ct];
|
|
noun = _G(_entireFile)[offset + ct + plus];
|
|
|
|
ap->_vocab = verb * 150 + noun;
|
|
|
|
for (int j = 0; j < 2; j++) {
|
|
plus += na + 1;
|
|
value = _G(_entireFile)[offset + ct + plus];
|
|
plus += na + 1;
|
|
value2 = _G(_entireFile)[offset + ct + plus];
|
|
ap->_action[j] = 150 * value + value2;
|
|
}
|
|
|
|
int offset2 = offset + 0x624;
|
|
plus = 0;
|
|
|
|
for (int j = 0; j < 5; j++) {
|
|
value = _G(_entireFile)[offset2 + ct * 2 + plus];
|
|
value2 = _G(_entireFile)[offset2 + ct * 2 + plus + 1];
|
|
ap->_condition[j] = value + value2 * 0x100;
|
|
plus += (na + 1) * 2;
|
|
}
|
|
ct++;
|
|
}
|
|
|
|
if (CURRENT_GAME == HULK_C64) {
|
|
_G(_hulkCoordinates) = 0x22cd;
|
|
_G(_hulkItemImageOffsets) = 0x2731;
|
|
_G(_hulkLookImageOffsets) = 0x2761;
|
|
_G(_hulkSpecialImageOffsets) = 0x2781;
|
|
_G(_hulkImageOffset) = -0x7ff;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
} // End of namespace Scott
|
|
} // End of namespace Glk
|