Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

1
engines/chewy/POTFILES Normal file
View File

@@ -0,0 +1 @@
engines/chewy/metaengine.cpp

116
engines/chewy/ani_dat.h Normal file
View File

@@ -0,0 +1,116 @@
/* 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/>.
*
*/
#ifndef CHEWY_ANIDAT_H
#define CHEWY_ANIDAT_H
namespace Chewy {
#define SIB_CABLE_R1 1
#define SIB_MONOCLE 6
#define SIB_NOTEBOOK 7
#define SIB_TERMINAL_R5 8
#define SIB_BUTTON_R5 9
#define SIB_DOOR_R5 10
#define SIB_TBUTTON1_R6 11
#define SIB_SEIL 12
#define SIB_TBUTTON2_R6 13
#define SIB_TBUTTON3_R6 15
#define SIB_BOLA_SCHACHT 17
#define SIB_BOLA_BUTTON_R6 18
#define SIB_BOLA_FLECK_R6 20
#define SIB_BOLA_R6 21
#define SIB_TBUTTON1_R7 22
#define SIB_HEBEL_R7 23
#define SIB_KLINGEL_R7 24
#define SIB_GIPS_R7 25
#define SIB_TBUTTON2_R7 26
#define SIB_SCHLOTT_R7 27
#define SIB_LHAKEN_R7 28
#define SIB_RHAKEN_R7 29
#define SIB_FOLTER_R8 30
#define SIB_GTUER 31
#define SIB_TUER_R8 32
#define SIB_GIPS_R8 33
#define SIB_DEE_PAINT_R9 34
#define SIB_GGITTER_R9 35
#define SIB_SURIMY_R10 36
#define SIB_PAINT_R22 37
#define SIB_SCHLITZ_R11 38
#define SIB_TBUTTON1_R11 39
#define SIB_BANDBUTTON_R13 40
#define SIB_TBUTTON2_R11 41
#define SIB_TBUTTON3_R11 42
#define SIB_CARTRIDGE_R23 43
#define SIB_FLUXO_R23 44
#define SIB_TRANSLATOR_23 45
#define SIB_FEUER_R14 46
#define SIB_TALISMAN_R12 47
#define SIB_ROEHRE_R12 48
#define SIB_L_ROEHRE_R12 49
#define SIB_GITTER_R16 50
#define SIB_SCHALTER1_R21 51
#define SIB_SCHALTER2_R21 52
#define SIB_SCHALTER3_R21 53
#define SIB_SEIL_R21 54
#define SIB_GITTER1_R21 55
#define SIB_GITTER2_R21 56
#define SIB_FLUESSIG_R17 57
#define SIB_HEBEL_R17 58
#define SIB_CART1_R18 59
#define SIB_DOORKNOB_R18 60
#define SIB_CART_FACH_R18 61
#define SIB_SCHLAUCH_R25 62
#define SIB_SCHLAUCH_R26 63
#define SIB_TRICHTER_R26 64
#define SIB_ANGEL0_R26 65
#define SIB_MILCH_R27 66
#define SIB_AUTO_SITZ 67
#define SIB_PUTE_R34 68
#define SIB_KAFFEE_R33 69
#define SIB_ZAPPER_R39 70
#define SIB_KNOCHEN_R35 71
#define SIB_RADIO_R35 72
#define SIB_TOPF_R31 73
#define SIB_HFUTTER1_R37 74
#define SIB_HFUTTER2_R37 75
#define SIB_KUERBIS_R37 76
#define SIB_AUTO_R28 77
#define SIB_SURIMY_R27 78
#define SIB_ZEITUNG_R27 79
#define SIB_BKASTEN_R28 80
#define SIB_MUENZE_R40 81
#define SIB_VISIT_R53 82
#define SIB_CIGAR_R50 83
#define SIB_KAPPE_R51 84
#define SIB_FLASCHE_R51 85
#define SIB_LAMPE_R52 86
#define SIB_AUSRUEST_R51 87
#define SIB_KAUTABAK_R56 88
#define SIB_ASHTRAY_R64 89
#define SIB_PIRANHA 90
#define SIB_SCHALL 91
#define SIB_ARTEFAKT 92
#define SIB_AUSRUEST_R52 93
} // namespace Chewy
#endif

972
engines/chewy/atds.cpp Normal file
View File

@@ -0,0 +1,972 @@
/* 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/>.
*
*/
#include "common/memstream.h"
#include "chewy/atds.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/font.h"
#include "chewy/globals.h"
#include "chewy/mcga_graphics.h"
#include "chewy/sound.h"
#include "chewy/text.h"
namespace Chewy {
bool AtsTxtHeader::load(Common::SeekableReadStream *src) {
_txtNr = src->readUint16LE();
_aMov = src->readSint16LE();
_curNr = src->readSint16LE();
src->skip(2);
return true;
}
void AadInfo::load(Common::SeekableReadStream *src) {
_x = src->readSint16LE();
_y = src->readSint16LE();
_color = src->readSint16LE();
}
void AadInfoArray::load(const void *data, size_t count) {
resize(count);
Common::MemoryReadStream src((const byte *)data, count * AadInfo::SIZE());
for (uint i = 0; i < count; ++i)
(*this)[i].load(&src);
}
bool DialogCloseupTxtHeader::load(const void *src) {
Common::MemoryReadStream rs((const byte *)src, 8);
_diaNr = rs.readSint16LE();
_perNr = rs.readSint16LE();
_aMov = rs.readSint16LE();
_curNr = rs.readSint16LE();
return true;
}
Atdsys::Atdsys() {
SplitStringInit init_ssi = { nullptr, 0, 0 };
_aadv._dialog = false;
_aadv._strNr = -1;
_aadv._silentCount = false;
_dialogCloseup._dialog = -1;
_dialogCloseup._autoDia = false;
_dialogCloseup._strNr = -1;
_dialogCloseup._silentCount = false;
_atdsv._delay = 1;
_atdsv._silent = false;
_atdsv._diaNr = -1;
_atdsv.aad_str = nullptr;
_atdsv._vocNr = -1;
_atdsv._eventsEnabled = true;
for (int16 i = 0; i < AAD_MAX_PERSON; i++)
_ssi[i] = init_ssi;
_invBlockNr = -1;
_dialogResource = new DialogResource(ADS_TXT_STEUER);
_text = _G(txt);
_dialogCloseupNextBlock._blkNr = 0;
_dialogCloseupNextBlock._endNr = 0;
_dialogCloseupStackPtr = 0;
init();
initItemUseWith();
}
Atdsys::~Atdsys() {
for (int16 i = 0; i < MAX_HANDLE; i++) {
if (_atdsMem[i])
free(_atdsMem[i]);
_atdsMem[i] = nullptr;
}
delete _dialogResource;
}
void Atdsys::init() {
set_handle(AAD_DATA, AAD_TAP_OFF, AAD_TAP_MAX);
set_handle(DIALOG_CLOSEUP_DATA, ADS_TAP_OFF, ADS_TAP_MAX);
_G(gameState).AadSilent = 10;
_G(gameState).DelaySpeed = 5;
_G(moveState)[P_CHEWY].Delay = _G(gameState).DelaySpeed;
set_delay(&_G(gameState).DelaySpeed, _G(gameState).AadSilent);
set_string_end_func(&atdsStringStart);
}
void Atdsys::initItemUseWith() {
int16 objA, objB, txtNum;
Common::File f;
f.open(INV_USE_IDX);
// The file is 25200 bytes, and contains 25200 / 50 / 6 = 84 blocks
int totalEntries = f.size() / 6;
for (int entry = 0; entry < totalEntries; entry++) {
objA = f.readSint16LE();
objB = f.readSint16LE();
txtNum = f.readSint16LE();
assert(objA <= 255);
const uint32 key = (objA & 0xff) << 16 | objB;
_itemUseWithDesc[key] = txtNum;
}
f.close();
}
void Atdsys::set_delay(int16 *delay, int16 silent) {
_atdsv._delay = *delay;
_atdsv._silent = silent;
}
void Atdsys::set_string_end_func
(void (*strFunc)(int16 diaNr, int16 strNr, int16 personNr, int16 mode)) {
_atdsv.aad_str = strFunc;
}
int16 Atdsys::get_delay(int16 txt_len) {
const int16 width = 220;
const int16 lines = 4;
const int16 w = _G(fontMgr)->getFont()->getDataWidth();
int16 z_len = (width / w) + 1;
int16 maxLen = z_len * lines;
if (txt_len > maxLen)
txt_len = maxLen;
int16 ret = _atdsv._delay * (txt_len + z_len);
return ret;
}
void Atdsys::split_string(SplitStringInit *ssi_, SplitStringRet *ret) {
const int16 w = _G(fontMgr)->getFont()->getDataWidth();
const int16 h = _G(fontMgr)->getFont()->getDataHeight();
const int16 width = 220;
const int16 lines = 4;
ret->_nr = 0;
ret->_next = false;
ret->_strPtr = _splitPtr;
ret->_x = _splitX;
int16 zeichen_anz = (width / w) + 1;
memset(_splitPtr, 0, sizeof(char *) * MAX_STR_SPLIT);
calc_txt_win(ssi_);
char *str_adr = ssi_->_str;
int16 count = 0;
int16 tmp_count = 0;
bool endLoop = false;
char *start_adr = str_adr;
while (!endLoop) {
switch (*str_adr) {
case 0:
if (str_adr[1] != ATDS_END_TEXT) {
str_adr[0] = ' ';
}
// Fall through
case 0x20:
if (count < zeichen_anz && *str_adr == 0) {
tmp_count = count;
}
if (count < zeichen_anz && *str_adr != 0) {
tmp_count = count;
++str_adr;
++count;
} else {
_splitPtr[ret->_nr] = start_adr;
start_adr[tmp_count] = 0;
_splitX[ret->_nr] = ssi_->_x + ((width - (strlen(start_adr) * w)) >> 1);
++ret->_nr;
if (ret->_nr == lines) {
endLoop = true;
bool endInnerLoop = false;
while (!endInnerLoop) {
if (*str_adr == ATDS_END_TEXT)
endInnerLoop = true;
else if (*str_adr != ' ' && *str_adr != 0) {
endInnerLoop = true;
ret->_next = true;
}
++str_adr;
}
} else if (*str_adr == 0 && count < zeichen_anz) {
endLoop = true;
} else {
str_adr = start_adr + tmp_count + 1;
start_adr = str_adr;
count = 0;
tmp_count = 0;
}
}
break;
case '!':
case '?':
case '.':
case ',':
if (str_adr[1] == 0 || str_adr[1] == ' ') {
int16 test_zeilen;
if (*str_adr == ',')
test_zeilen = 1;
else
test_zeilen = 2;
++count;
++str_adr;
if (ret->_nr + test_zeilen >= lines) {
if (count < zeichen_anz) {
tmp_count = count;
endLoop = true;
}
_splitPtr[ret->_nr] = start_adr;
start_adr[tmp_count] = 0;
_splitX[ret->_nr] = ssi_->_x + ((width - (strlen(start_adr) * w)) >> 1);
++ret->_nr;
bool ende1 = false;
while (!ende1) {
if (*str_adr == ATDS_END_TEXT)
ende1 = true;
else if (*str_adr != ' ' && *str_adr != 0) {
ende1 = true;
ret->_next = true;
}
++str_adr;
}
if (!endLoop) {
str_adr = start_adr + tmp_count + 1;
start_adr = str_adr;
count = 0;
tmp_count = 0;
}
}
} else {
++count;
++str_adr;
}
break;
default:
++count;
++str_adr;
break;
}
}
if (ret->_nr <= lines)
ret->_y = ssi_->_y + (lines - ret->_nr) * h;
else
ret->_y = ssi_->_y;
}
void Atdsys::str_null2leer(char *strStart, char *strEnd) {
while (strStart < strEnd) {
if (*strStart == 0)
*strStart = 32;
++strStart;
}
}
void Atdsys::calc_txt_win(SplitStringInit *ssi_) {
const int16 h = _G(fontMgr)->getFont()->getDataHeight();
const int16 width = 220;
const int16 lines = 4;
if (ssi_->_x - (width >> 1) < 2)
ssi_->_x = 2;
else if (ssi_->_x + (width >> 1) > (SCREEN_WIDTH - 2))
ssi_->_x = ((SCREEN_WIDTH - 2) - width);
else
ssi_->_x -= (width >> 1);
if (ssi_->_y - (lines * h) < 2) {
ssi_->_y = 2;
} else if (ssi_->_y + (lines * h) > (SCREEN_HEIGHT - 2))
ssi_->_y = (SCREEN_HEIGHT - 2) - (lines * h);
else {
ssi_->_y -= (lines * h);
}
}
void Atdsys::set_split_win(int16 nr, int16 x, int16 y) {
_ssi[nr]._x = x;
_ssi[nr]._y = y;
}
void Atdsys::set_handle(int16 mode, int16 chunkStart, int16 chunkNr) {
assert(mode == AAD_DATA || mode == DIALOG_CLOSEUP_DATA);
uint32 size = _text->findLargestChunk(chunkStart, chunkStart + chunkNr);
char *tmp_adr = size ? (char *)MALLOC(size + 3) : nullptr;
if (_atdsMem[mode])
free(_atdsMem[mode]);
_atdsMem[mode] = tmp_adr;
_atdsPoolOff[mode] = chunkStart;
}
void Atdsys::load_atds(int16 chunkNr, int16 mode) {
assert(mode == AAD_DATA || mode == DIALOG_CLOSEUP_DATA);
char *txt_adr = _atdsMem[mode];
if (txt_adr) {
const uint32 chunkSize = _text->getChunk(chunkNr + _atdsPoolOff[mode])->size;
const uint8 *chunkData = _text->getChunkData(chunkNr + _atdsPoolOff[mode]);
memcpy(txt_adr, chunkData, chunkSize);
delete[] chunkData;
txt_adr[chunkSize] = (char)BLOCKENDE;
txt_adr[chunkSize + 1] = (char)BLOCKENDE;
txt_adr[chunkSize + 2] = (char)BLOCKENDE;
}
}
bool Atdsys::start_ats(int16 txtNr, int16 txtMode, int16 color, int16 mode, int16 *vocNr) {
assert(mode == ATS_DATA || mode == INV_USE_DATA || mode == INV_USE_DEF);
EVENTS_CLEAR;
g_events->_kbInfo._scanCode = Common::KEYCODE_INVALID;
g_events->_kbInfo._keyCode = '\0';
_G(minfo).button = 0;
*vocNr = -1;
_atsv.shown = false;
Common::StringArray textArray;
if (mode != INV_USE_DEF) {
const uint8 roomNum = _G(room)->_roomInfo->_roomNr;
textArray = getTextArray(roomNum, txtNr, mode, txtMode);
} else {
textArray = getTextArray(0, txtNr, mode, -1);
}
_atsv.text.clear();
for (uint i = 0; i < textArray.size(); i++)
_atsv.text += textArray[i] + " ";
_atsv.text.deleteLastChar();
if (_atsv.text.size() > 0) {
*vocNr = txtMode != TXT_MARK_NAME ? _text->getLastSpeechId() : -1;
_atsv.shown = true;
_atsv._txtMode = txtMode;
_atsv._delayCount = get_delay(_atsv.text.size());
_atsv._color = color;
_printDelayCount1 = _atsv._delayCount / 10;
_mousePush = true;
}
return _atsv.shown;
}
void Atdsys::stop_ats() {
_atsv.shown = false;
}
void Atdsys::print_ats(int16 x, int16 y, int16 scrX, int16 scrY) {
if (_atsv.shown) {
if (_atdsv._eventsEnabled) {
switch (g_events->getSwitchCode()) {
case Common::KEYCODE_ESCAPE:
case Common::KEYCODE_RETURN:
case Common::MOUSE_BUTTON_LEFT:
if (!_mousePush) {
EVENTS_CLEAR;
g_events->_kbInfo._scanCode = Common::KEYCODE_INVALID;
g_events->_kbInfo._keyCode = '\0';
_G(minfo).button = 0;
if (_atsv._silentCount <= 0 && _atsv._delayCount > _printDelayCount1) {
_mousePush = true;
_atsv._delayCount = 0;
}
}
break;
default:
_mousePush = false;
break;
}
} else {
_mousePush = false;
}
if (_atsv._silentCount <= 0) {
// TODO: Rewrite this
SplitStringInit *atsSsi = &_ssi[0];
char *txt = new char[_atsv.text.size() + 2];
const int16 h = _G(fontMgr)->getFont()->getDataHeight();
uint shownLen = 0;
SplitStringRet splitString;
Common::strlcpy(txt, _atsv.text.c_str(), _atsv.text.size() + 1);
txt[_atsv.text.size() + 1] = ATDS_END_TEXT;
atsSsi->_str = txt;
atsSsi->_x = x - scrX;
atsSsi->_y = y - scrY;
split_string(atsSsi, &splitString);
for (int16 i = 0; i < splitString._nr; i++) {
if (g_engine->_sound->subtitlesEnabled()) {
_G(out)->printxy(splitString._x[i],
splitString._y + (i * h) + 1,
0, 300, 0, splitString._strPtr[i]);
_G(out)->printxy(splitString._x[i],
splitString._y + (i * h) - 1,
0, 300, 0, splitString._strPtr[i]);
_G(out)->printxy(splitString._x[i] + 1,
splitString._y + (i * h),
0, 300, 0, splitString._strPtr[i]);
_G(out)->printxy(splitString._x[i] - 1,
splitString._y + (i * h),
0, 300, 0, splitString._strPtr[i]);
_G(out)->printxy(splitString._x[i],
splitString._y + (i * h),
_atsv._color,
300, 0, splitString._strPtr[i]);
}
shownLen += strlen(splitString._strPtr[i]) + 1;
}
delete[] txt;
if (_atsv._delayCount <= 0) {
if (!splitString._next) {
_atsv.shown = false;
} else {
_atsv._delayCount = get_delay(_atsv.text.size() - shownLen);
_printDelayCount1 = _atsv._delayCount / 10;
_atsv._silentCount = _atdsv._silent;
}
} else {
--_atsv._delayCount;
}
} else {
--_atsv._silentCount;
}
}
}
void Atdsys::set_ats_str(int16 txtNr, int16 txtMode, int16 strNr, int16 mode) {
_text->setSubtextNum(txtNr, txtMode, strNr, mode);
}
void Atdsys::set_all_ats_str(int16 txtNr, int16 strNr, int16 mode) {
for (int16 i = 0; i < 5; i++)
set_ats_str(txtNr, i, strNr, mode);
}
int16 Atdsys::getControlBit(int16 txtNr, int16 bitIdx) {
return _text->getControlBit(txtNr, bitIdx);
}
void Atdsys::setControlBit(int16 txtNr, int16 bitIdx) {
_text->setControlBit(txtNr, bitIdx);
}
void Atdsys::delControlBit(int16 txtNr, int16 bitIdx) {
_text->delControlBit(txtNr, bitIdx);
}
int16 Atdsys::start_aad(int16 diaNr, bool continueWhenSpeechEnds) {
if (_aadv._dialog)
stopAad();
_continueWhenSpeechEnds = continueWhenSpeechEnds;
EVENTS_CLEAR;
g_events->_kbInfo._scanCode = Common::KEYCODE_INVALID;
g_events->_kbInfo._keyCode = '\0';
_G(minfo).button = 0;
if (_atdsMem[AAD_HANDLE]) {
_aadv._ptr = _atdsMem[AAD_HANDLE];
aad_search_dia(diaNr, &_aadv._ptr);
if (_aadv._ptr) {
_aadv._person.load(_aadv._ptr, _aadv._txtHeader->_perNr);
_aadv._ptr += _aadv._txtHeader->_perNr * sizeof(AadInfo);
_aadv._dialog = true;
_aadv._strNr = 0;
_aadv._strHeader = (AadStrHeader *)_aadv._ptr;
_aadv._ptr += sizeof(AadStrHeader);
int16 txtLen = aadGetTxtLen(_aadv._ptr);
_aadv._delayCount = get_delay(txtLen);
_printDelayCount1 = _aadv._delayCount / 10;
_atdsv._diaNr = diaNr;
if (_atdsv.aad_str != nullptr)
_atdsv.aad_str(_atdsv._diaNr, 0, _aadv._strHeader->_akPerson, AAD_STR_START);
_mousePush = true;
stop_ats();
_atdsv._vocNr = -1;
}
}
return _aadv._dialog;
}
void Atdsys::stopAad() {
_aadv._dialog = false;
_aadv._strNr = -1;
}
void Atdsys::print_aad(int16 scrX, int16 scrY) {
if (_aadv._dialog) {
if (_atdsv._eventsEnabled) {
switch (g_events->getSwitchCode()) {
case Common::KEYCODE_ESCAPE:
case Common::KEYCODE_RETURN:
case Common::MOUSE_BUTTON_LEFT:
if (!_mousePush) {
EVENTS_CLEAR;
g_events->_kbInfo._scanCode = Common::KEYCODE_INVALID;
g_events->_kbInfo._keyCode = '\0';
_G(minfo).button = 0;
if (_aadv._silentCount <= 0 && _aadv._delayCount > _printDelayCount1) {
_mousePush = true;
_aadv._delayCount = 0;
}
}
break;
default:
_mousePush = false;
break;
}
} else {
_mousePush = false;
}
if (_aadv._silentCount <= 0) {
char *tmp_ptr = _aadv._ptr;
const int16 personId = _aadv._strHeader->_akPerson;
_ssi[personId]._str = tmp_ptr;
if (_aadv._person[personId]._x != -1) {
_ssi[personId]._x = _aadv._person[personId]._x - scrX;
}
if (_aadv._person[personId]._y != -1) {
_ssi[personId]._y = _aadv._person[personId]._y - scrY;
}
char *start_ptr = tmp_ptr;
int16 txtLen = aadGetTxtLen(start_ptr);
str_null2leer(start_ptr, start_ptr + txtLen - 1);
SplitStringInit tmp_ssi = _ssi[personId];
SplitStringRet splitString;
split_string(&tmp_ssi, &splitString);
const int16 h = _G(fontMgr)->getFont()->getDataHeight();
for (int16 i = 0; i < splitString._nr; i++) {
if (g_engine->_sound->subtitlesEnabled() ||
_aadv._strHeader->_vocNr - ATDS_VOC_OFFSET == -1) {
_G(out)->printxy(splitString._x[i] + 1,
splitString._y + (i * h),
0, 300, 0, splitString._strPtr[i]);
_G(out)->printxy(splitString._x[i] - 1,
splitString._y + (i * h),
0, 300, 0, splitString._strPtr[i]);
_G(out)->printxy(splitString._x[i],
splitString._y + (i * h) + 1,
0, 300, 0, splitString._strPtr[i]);
_G(out)->printxy(splitString._x[i],
splitString._y + (i * h) - 1,
0, 300, 0, splitString._strPtr[i]);
_G(out)->printxy(splitString._x[i],
splitString._y + (i * h),
_aadv._person[personId]._color,
300, 0, splitString._strPtr[i]);
}
tmp_ptr += strlen(splitString._strPtr[i]) + 1;
}
str_null2leer(start_ptr, start_ptr + txtLen - 1);
if (g_engine->_sound->speechEnabled() &&
_aadv._strHeader->_vocNr - ATDS_VOC_OFFSET != -1) {
if (_atdsv._vocNr != _aadv._strHeader->_vocNr - ATDS_VOC_OFFSET) {
_atdsv._vocNr = _aadv._strHeader->_vocNr - ATDS_VOC_OFFSET;
g_engine->_sound->playSpeech(_atdsv._vocNr, false);
}
if (_continueWhenSpeechEnds && _atdsv._vocNr >= 0 && !g_engine->_sound->isSpeechActive())
stopAad();
}
if (_aadv._delayCount <= 0) {
_aadv._ptr = tmp_ptr;
while (*tmp_ptr == ' ' || *tmp_ptr == 0)
++tmp_ptr;
if (tmp_ptr[1] == ATDS_END ||
tmp_ptr[1] == ATDS_END_ENTRY) {
if (_atdsv.aad_str != 0)
_atdsv.aad_str(_atdsv._diaNr, _aadv._strNr, personId, AAD_STR_END);
_aadv._dialog = false;
_dialogCloseup._autoDia = false;
_aadv._strNr = -1;
splitString._next = false;
} else {
if (!splitString._next) {
++_aadv._strNr;
while (*_aadv._ptr++ != ATDS_END_TEXT) {}
const int16 tmp_person = _aadv._strHeader->_akPerson;
const int16 tmp_str_nr = _aadv._strNr;
_aadv._strHeader = (AadStrHeader *)_aadv._ptr;
_aadv._ptr += sizeof(AadStrHeader);
if (_atdsv.aad_str != nullptr) {
if (tmp_person != _aadv._strHeader->_akPerson) {
_atdsv.aad_str(_atdsv._diaNr, tmp_str_nr, tmp_person, AAD_STR_END);
_atdsv.aad_str(_atdsv._diaNr, _aadv._strNr, _aadv._strHeader->_akPerson, AAD_STR_START);
}
}
}
txtLen = aadGetTxtLen(_aadv._ptr);
_aadv._delayCount = get_delay(txtLen);
_printDelayCount1 = _aadv._delayCount / 10;
_aadv._silentCount = _atdsv._silent;
}
} else {
if (_aadv._strHeader->_vocNr - ATDS_VOC_OFFSET == -1)
--_aadv._delayCount;
}
} else {
--_aadv._silentCount;
}
}
}
int16 Atdsys::aadGetStatus() {
return _aadv._strNr;
}
int16 Atdsys::aadGetTxtLen(char *str) {
char *ptr = str;
while (*str != ATDS_END_TEXT)
++str;
int16 txtLen = (str - ptr) - 1;
return txtLen;
}
void Atdsys::aad_search_dia(int16 diaNr, char **ptr) {
char *start_ptr = *ptr;
if (start_ptr[0] == (char)BLOCKENDE &&
start_ptr[1] == (char)BLOCKENDE &&
start_ptr[2] == (char)BLOCKENDE) {
*ptr = nullptr;
} else {
bool ende = false;
while (!ende) {
uint16 *pos = (uint16 *)start_ptr;
if (pos[0] == diaNr) {
ende = true;
_aadv._txtHeader = (DialogCloseupTxtHeader *)start_ptr;
*ptr = start_ptr + sizeof(DialogCloseupTxtHeader);
} else {
start_ptr += sizeof(DialogCloseupTxtHeader) + pos[1] * sizeof(AadInfo);
bool ende1 = false;
for (; !ende1; ++start_ptr) {
if (*start_ptr != ATDS_END_TEXT)
continue;
if (start_ptr[1] == ATDS_END) {
++start_ptr;
if (start_ptr[1] == (char)BLOCKENDE &&
start_ptr[2] == (char)BLOCKENDE &&
start_ptr[3] == (char)BLOCKENDE) {
ende = true;
ende1 = true;
*ptr = nullptr;
} else {
ende1 = true;
}
}
}
}
}
}
}
bool Atdsys::startDialogCloseup(int16 diaNr) {
bool ret = false;
bool end = false;
load_atds(diaNr, DIALOG_CLOSEUP_DATA);
if (_atdsMem[ADS_HANDLE][0] == (char)BLOCKENDE &&
_atdsMem[ADS_HANDLE][1] == (char)BLOCKENDE &&
_atdsMem[ADS_HANDLE][2] == (char)BLOCKENDE)
end = true;
if (!end) {
_dialogCloseup._ptr = _atdsMem[ADS_HANDLE];
_dialogCloseup._txtHeader.load(_dialogCloseup._ptr);
if (_dialogCloseup._txtHeader._diaNr == diaNr) {
ret = true;
_dialogCloseup._ptr += DialogCloseupTxtHeader::SIZE();
_dialogCloseup._person.load(_dialogCloseup._ptr, _dialogCloseup._txtHeader._perNr);
_dialogCloseup._ptr += _dialogCloseup._txtHeader._perNr * AadInfo::SIZE();
_dialogCloseup._dialog = diaNr;
_dialogCloseup._strNr = 0;
_dialogCloseupStack[0] = 0;
_dialogCloseupStackPtr = 1;
}
}
return ret;
}
void Atdsys::stopDialogCloseup() {
_dialogCloseup._dialog = -1;
_dialogCloseup._autoDia = false;
}
int16 Atdsys::getDialogCloseupStatus() {
return _dialogCloseup._dialog;
}
char **Atdsys::dialogCloseupItemPtr(uint16 dialogNum, int16 blockNr, int16 *retNr) {
*retNr = 0;
memset(_ePtr, 0, sizeof(char *) * DIALOG_CLOSEUP_MAX);
if (_dialogCloseup._dialog != -1) {
_dialogCloseup._blockPtr = _dialogCloseup._ptr;
dialogCloseupSearchBlock(blockNr, &_dialogCloseup._blockPtr);
if (_dialogCloseup._blockPtr) {
for (int16 i = 0; i < DIALOG_CLOSEUP_MAX; i++) {
char *itemPtr = _dialogCloseup._blockPtr;
dialogCloseupSearchItem(i, &itemPtr);
if (itemPtr) {
char nr = itemPtr[-1];
itemPtr += sizeof(AadStrHeader);
if (_dialogResource->isItemShown(dialogNum, blockNr, (int16)nr)) {
_ePtr[*retNr] = itemPtr;
_eNr[*retNr] = (int16)nr;
++(*retNr);
}
}
}
}
}
return _ePtr;
}
DialogCloseupNextBlock *Atdsys::dialogCloseupItemChoice(uint16 dialogNum, int16 blockNr, int16 itemNr) {
_dialogCloseupNextBlock._blkNr = blockNr;
if (!_aadv._dialog) {
if (!_dialogCloseup._autoDia) {
dialogCloseupSearchItem(_eNr[itemNr], &_dialogCloseup._blockPtr);
if (_dialogCloseup._blockPtr) {
if (startAutoDialogCloseup(_dialogCloseup._blockPtr))
_dialogCloseup._autoDia = true;
if (_dialogResource->hasExitBit(dialogNum, blockNr, _eNr[itemNr])) {
stopDialogCloseup();
_dialogCloseupNextBlock._endNr = _eNr[itemNr];
_dialogCloseupNextBlock._blkNr = -1;
}
}
}
}
return &_dialogCloseupNextBlock;
}
DialogCloseupNextBlock *Atdsys::calcNextDialogCloseupBlock(uint16 dialogNum, int16 blockNr, int16 itemNr) {
if (!_dialogResource->hasShowBit(dialogNum, blockNr, _eNr[itemNr]))
_dialogResource->setItemShown(dialogNum, blockNr, _eNr[itemNr], false);
_dialogCloseupNextBlock._endNr = _eNr[itemNr];
if (_dialogResource->hasRestartBit(dialogNum, blockNr, _eNr[itemNr])) {
_dialogCloseupNextBlock._blkNr = 0;
_dialogCloseupStackPtr = 0;
} else {
const uint8 nextBlock = _dialogResource->getNextBlock(dialogNum, blockNr, _eNr[itemNr]);
if (nextBlock) {
_dialogCloseupNextBlock._blkNr = nextBlock;
int16 option = 0;
while (!option && _dialogCloseupNextBlock._blkNr != -1) {
option = 0;
dialogCloseupItemPtr(dialogNum, _dialogCloseupNextBlock._blkNr, &option);
if (!option) {
_dialogCloseupNextBlock._blkNr = getDialogCloseupBlock(dialogNum);
}
}
} else {
_dialogCloseupNextBlock._blkNr = getDialogCloseupBlock(dialogNum);
}
}
_dialogCloseupStack[_dialogCloseupStackPtr] = _dialogCloseupNextBlock._blkNr;
++_dialogCloseupStackPtr;
return &_dialogCloseupNextBlock;
}
int16 Atdsys::getDialogCloseupBlock(uint16 dialogNum) {
_dialogCloseupStackPtr -= 1;
int16 ret = -1;
bool end = false;
while (_dialogCloseupStackPtr >= 0 && !end) {
short blk_nr = _dialogCloseupStack[_dialogCloseupStackPtr];
int16 option;
dialogCloseupItemPtr(dialogNum, blk_nr, &option);
if (option) {
ret = blk_nr;
end = true;
} else {
--_dialogCloseupStackPtr;
}
}
++_dialogCloseupStackPtr;
return ret;
}
void Atdsys::dialogCloseupSearchBlock(int16 blockNr, char **ptr) {
char *start_ptr = *ptr;
bool end = false;
while (!end) {
if (*start_ptr == (char)blockNr) {
end = true;
*ptr = start_ptr;
} else {
start_ptr += 2 + sizeof(AadStrHeader);
while (*start_ptr++ != ATDS_END_BLOCK) {}
if (start_ptr[0] == ATDS_END &&
start_ptr[1] == ATDS_END) {
end = true;
*ptr = nullptr;
}
}
}
}
void Atdsys::dialogCloseupSearchItem(int16 itemNr, char **blkAdr) {
char *start_ptr = *blkAdr + 1;
bool end = false;
while (!end) {
if (*start_ptr == itemNr) {
end = true;
*blkAdr = start_ptr + 1;
} else {
start_ptr += 1 + sizeof(AadStrHeader);
while (*start_ptr++ != ATDS_END_ENTRY) {}
if (*start_ptr == ATDS_END_BLOCK) {
end = true;
*blkAdr = nullptr;
}
}
}
}
int16 Atdsys::startAutoDialogCloseup(char *itemAdr) {
_aadv._dialog = false;
if (itemAdr) {
_aadv._person = _dialogCloseup._person;
_aadv._ptr = itemAdr;
_aadv._dialog = true;
_aadv._strNr = 0;
_aadv._strHeader = (AadStrHeader *)_aadv._ptr;
_aadv._ptr += sizeof(AadStrHeader);
int16 txtLen = aadGetTxtLen(_aadv._ptr);
_aadv._delayCount = get_delay(txtLen);
_atdsv._diaNr = _dialogCloseup._txtHeader._diaNr + 10000;
if (_atdsv.aad_str != nullptr)
_atdsv.aad_str(_atdsv._diaNr, 0, _aadv._strHeader->_akPerson, AAD_STR_START);
_mousePush = true;
stop_ats();
} else {
_aadv._dialog = false;
}
return _aadv._dialog;
}
void Atdsys::hideDialogCloseupItem(int16 diaNr, int16 blockNr, int16 itemNr) {
_dialogResource->setItemShown(diaNr, blockNr, itemNr, false);
}
void Atdsys::showDialogCloseupItem(int16 diaNr, int16 blockNr, int16 itemNr) {
_dialogResource->setItemShown(diaNr, blockNr, itemNr, true);
}
int16 Atdsys::calc_inv_no_use(int16 curInv, int16 testNr) {
if (curInv != -1)
_invBlockNr = curInv + 1;
assert(curInv <= 255);
const uint32 key = (curInv & 0xff) << 16 | testNr;
return (_itemUseWithDesc.contains(key)) ? _itemUseWithDesc[key] : -1;
}
int8 Atdsys::getStereoPos(int16 x) {
return floor(x / 2.5);
}
void Atdsys::saveAtdsStream(Common::WriteStream *stream) {
_dialogResource->saveStream(stream);
}
void Atdsys::loadAtdsStream(Common::SeekableReadStream* stream) {
_dialogResource->loadStream(stream);
}
uint32 Atdsys::getAtdsStreamSize() const {
return _dialogResource->getStreamSize();
}
Common::StringArray Atdsys::getTextArray(uint dialogNum, uint entryNum, int type, int subEntry) {
if (dialogNum == 45 && entryNum == 295 && type == 1 && subEntry == -1 &&
g_engine->getLanguage() == Common::EN_ANY) {
// WORKAROUND: Taxi hotspot in room 45 (Big City)
Common::StringArray results;
results.push_back("Taxi");
return results;
} else if (!getControlBit(entryNum, ATS_ACTIVE_BIT))
return _text->getTextArray(dialogNum, entryNum, type, subEntry);
else
return Common::StringArray();
}
Common::String Atdsys::getTextEntry(uint dialogNum, uint entryNum, int type, int subEntry) {
if (!getControlBit(entryNum, ATS_ACTIVE_BIT))
return _text->getTextEntry(dialogNum, entryNum, type, subEntry);
else
return Common::String();
}
int16 Atdsys::getLastSpeechId() {
return _text->getLastSpeechId();
}
} // namespace Chewy

310
engines/chewy/atds.h Normal file
View File

@@ -0,0 +1,310 @@
/* 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/>.
*
*/
#ifndef CHEWY_ATDS_H
#define CHEWY_ATDS_H
#include "common/str.h"
#include "common/str-array.h"
#include "chewy/resource.h"
#include "chewy/text.h"
namespace Chewy {
#define ATDS_VOC_OFFSET 20
#define AAD_MAX_PERSON 10
#define AAD_STR_START 0
#define AAD_STR_END 1
#define AAD_DATA 0
#define ATS_DATA 1
#define DIALOG_CLOSEUP_DATA 2 // ADS_DATA
#define INV_USE_DATA 4
#define INV_ATS_DATA 6
#define MAX_HANDLE 8
#define AAD_HANDLE 0
#define ADS_HANDLE 2
#define MAX_STR_SPLIT 10
#define SPLIT_CENTER 1
#define SPLIT_LEFT 2
#define ATDS_END_LINE 0
#define ATDS_END_BLOCK 0x0b
#define ATDS_END_ENTRY 0x0c
#define ATDS_END_TEXT 0x0d
#define ATDS_END 0x0e
#define BLOCKENDE 0x0f
#define MAX_ATS_ROOM 100
#define ATS_ACTIVE_BIT 1
#define ATS_COUNT_BIT 2
#define ATS_RESET_BIT 4
#define ATS_ACTION_BIT 8
#define MAX_ATS_STATUS 3
#define TXT_MARK_NAME 0
#define TXT_MARK_LOOK 1
#define TXT_MARK_USE 2
#define TXT_MARK_WALK 3
#define TXT_MARK_TALK 4
#define CONTROL_BYTE 0xff
#define DIALOG_CLOSEUP_MAX 6
#define DIALOG_CLOSEUP_STACK_SIZE 50
#define ADS_EXIT_BIT 1
#define ADS_SHOW_BIT 2
#define ADS_RESTART_BIT 4
struct KbdMouseInfo;
class Text;
struct AtdsVar {
int16 _silent = 0;
int16 _delay = 1;
int16 _diaNr = 0;
bool _eventsEnabled = false;
int16 _vocNr = 0;
void (*aad_str)(int16 diaNr, int16 strNr, int16 personNr, int16 mode) = nullptr;
};
#define IUID_IIB 0
#define IUID_SIB 1
#define IUID_REC 2
#define IUID_AUTO 3
#define IUID_DET 4
#define IUID_PLAYER 5
#define INV_USE_DEF 16
struct AadInfo {
int16 _x;
int16 _y;
int16 _color;
AadInfo() : _x(0), _y(0), _color(0) {}
void load(Common::SeekableReadStream *src);
static constexpr int SIZE() { return 6; }
};
class AadInfoArray : public Common::Array<AadInfo> {
public:
void load(const void *data, size_t count);
};
struct AadStrHeader {
int16 _akPerson;
int16 _vocNr;
};
// ADS (dialog closeup) header
struct DialogCloseupTxtHeader {
int16 _diaNr;
int16 _perNr;
int16 _aMov;
int16 _curNr;
bool load(const void *src);
static constexpr int SIZE() { return 8; }
};
struct DialogCloseupVariables {
int16 _dialog;
int16 _autoDia;
DialogCloseupTxtHeader _txtHeader;
AadInfoArray _person;
char *_ptr;
char *_blockPtr;
int16 _strNr;
int16 _delayCount;
int16 _silentCount;
};
struct DialogCloseupNextBlock {
int16 _blkNr;
int16 _endNr;
};
struct AadVar {
int16 _dialog;
DialogCloseupTxtHeader *_txtHeader;
AadStrHeader *_strHeader;
AadInfoArray _person;
char *_ptr;
int16 _strNr;
int16 _delayCount;
int16 _silentCount;
};
struct AtsTxtHeader {
uint16 _txtNr = 0;
int16 _aMov = 0;
int16 _curNr = 0;
bool load(Common::SeekableReadStream *src);
static constexpr int SIZE() { return 8; }
};
struct AtsVar {
AtsTxtHeader _txtHeader;
uint16 vocNum;
Common::String text;
int16 _delayCount;
int16 _silentCount;
int16 _color;
int16 _txtMode;
bool shown;
};
struct SplitStringRet {
char **_strPtr;
int16 *_x;
int16 _y;
short _nr;
int16 _next;
SplitStringRet() {
_strPtr = nullptr;
_x = nullptr;
_y = 0;
_nr = 0;
_next = 0;
}
};
struct SplitStringInit {
char *_str;
int16 _x;
int16 _y;
};
class Atdsys {
public:
Atdsys();
~Atdsys();
void set_delay(int16 *delay, int16 silent);
void set_split_win(int16 nr, int16 x, int16 y);
void split_string(SplitStringInit *ssi, SplitStringRet *ret);
void calc_txt_win(SplitStringInit *ssi);
void str_null2leer(char *strStart, char *strEnd);
void load_atds(int16 chunkNr, int16 mode);
void set_handle(int16 mode, int16 chunkStart, int16 chunkNr);
bool start_ats(int16 txtNr, int16 txtMode, int16 color, int16 mode, int16 *vocNr);
void stop_ats();
bool atsShown() { return _atsv.shown; }
void print_ats(int16 x, int16 y, int16 scrX, int16 scrY);
int16 getControlBit(int16 txtNr, int16 bitIdx);
void setControlBit(int16 txtNr, int16 bitIdx);
void delControlBit(int16 txtNr, int16 bitIdx);
void set_ats_str(int16 txtNr, int16 txtMode, int16 strNr, int16 mode);
void set_all_ats_str(int16 txtNr, int16 strNr, int16 mode);
int16 start_aad(int16 diaNr, bool continueWhenSpeechEnds = false);
void stopAad();
void print_aad(int16 scrX, int16 scrY);
int16 aadGetStatus();
void set_string_end_func(void (*strFunc)(int16 diaNr, int16 strNr, int16 personNr, int16 mode));
void aad_search_dia(int16 diaNr, char **ptr);
int16 aadGetTxtLen(char *str);
bool startDialogCloseup(int16 diaNr);
void stopDialogCloseup();
char **dialogCloseupItemPtr(uint16 dialogNum, int16 blockNr, int16 *retNr);
DialogCloseupNextBlock *dialogCloseupItemChoice(uint16 dialogNum, int16 blockNr, int16 itemNr);
DialogCloseupNextBlock *calcNextDialogCloseupBlock(uint16 dialogNum, int16 blockNr, int16 itemNr);
int16 getDialogCloseupStatus();
void hideDialogCloseupItem(int16 diaNr, int16 blockNr, int16 itemNr);
void showDialogCloseupItem(int16 diaNr, int16 blockNr, int16 itemNr);
int16 getDialogCloseupBlock(uint16 dialogNum);
void dialogCloseupSearchBlock(int16 blockNr, char **ptr);
void dialogCloseupSearchItem(int16 itemNr, char **blkAdr);
int16 startAutoDialogCloseup(char *itemAdr);
int16 calc_inv_no_use(int16 curInv, int16 testNr);
int8 getStereoPos(int16 x);
void enableEvents(bool nr) {
_atdsv._eventsEnabled = nr;
}
void saveAtdsStream(Common::WriteStream *stream);
void loadAtdsStream(Common::SeekableReadStream *stream);
uint32 getAtdsStreamSize() const;
Common::StringArray getTextArray(uint dialogNum, uint entryNum, int type, int subEntry = -1);
Common::String getTextEntry(uint dialogNum, uint entryNum, int type, int subEntry = -1);
int16 getLastSpeechId();
private:
void init();
int16 get_delay(int16 txt_len);
void initItemUseWith();
char *_atdsMem[MAX_HANDLE] = { nullptr };
int16 _atdsPoolOff[MAX_HANDLE] = { 0 };
AadVar _aadv;
AtsVar _atsv;
DialogCloseupVariables _dialogCloseup;
AtdsVar _atdsv;
char *_ePtr[DIALOG_CLOSEUP_MAX] = { nullptr };
int16 _eNr[DIALOG_CLOSEUP_MAX] = { 0 };
DialogCloseupNextBlock _dialogCloseupNextBlock;
uint8 _dialogCloseupStack[DIALOG_CLOSEUP_STACK_SIZE] = { 0 };
int16 _dialogCloseupStackPtr;
bool _continueWhenSpeechEnds = false;
SplitStringInit _ssi[AAD_MAX_PERSON] = {
{ nullptr, 100, 0 },
{ nullptr, 100, 0 },
{ nullptr, 100, 0 },
{ nullptr, 100, 0 },
{ nullptr, 100, 0 },
{ nullptr, 100, 0 },
{ nullptr, 100, 0 },
{ nullptr, 100, 0 },
{ nullptr, 100, 0 },
{ nullptr, 100, 0 },
};
char *_splitPtr[MAX_STR_SPLIT] = { nullptr };
int16 _splitX[MAX_STR_SPLIT] = { 0 };
int16 _invBlockNr;
int16 _mousePush = 0;
int _printDelayCount1 = 0;
DialogResource *_dialogResource;
Text *_text;
Common::HashMap<uint32, uint16> _itemUseWithDesc;
};
} // namespace Chewy
#endif

View File

@@ -0,0 +1,63 @@
/* 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/>.
*
*/
#include "chewy/audio/chewy_voc.h"
#include "common/stream.h"
namespace Chewy {
ChewyVocStream::ChewyVocStream(Common::SeekableReadStream* stream, DisposeAfterUse::Flag disposeAfterUse) :
VocStream(stream, true, disposeAfterUse) {
removeHeaders();
}
void ChewyVocStream::removeHeaders() {
// Check the sample blocks for non-standard headers.
for (auto &block : _blocks) {
if (block.code == 1 && block.sampleBlock.samples > 80) {
// Found a sample block. Check for the headers.
int headerSize = 0;
if (_stream->readUint32BE() == FOURCC_RIFF) {
// Found a RIFF header.
headerSize = 44;
} else {
_stream->seek(block.sampleBlock.offset + 76);
if (_stream->readUint32BE() == FOURCC_SCRS) {
// Found an SCRS (?) header.
headerSize = 80;
}
}
if (headerSize > 0) {
// Move the offset past the header and adjust the length.
block.sampleBlock.offset += headerSize;
block.sampleBlock.samples -= headerSize;
_length = _length.addFrames(-headerSize);
}
}
}
// Reset the stream.
rewind();
}
} // End of namespace Chewy

View File

@@ -0,0 +1,49 @@
/* 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/>.
*
*/
#ifndef CHEWY_AUDIO_CHEWY_VOC_H
#define CHEWY_AUDIO_CHEWY_VOC_H
#include "audio/decoders/voc.h"
#include "common/endian.h"
namespace Chewy {
// This stream differs from the standard VOC stream on 2 points:
// - VOC data header is not present, so not processed.
// - Some VOC blocks contain non-standard headers. These are removed because
// otherwise they will be interpreted as audio data and cause static.
class ChewyVocStream : public Audio::VocStream {
protected:
static const uint32 FOURCC_SCRS = MKTAG('S', 'C', 'R', 'S');
static const uint32 FOURCC_RIFF = MKTAG('R', 'I', 'F', 'F');
public:
ChewyVocStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse);
protected:
void removeHeaders();
};
} // End of namespace Audio
#endif

View File

@@ -0,0 +1,144 @@
/* 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/>.
*
*/
#include "chewy/audio/module_tmf.h"
#include "common/array.h"
#include "common/stream.h"
const uint8 Chewy::Module_TMF::TMF_MOD_SONG_NAME[] = {
'S', 'C', 'U', 'M', 'M',
'V', 'M', ' ', 'M', 'O',
'D', 'U', 'L', 'E', '\0',
'\0', '\0', '\0', '\0', '\0', '\0'
};
const uint8 Chewy::Module_TMF::TMF_MOD_INSTRUMENT_NAME[] = {
'S', 'C', 'U', 'M', 'M',
'V', 'M', ' ', 'I', 'N',
'S', 'T', 'R', 'U', 'M',
'E', 'N', 'T', ' ', '\0',
'\0', '\0', '\0'
};
const uint16 Chewy::Module_TMF::TMF_MOD_PERIODS[] = {
856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453,
428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226,
214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113
};
bool Chewy::Module_TMF::load(Common::SeekableReadStream& stream, int offs) {
stream.seek(offs);
// Check TMF fourCC.
if (stream.readUint32BE() != MKTAG('T', 'M', 'F', '\0'))
error("Corrupt TMF resource");
// Write song name (not present in TMF data).
Common::copy(TMF_MOD_SONG_NAME, TMF_MOD_SONG_NAME + 21, songname);
// Copy instrument data.
uint8 fineTune, instVolume;
uint32 repeatPoint, repeatLength, sampleLength;
//uint32 totalSampleLength = 0;
for (int i = 0; i < NUM_SAMPLES; ++i) {
fineTune = stream.readByte();
instVolume = stream.readByte();
// Repeat point, repeat length and sample length are 32 bit LE in bytes
// instead of 16 bit BE in words.
repeatPoint = stream.readUint32LE();
assert(repeatPoint <= 0x1FFFF && repeatPoint % 2 == 0);
repeatLength = stream.readUint32LE();
assert(repeatLength <= 0x1FFFF && repeatLength % 2 == 0);
// Sample length is at the end instead of at the start.
sampleLength = stream.readUint32LE();
assert(sampleLength <= 0x1FFFF && sampleLength % 2 == 0);
//totalSampleLength += sampleLength;
// Instrument name is not present in TMF data.
Common::copy(TMF_MOD_INSTRUMENT_NAME, TMF_MOD_INSTRUMENT_NAME + 23, sample[i].name);
sample[i].name[19] = '0' + i / 10;
sample[i].name[20] = '0' + i % 10;
sample[i].len = sampleLength;
// Finetune is a signed nibble in MOD, but TMF uses a signed byte
// (within nibble range).
sample[i].finetune = fineTune & 0x0F;
sample[i].vol = instVolume;
sample[i].repeat = repeatPoint;
sample[i].replen = repeatLength;
}
// Copy pattern table.
songlen = stream.readByte();
// Second byte is the number of different patterns in TMF. This byte is
// unused in MOD (usually set to 0x7F).
uint8 numPatterns = stream.readByte();
undef = 0x7F;
stream.read(songpos, 128);
// M.K. fourCC is not present in TMF.
sig = signatures[0];
// TMF has a 32 bit LE number for each instrument here; these are probably
// offsets for each sample. They are not present in MOD and not needed, so
// they are skipped.
stream.skip(4 * 31);
// Copy pattern data.
pattern = new Modules::pattern_t[numPatterns];
for (int i = 0; i < numPatterns; ++i) {
for (int j = 0; j < 64; ++j) {
for (int k = 0; k < 4; ++k) {
// TMF channel data has this format:
// 1 byte note (0-0x23 or 0x30 for "use previous value")
// 1 byte sample
// 2 bytes effect (byte 3 high nibble is unused)
byte note = stream.readByte();
assert(note == 0x30 || note < 36);
byte sampleNum = stream.readByte();
uint16 effect = stream.readUint16BE();
assert((effect & 0xF000) == 0);
// Note is converted to a MOD 12 bit period using a lookup array.
uint16 period = note == 0x30 ? 0 : TMF_MOD_PERIODS[note];
pattern[i][j][k].sample = sampleNum;
pattern[i][j][k].period = period;
pattern[i][j][k].effect = effect;
pattern[i][j][k].note = periodToNote(period);
}
}
}
// Copy sample data.
for (int i = 0; i < NUM_SAMPLES; ++i) {
if (!sample[i].len) {
sample[i].data = nullptr;
} else {
sample[i].data = new int8[sample[i].len];
for (int j = 0; j < sample[i].len; j++) {
int tmfSample = stream.readByte();
// Convert from unsigned to signed.
tmfSample -= 0x80;
sample[i].data[j] = tmfSample & 0xFF;
}
}
}
return true;
}

View File

@@ -0,0 +1,42 @@
/* 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/>.
*
*/
#ifndef CHEWY_MUSIC_MODULE_TMF_H
#define CHEWY_MUSIC_MODULE_TMF_H
#include "audio/mods/module.h"
namespace Chewy {
// Module variant for the MOD-like TMF format used by Chewy.
class Module_TMF : public Modules::Module {
protected:
static const uint8 TMF_MOD_SONG_NAME[21];
static const uint8 TMF_MOD_INSTRUMENT_NAME[23];
static const uint16 TMF_MOD_PERIODS[36];
public:
bool load(Common::SeekableReadStream &stream, int offs) override;
};
} // End of namespace Chewy
#endif

View File

@@ -0,0 +1,38 @@
/* 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/>.
*
*/
#include "chewy/audio/tmf_stream.h"
#include "chewy/audio/module_tmf.h"
Chewy::TMFStream::TMFStream(Common::SeekableReadStream *stream, int offs) : ProtrackerStream(44100, true) {
_module = new Module_TMF();
bool result = _module->load(*stream, offs);
assert(result);
// Channel panning used by TMF is L-R-L-R instead of MOD's L-R-R-L.
setChannelPanning(0, PANNING_LEFT);
setChannelPanning(1, PANNING_RIGHT);
setChannelPanning(2, PANNING_LEFT);
setChannelPanning(3, PANNING_RIGHT);
startPaula();
}

View File

@@ -0,0 +1,37 @@
/* 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/>.
*
*/
#ifndef CHEWY_MUSIC_TMF_STREAM_H
#define CHEWY_MUSIC_TMF_STREAM_H
#include "audio/mods/protracker.h"
namespace Chewy {
// AudioStream for the MOD-like TMF music format used by Chewy.
class TMFStream : public Modules::ProtrackerStream {
public:
TMFStream(Common::SeekableReadStream *stream, int offs);
};
} // End of namespace Chewy
#endif

163
engines/chewy/barriers.cpp Normal file
View File

@@ -0,0 +1,163 @@
/* 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/>.
*
*/
#include "common/file.h"
#include "chewy/chewy.h"
#include "chewy/globals.h"
#include "chewy/barriers.h"
namespace Chewy {
int16 Barriers::getBarrierId(int16 x, int16 y) {
const int16 width = _G(room)->_barriers->getWidth();
const byte *data = _G(room)->_barriers->getData();
const int16 result = getBarrierId(((y / 8) * width) + (x / 8), data + 6);
delete[] data;
return result;
}
int16 Barriers::getBarrierId(int16 g_idx, const byte *buffer) {
int16 idx_nr = buffer[g_idx];
switch (idx_nr) {
case 40:
switch (_G(gameState)._personRoomNr[P_CHEWY]) {
case 8:
if (_G(gameState).R8GTuer)
return 0;
break;
case 9:
if (!_G(gameState).R9Grid)
return 0;
break;
case 16:
if (!_G(gameState).R16F5Exit)
return 0;
break;
case 17:
if (_G(gameState).R17Location != 1)
return 0;
break;
case 21:
if (!_G(gameState).R21Laser2Weg)
return 0;
break;
case 31:
if (!_G(gameState).R31KlappeZu)
return 0;
break;
case 41:
if (!_G(gameState).R41LolaOk)
return 0;
break;
case 52:
if (!_G(gameState).R52LichtAn)
return 2;
else
return 4;
break;
case 71:
return _G(gameState).R71LeopardVined ? 1 : 0;
case 76:
return _G(gameState).flags29_4 ? 4 : 0;
case 84:
if (!_G(gameState).R88UsedMonkey)
_G(gameState).R84GoonsPresent = true;
break;
case 86:
if (!_G(gameState).flags32_2)
return 0;
break;
case 94:
if (!_G(gameState).flags35_10)
return 0;
break;
case 97:
if (_G(gameState).flags35_80)
return 0;
break;
default:
break;
}
break;
case 41:
switch (_G(gameState)._personRoomNr[P_CHEWY]) {
case 17:
if (_G(gameState).R17Location != 2)
return 0;
break;
case 21:
if (!_G(gameState).R21Laser1Weg)
return 0;
else
return 3;
case 37:
if (!_G(gameState).R37RoosterFoughtWithDog)
return 0;
break;
case 52:
if (!_G(gameState).R52TuerAuf)
return 2;
else
return 4;
break;
case 97:
if (_G(gameState).flags36_20)
return 0;
break;
default:
break;
}
break;
case 42:
if (_G(gameState)._personRoomNr[P_CHEWY] == 97 && !_G(gameState).flags37_1)
return 0;
break;
default:
break;
}
return idx_nr;
}
} // namespace Chewy

37
engines/chewy/barriers.h Normal file
View File

@@ -0,0 +1,37 @@
/* 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/>.
*
*/
#ifndef CHEWY_BARRIERS_H
#define CHEWY_BARRIERS_H
namespace Chewy {
class Barriers {
public:
Barriers() {}
int16 getBarrierId(int16 x, int16 y);
int16 getBarrierId(int16 g_idx, const byte *buffer);
};
} // namespace Chewy
#endif

188
engines/chewy/chewy.cpp Normal file
View File

@@ -0,0 +1,188 @@
/* 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/>.
*
*/
#include "common/config-manager.h"
#include "common/fs.h"
#include "common/system.h"
#include "engines/metaengine.h"
#include "engines/util.h"
#include "chewy/chewy.h"
#include "chewy/cursor.h"
#include "chewy/console.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/main.h"
#include "chewy/resource.h"
#include "chewy/sound.h"
#include "chewy/video/video_player.h"
namespace Chewy {
ChewyEngine *g_engine;
Graphics::Screen *g_screen;
ChewyEngine::ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc)
: Engine(syst),
_gameDescription(gameDesc),
_rnd("chewy") {
g_engine = this;
g_screen = nullptr;
const Common::FSNode gameDataDir(ConfMan.getPath("path"));
SearchMan.addSubDirectoryMatching(gameDataDir, "back");
SearchMan.addSubDirectoryMatching(gameDataDir, "cut");
SearchMan.addSubDirectoryMatching(gameDataDir, "err");
SearchMan.addSubDirectoryMatching(gameDataDir, "misc");
SearchMan.addSubDirectoryMatching(gameDataDir, "room");
SearchMan.addSubDirectoryMatching(gameDataDir, "sound");
SearchMan.addSubDirectoryMatching(gameDataDir, "txt");
}
ChewyEngine::~ChewyEngine() {
delete _events;
delete _globals;
delete _screen;
delete _sound;
delete _video;
g_engine = nullptr;
g_screen = nullptr;
}
void ChewyEngine::initialize() {
g_screen = _screen = new Graphics::Screen();
_globals = new Globals();
_events = new EventsManager(_screen);
_sound = new Sound(_mixer);
_video = new VideoPlayer();
setDebugger(new Console());
syncSoundSettings();
}
Common::Error ChewyEngine::run() {
// Initialize backend
//initGraphics(640, 480);
initGraphics(320, 200);
initialize();
game_main();
return Common::kNoError;
}
#define SCUMMVM_TAG MKTAG('S', 'C', 'V', 'M')
void ChewyEngine::syncSoundSettings() {
_sound->syncSoundSettings();
Engine::syncSoundSettings();
}
Common::Error ChewyEngine::loadGameStream(Common::SeekableReadStream *stream) {
exit_room(-1);
Common::Serializer s(stream, nullptr);
if (!_G(gameState).synchronize(s)) {
error("loadGameStream error");
return Common::kReadingFailed;
} else {
if (stream->readUint32BE() != SCUMMVM_TAG ||
stream->readUint32LE() != _G(atds)->getAtdsStreamSize())
return Common::kReadingFailed;
_G(atds)->loadAtdsStream(stream);
_G(flags).LoadGame = true;
if (_G(cur)->usingInventoryCursor()) {
_G(menu_item) = CUR_USE;
}
if (_G(cur)->usingInventoryCursor())
_G(gameState).room_m_obj[_G(cur)->getInventoryCursor()].RoomNr = -1;
_G(room)->loadRoom(&_G(room_blk), _G(gameState)._personRoomNr[P_CHEWY], &_G(gameState));
load_chewy_taf(_G(gameState).ChewyAni);
_G(fx_blend) = BLEND1;
_G(room)->calc_invent(&_G(room_blk), &_G(gameState));
if (_G(cur)->usingInventoryCursor())
_G(gameState).room_m_obj[_G(cur)->getInventoryCursor()].RoomNr = 255;
_G(obj)->sort();
for (int i = 0; i < MAX_PERSON; i++) {
setPersonPos(_G(gameState).X[i], _G(gameState).Y[i], i, _G(gameState).Phase[i]);
}
// WORKAROUND: The original doesn't allow saving in room 47
// (combination lock close-up). This workaround fixes loading
if (_G(gameState)._personRoomNr[P_CHEWY] == 47) {
_G(gameState)._personHide[P_CHEWY] = false;
_G(gameState)._personHide[P_HOWARD] = false;
}
_G(auto_obj) = 0;
enter_room(-1);
_G(flags).LoadGame = false;
return Common::kNoError;
}
}
Common::Error ChewyEngine::saveGameStream(Common::WriteStream *stream, bool isAutosave) {
Common::Serializer s(nullptr, stream);
for (int i = 0; i < MAX_PERSON; i++) {
_G(gameState).X[i] = _G(moveState)[i].Xypos[0];
_G(gameState).Y[i] = _G(moveState)[i].Xypos[1];
_G(gameState).Phase[i] = _G(person_end_phase)[i];
}
if (!_G(gameState).synchronize(s))
return Common::kWritingFailed;
stream->writeUint32BE(SCUMMVM_TAG);
stream->writeUint32LE(_G(atds)->getAtdsStreamSize());
_G(atds)->saveAtdsStream(stream);
return Common::kNoError;
}
SaveStateList ChewyEngine::listSaves() {
return getMetaEngine()->listSaves(_targetName.c_str());
}
void ChewyEngine::showGmm(bool isInGame) {
_canLoad = true;
_canSave = isInGame;
openMainMenuDialog();
_events->clearEvents();
_canLoad = false;
_canSave = false;
}
} // End of namespace Chewy

126
engines/chewy/chewy.h Normal file
View File

@@ -0,0 +1,126 @@
/* 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/>.
*
*/
#ifndef CHEWY_CHEWY_H
#define CHEWY_CHEWY_H
// FIXME
#define AIL
#define ENGLISCH
#include "common/scummsys.h"
#include "common/error.h"
#include "common/memstream.h"
#include "common/random.h"
#include "engines/engine.h"
#include "engines/savestate.h"
#include "graphics/screen.h"
namespace Chewy {
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 200
#define SHOULD_QUIT g_engine->shouldQuit()
#define SHOULD_QUIT_RETURN if (g_engine->shouldQuit()) return
#define SHOULD_QUIT_RETURN0 if (g_engine->shouldQuit()) return 0
struct ChewyGameDescription;
class EventsManager;
class Globals;
class Sound;
class VideoPlayer;
class ChewyEngine : public Engine {
private:
bool _canLoad = false;
bool _canSave = false;
protected:
// Engine APIs
Common::Error run() override;
/**
* Returns engine features
*/
bool hasFeature(EngineFeature f) const override;
void initialize();
void shutdown() {}
public:
const ChewyGameDescription *_gameDescription;
Common::RandomSource _rnd;
EventsManager *_events = nullptr;
Globals *_globals = nullptr;
Sound *_sound = nullptr;
VideoPlayer *_video = nullptr;
Graphics::Screen *_screen = nullptr;
bool _showWalkAreas = false;
public:
ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc);
~ChewyEngine() override;
uint32 getFeatures() const;
Common::Language getLanguage() const;
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
return _canLoad;
}
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
return _canSave;
}
void setCanLoadSave(bool canLoadSave) {
_canLoad = canLoadSave;
_canSave = canLoadSave;
}
void syncSoundSettings() override;
/**
* Load savegame data
*/
Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
/**
* Save savegame data
*/
Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave) override;
SaveStateList listSaves();
/**
* Show the GMM
*/
void showGmm(bool isInGame);
uint getRandomNumber(uint max) {
return _rnd.getRandomNumber(max);
}
};
extern ChewyEngine *g_engine;
extern Graphics::Screen *g_screen;
} // End of namespace Chewy
#endif

View File

@@ -0,0 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
add_engine chewy "Chewy: Esc from F5" yes

172
engines/chewy/console.cpp Normal file
View File

@@ -0,0 +1,172 @@
/* 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/>.
*
*/
#include "common/file.h"
#include "chewy/console.h"
#include "chewy/globals.h"
#include "chewy/chewy.h"
#include "chewy/sound.h"
#include "chewy/video/video_player.h"
namespace Chewy {
static int strToInt(const char *s) {
if (!*s)
// No string at all
return 0;
else if (toupper(s[strlen(s) - 1]) != 'H')
// Standard decimal string
return atoi(s);
// Hexadecimal string
uint tmp = 0;
int read = sscanf(s, "%xh", &tmp);
if (read < 1)
error("strToInt failed on string \"%s\"", s);
return (int)tmp;
}
Console::Console() : GUI::Debugger() {
registerCmd("room", WRAP_METHOD(Console, Cmd_Room));
registerCmd("item", WRAP_METHOD(Console, Cmd_Item));
registerCmd("cursor", WRAP_METHOD(Console, Cmd_Cursor));
registerCmd("play_sound", WRAP_METHOD(Console, Cmd_PlaySound));
registerCmd("play_speech", WRAP_METHOD(Console, Cmd_PlaySpeech));
registerCmd("play_music", WRAP_METHOD(Console, Cmd_PlayMusic));
registerCmd("play_video", WRAP_METHOD(Console, Cmd_PlayVideo));
registerCmd("walk", WRAP_METHOD(Console, Cmd_WalkAreas));
registerCmd("text", WRAP_METHOD(Console, Cmd_Text));
}
Console::~Console() {
}
bool Console::Cmd_Room(int argc, const char **argv) {
if (argc == 1) {
debugPrintf("%s <roomNum>\n", argv[0]);
debugPrintf("Current room is %d\n", _G(gameState)._personRoomNr[P_CHEWY]);
return true;
} else {
int roomNum = strToInt(argv[1]);
exit_room(-1);
_G(gameState)._personRoomNr[P_CHEWY] = roomNum;
_G(room)->loadRoom(&_G(room_blk), roomNum, &_G(gameState));
_G(fx_blend) = BLEND1;
enter_room(-1);
return false;
}
}
bool Console::Cmd_Item(int argc, const char **argv) {
if (argc == 1) {
debugPrintf("%s <itemNum>\n", argv[0]);
} else {
int itemNum = strToInt(argv[1]);
invent_2_slot(itemNum);
debugPrintf("Done.\n");
}
return true;
}
bool Console::Cmd_Cursor(int argc, const char **argv) {
if (argc == 1) {
debugPrintf("%s <cursorNum>\n", argv[0]);
} else {
int cursorNum = strToInt(argv[1]);
cursorChoice(cursorNum);
}
return false;
}
bool Console::Cmd_PlaySound(int argc, const char **argv) {
if (argc < 2) {
debugPrintf("Usage: play_sound <number>\n");
return true;
}
int resNum = atoi(argv[1]);
g_engine->_sound->playSound(resNum);
return true;
}
bool Console::Cmd_PlaySpeech(int argc, const char **argv) {
if (argc < 2) {
debugPrintf("Usage: play_speech <number>\n");
return true;
}
int resNum = atoi(argv[1]);
g_engine->_sound->playSpeech(resNum, false);
return true;
}
bool Console::Cmd_PlayMusic(int argc, const char **argv) {
if (argc < 2) {
debugPrintf("Usage: play_music <number>\n");
return true;
}
int resNum = atoi(argv[1]);
g_engine->_sound->stopMusic();
g_engine->_sound->playMusic(resNum);
return true;
}
bool Console::Cmd_PlayVideo(int argc, const char **argv) {
if (argc < 2) {
debugPrintf("Usage: play_video <number>\n");
return true;
}
int resNum = atoi(argv[1]);
g_engine->_video->playVideo(resNum);
return false;
}
bool Console::Cmd_WalkAreas(int argc, const char **argv) {
g_engine->_showWalkAreas = (argc == 2) && !strcmp(argv[1], "on");
return false;
}
bool Console::Cmd_Text(int argc, const char **argv) {
if (argc < 4) {
debugPrintf("Usage: text <chunk> <entry> <type>\n");
return true;
}
int chunk = atoi(argv[1]);
int entry = atoi(argv[2]);
int type = atoi(argv[3]);
Common::StringArray text = _G(atds)->getTextArray(chunk, entry, type);
for (uint i = 0; i < text.size(); i++) {
debugPrintf("%d: %s\n", i, text[i].c_str());
}
return true;
}
} // namespace Chewy

48
engines/chewy/console.h Normal file
View File

@@ -0,0 +1,48 @@
/* 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/>.
*
*/
#ifndef CHEWY_CONSOLE_H
#define CHEWY_CONSOLE_H
#include "gui/debugger.h"
namespace Chewy {
class Console : public GUI::Debugger {
protected:
bool Cmd_Room(int argc, const char **argv);
bool Cmd_Item(int argc, const char **argv);
bool Cmd_Cursor(int argc, const char **argv);
bool Cmd_PlaySound(int argc, const char **argv);
bool Cmd_PlaySpeech(int argc, const char **argv);
bool Cmd_PlayMusic(int argc, const char **argv);
bool Cmd_PlayVideo(int argc, const char **argv);
bool Cmd_WalkAreas(int argc, const char **argv);
bool Cmd_Text(int argc, const char **argv);
public:
Console();
~Console() override;
};
} // End of namespace Chewy
#endif

6
engines/chewy/credits.pl Normal file
View File

@@ -0,0 +1,6 @@
begin_section("Chewy");
add_person("Paul Gilbert", "dreammaster", "");
add_person("Eugene Sandulenko", "sev", "");
add_person("Arnaud Boutonn&eacute;", "Strangerke", "");
add_person("Filippos Karapetis", "bluegr", "");
end_section();

140
engines/chewy/cursor.cpp Normal file
View File

@@ -0,0 +1,140 @@
/* 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/>.
*
*/
#include "graphics/cursorman.h"
#include "chewy/cursor.h"
#include "chewy/events.h"
#include "chewy/globals.h"
namespace Chewy {
Cursor::Cursor() {
const auto res = new SpriteResource(CURSOR_TAF);
const auto invRes = new SpriteResource(INVENTORY_TAF);
_cursorCount = res->getChunkCount();
_invCursorCount = invRes->getChunkCount();
_curSprites = new CursorSprite[_cursorCount + _invCursorCount];
for (uint32 i = 0; i < _cursorCount + _invCursorCount; i++) {
const TAFChunk *sprite = (i < _cursorCount) ? res->getSprite(i) : invRes->getSprite(i - _cursorCount);
_curSprites[i].width = sprite->width;
_curSprites[i].height = sprite->height;
_curSprites[i].data = new byte[sprite->width * sprite->height];
memcpy(_curSprites[i].data, sprite->data, sprite->width * sprite->height);
delete sprite;
}
delete invRes;
delete res;
_currentCursor.data = _customCursor.data = nullptr;
_currentCursor.width = _customCursor.width = 0;
_currentCursor.height = _customCursor.height = 0;
clearCustomCursor();
}
Cursor::~Cursor() {
for (uint32 i = 0; i < _cursorCount + _invCursorCount; i++) {
delete[] _curSprites[i].data;
_curSprites[i].data = nullptr;
}
delete[] _curSprites;
}
void Cursor::updateCursor() {
if (!CursorMan.isVisible())
return;
--_curAniCountdown;
if (_curAniCountdown <= 0) {
_curAniCountdown = _animDelay;
++_aniCount;
if (_aniCount > _animEnd)
_aniCount = _animStart;
}
if (_customCursor.data != nullptr) {
CursorMan.replaceCursor(_customCursor.data, _customCursor.width, _customCursor.height, 0, 0, 0);
_currentCursor.data = _customCursor.data;
_currentCursor.width = _customCursor.width;
_currentCursor.height = _customCursor.height;
} else {
const uint32 cursorOffset = _invCursor >= 0 ? _cursorCount : 0;
const CursorSprite s = _curSprites[_aniCount + cursorOffset];
CursorMan.replaceCursor(s.data, s.width, s.height, 0, 0, 0);
_currentCursor.data = s.data;
_currentCursor.width = s.width;
_currentCursor.height = s.height;
}
}
void Cursor::showCursor() {
CursorMan.showMouse(true);
updateCursor();
}
void Cursor::hideCursor() {
CursorMan.showMouse(false);
}
bool Cursor::isCursorVisible() const {
return CursorMan.isVisible();
}
void Cursor::setAnimation(uint8 start, uint8 end, int16 delay) {
_aniCount = _animStart = start;
_animEnd = end;
if (delay >= 0)
_animDelay = delay;
_curAniCountdown = 0;
}
void Cursor::setCustomRoomCursor(byte *roomSprite) {
const uint16 width = READ_LE_INT16(roomSprite);
const uint16 height = READ_LE_INT16(roomSprite + 2);
setCustomCursor(roomSprite + 4, width, height);
}
void Cursor::setCustomCursor(byte *data, uint16 width, uint16 height) {
_currentCursor.data = _customCursor.data = data;
_currentCursor.width = _customCursor.width = width;
_currentCursor.height = _customCursor.height = height;
CursorMan.replaceCursor(_customCursor.data, _customCursor.width, _customCursor.height, 0, 0, 0);
}
void Cursor::clearCustomCursor() {
if (_customCursor.data) {
_customCursor.data = nullptr;
_customCursor.width = 0;
_customCursor.height = 0;
updateCursor();
}
}
void Cursor::move(int16 x, int16 y) {
g_events->warpMouse(Common::Point(x, y));
}
} // namespace Chewy

84
engines/chewy/cursor.h Normal file
View File

@@ -0,0 +1,84 @@
/* 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/>.
*
*/
#ifndef CHEWY_CURSOR_H
#define CHEWY_CURSOR_H
#include "chewy/globals.h"
namespace Chewy {
struct CursorSprite {
uint16 width;
uint16 height;
byte *data;
};
class Cursor {
public:
Cursor();
~Cursor();
void updateCursor();
void showCursor();
void hideCursor();
bool isCursorVisible() const;
void setAnimation(uint8 start, uint8 end, int16 delay);
void setCustomCursor(byte *data, uint16 width, uint16 height);
void setCustomRoomCursor(byte *roomSprite);
void clearCustomCursor();
void move(int16 x, int16 y);
uint8 getAnimStart() const { return _animStart; }
byte *getCursorSprite() const { return _currentCursor.data; }
uint16 getCursorWidth() const { return _currentCursor.width; }
uint16 getCursorHeight() const { return _currentCursor.height; }
byte *getCursorSprite(uint num) const { return _curSprites[num].data; }
uint16 getCursorWidth(uint num) const { return _curSprites[num].width; }
uint16 getCursorHeight(uint num) const { return _curSprites[num].height; }
void setInventoryCursor(int num) {
_invCursor = num;
if (num >= 0)
setAnimation(num, num, (1 + _G(gameState).DelaySpeed) * 5);
}
int getInventoryCursor() const { return _invCursor; }
bool usingInventoryCursor() const { return _invCursor >= 0; }
private:
CursorSprite *_curSprites = nullptr;
CursorSprite _customCursor;
CursorSprite _currentCursor;
uint32 _cursorCount = 0;
uint32 _invCursorCount = 0;
int _invCursor = 0;
int16 _curAniCountdown = 0;
int16 _aniCount = 0;
uint8 _animStart = 0;
uint8 _animEnd = 0;
int16 _animDelay = 0;
};
} // namespace Chewy
#endif

575
engines/chewy/defines.h Normal file
View File

@@ -0,0 +1,575 @@
/* 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/>.
*
*/
#ifndef CHEWY_DEFINES_H
#define CHEWY_DEFINES_H
namespace Chewy {
#define VERSION1 0
#define VERSION2 2
#define ADS_TAP_MAX 500
#define ATS_TAP_MAX 100
#define AAD_TAP_MAX 100
#define INV_TAP_MAX 140
#define USE_TAP_MAX 140
#define ADS_TAP_OFF 0
#define AAD_TAP_OFF ADS_TAP_MAX + ATS_TAP_MAX // 500 + 100
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 200
enum SetupScreenMode {
NO_SETUP = 0,
DO_SETUP = 1,
DO_MAIN_LOOP = 2
};
#define JXDIFF 180
#define JYDIFF 150
#define SAVEIO 1
#define LOADIO 2
#define ALLIO 3
#define PAL1 1
#define CUR_WALK 0
#define CUR_USE 1
#define CUR_LOOK 2
#define CUR_TALK 3
#define CUR_SAVE 4
#define CUR_INVENT 5
#define CUR_NO_WALK 6
#define CUR_NOPE 7
#define CUR_NO_USE 10
#define CUR_NO_LOOK 11
#define CUR_NO_TALK 12
#define CUR_EXIT_LEFT 13
#define CUR_EXIT_RIGHT 14
#define CUR_EXIT_TOP 15
#define CUR_EXIT_BOTTOM 16
#define CUR_USER 17
#define CUR_DISK 18
#define CUR_HOWARD 19
#define CUR_POINT 20
#define CUR_NICHELLE 21
#define CUR_BLASTER 22
#define EXIT_LEFT_SPR 26
#define EXIT_RIGHT_SPR 27
#define EXIT_ABOVE_SPR 28
#define EXIT_BOTTOM_SPR 29
#define MENU_X 26
#define MENU_Y 21
#define MENU_CLIPX1 18
#define MENU_CLIPY1 5
#define MENU_CLIPX2 245
#define MENU_CLIPY2 30
#define MAX_MENU_SPRITE 13
#define MENU_START_SPRITE 0
#define WIN_INF_X 15
#define WIN_INF_Y 15
#define WIN_LOOK_X 30
#define WIN_LOOK_Y 150
#define ARROW_UP 26
#define INVENTORY_HOTSPOTS_COUNT 8
#define HOT_LOOK_NR 2
#define MES_RAHMEN 1
#define MES_NO_RAHMEN 2
#define INV_ATS_MODE 0
#define INV_USE_ATS_MODE 1
#define WIN_INVENTORY WIN_INF_X,WIN_INF_Y,18,11,60,1
#define WIN_TEST 24,36,2,8,60,0
#define WIN_LOOK WIN_LOOK_X,WIN_LOOK_Y,10,6,60,1
#define WIN_LOOK2 WIN_LOOK_X+4,WIN_LOOK_Y+4,3,3,60,0
#define MAX_RAUM 70
#define MAX_MOV_OBJ 140
#define MAX_FEST_OBJ 140
#define MAX_EXIT 150
#define MAX_AUTO_MOV 20
#define MAX_TIMER_OBJ 10
#define MAX_ROOM_TIMER 10
#define ANI_FRONT 0
#define ANI_BACK 1
#define ANI_WAIT 0
#define ANI_GO 1
#define MAX_PROG_ANI 10
#define INVENTORY_NORMAL 0
#define INVENTORY_STATIC 1
#define STATIC_USE 2
#define DETEDIT_REC 3
#define AUTO_OBJ 4
#define DETAIL_OBJ 5
#define SPIELER_OBJ 6
#define EPISODE1_TGP 0
#define GBOOK_TGP 1
#define NOTEBOOK_START 2
#define DIARY_START 3
#define CURSOR_TAF "misc/cursor.taf"
#define INVENTORY_TAF "misc/inventar.taf"
#define INVENTORY_IIB "misc/inventar.iib"
#define INVENTORY_SIB "misc/inventar.sib"
#define EXIT_EIB "misc/exit.eib"
#define CHEWY_TAF "misc/ch_walk.taf"
#define CHEWY_BO_TAF "misc/ch_bork.taf"
#define CHEWY_MI_TAF "misc/ch_mini.taf"
#define CHEWY_PUMP_TAF "misc/ch_pump.taf"
#define CHEWY_ROCK_TAF "misc/ch_rock.taf"
#define CHEWY_JMAN_TAF "misc/ch_mans.taf"
#define CHEWY_HELM_TAF "misc/ch_helm.taf"
#define MENUTAF "misc/menu.taf"
#define CH_SPZ_FILE "misc/ch_spez.taf"
#define OPTION_TAF "misc/option.taf"
#define DETAILTEST "room/test.rdi"
#define GBOOK "back/gbook.tgp"
#define EPISODE1 "back/episode1.tgp"
#define EPISODE1_GEP "back/episode1.gep"
#define FONT6x8 "txt/6x8.tff"
#define FONT8x8 "txt/8x8.tff"
#define ATDS_TXT "txt/atds.tap"
#define INV_ATS_STEUER "txt/inv_st.s"
#define ROOM_ATS_STEUER "txt/room_st.s"
#define ADS_TXT_STEUER "txt/diah.adh"
#define INV_USE_IDX "txt/inv_use.idx"
#define DETAIL_TVP "sound/details.tap"
#define QUIT_MSG_EN "QUIT ?? Y/N "
#define QUIT_MSG_DE "BEENDEN ?? J/N "
#define MAX_PERSON 3
#define P_CHEWY 0
#define P_HOWARD 1
#define P_NICHELLE 2
#define P_3 3
#define P_4 4
#define CHEWY_NORMAL 1
#define CHEWY_BORK 2
#define CHEWY_MINI 3
#define CHEWY_PUMPKIN 4
#define CHEWY_ROCKER 5
#define CHEWY_JMANS 6
#define CHEWY_ANI7 7
#define P_LEFT 0
#define P_RIGHT 1
#define LEFT 0
#define RIGHT 1
#define UP 2
#define DOWN 3
#define CH_UP 0
#define CH_DOWN 1
#define CH_LEFT_GE 2
#define CH_LEFT_NO 3
#define CH_LEFT_ZW 4
#define CH_RIGHT_GE 5
#define CH_RIGHT_NO 6
#define CH_RIGHT_ZW 7
#define CH_L_STEHEN 4
#define CH_R_STEHEN 7
#define CH_X_PIX 8
#define CH_Y_PIX 8
#define CH_HOT_MOV_X 8
#define CH_HOT_MOV_Y 25
#define CH_HOT_Y 34
#define CH_HOT_X 25
#define HO_HOT_MOV_X 8
#define HO_HOT_MOV_Y 59
#define HO_HOT_X 25
#define HO_HOT_Y 68
#define HO_X_PIX 8
#define NI_HOT_MOV_X 8
#define NI_HOT_MOV_Y 59
#define NI_HOT_X 25
#define NI_HOT_Y 68
#define NI_X_PIX 8
#define CH_SPZ_OFFSET 345
#define MAX_SPZ_PHASEN 30
#define CH_TALK1 0
#define CH_TALK2 1
#define CH_TALK3 2
#define CH_TALK4 3
#define CH_TALK5 4
#define CH_TALK6 5
#define CH_TALK7 6
#define CH_TALK8 7
#define CH_TALK9 8
#define CH_TALK10 9
#define CH_BAD1 10
#define CH_WONDER1 11
#define CH_EKEL 12
#define CH_LGET_O 13
#define CH_LGET_U 14
#define CH_TALK11 15
#define CH_TALK12 16
#define CH_TRANS 17
#define HO_WALK_L 18
#define HO_STAND_L 19
#define HO_TALK_L 20
#define HO_FRONT 21
#define HO_WALK_R 22
#define HO_STAND_R 23
#define HO_TALK_R 24
#define HO_BACK 25
#define CH_PUMP_TALK 26
#define CH_PUMP_GET1 27
#define CH_ROCK_GET1 28
#define CH_ROCK_HAND 29
#define CH_ROCK_TALK1 30
#define CH_ROCK_GET2 31
#define HO_BRILL_JMP 32
#define CH_JM_TITS 33
#define CH_JM_TALK 34
#define NI_WALK_L 35
#define NI_STAND_L 36
#define NI_TALK_L 37
#define NI_FRONT 38
#define NI_WALK_R 39
#define NI_STAND_R 40
#define NI_TALK_R 41
#define NI_BACK 42
#define ROOM_0_3 3
#define AUGE_TIMER 2
#define FUETTER_POS 3
#define KISSEN_POS 4
#define BLITZ_POS 5
#define VERSTECK_POS 6
#define PILLOW_INV 0
#define SLIME_INV 1
#define RED_CARD_INV 2
#define CABLE_INV 3
#define MONOCLE_INV 4
#define NOTEBOOK_INV 5
#define NOTEBOOK_OPEN_INV 6
#define DEFEKT_INV 7
#define STAHLSEIL_INV 8
#define BECHER_LEER_INV 9
#define BECHER_VOLL_INV 10
#define GIPS_EIMER_INV 11
#define SCHLOTT_INV 12
#define ZANGE_INV 13
#define MASKE_INV 14
#define KOHLE_HEISS_INV 15
#define KOHLE_KALT_INV 16
#define DEE_PAINT_INV 17
#define SURIMY_INV 18
#define BORK_INV 19
#define SPINAT_INV 20
#define YEL_CARD_INV 21
#define BWAFFE_INV 22
#define SICHERUNG_INV 23
#define FLUXO_INV 24
#define TRANSLATOR_INV 25
#define CARTRIDGE_INV 26
#define TALISMAN_INV 27
#define SEIL_INV 28
#define CYB_KRONE_INV 29
#define SCHLAUCH_INV 30
#define TRICHTER_INV 31
#define FISHINGROD_INV 32
#define MILCH_INV 33
#define KNIFE_INV 34
#define PUMPE_INV 35
#define CENT_INV 36
#define FISHING_ROD_INV 37
#define DENTURES_INV 38
#define H_FUTTER_INV 39
#define PUMPKIN_INV 40
#define K_MASKE_INV 41
#define K_FLEISCH_INV 42
#define K_KERNE_INV 43
#define EGGS_INV 44
#define KAFFEE_INV 45
#define PUTENKEULE_INV 46
#define BONE_INV 47
#define MANUSKRIPT_INV 48
#define RECORDER_INV 49
#define ZAPPER_INV 50
#define MUNTER_INV 51
#define EMPTY_MILK_BOTTLE_INV 52
#define WATER_FILLED_BOTTLE_INV 53
#define PAPIER_INV 54
#define LETTER_INV 55
#define TICKET_INV 56
#define ZEITUNG_INV 57
#define BMARKE_INV 58
#define STAMPEDLETTER_INV 59
#define DUENGER_INV 60
#define LIKOER_INV 61
#define LIKOER2_INV 62
#define DOLLAR175_INV 63
#define CASSETTE_INV 64
#define HOTEL_INV 65
#define KAPPE_INV 66
#define BOTTLE_INV 67
#define GUM_INV 68
#define CIGAR_INV 69
#define KEY_INV 70
#define BURGER_INV 71
#define WOOL_INV 72
#define UHR_INV 73
#define RING_INV 74
#define SACKGELD_INV 75
#define KILLER_INV 76
#define CUTMAG_INV 77
#define JMKOST_INV 78
#define LEDER_INV 79
#define SPARK_INV 80
#define BESTELL_INV 81
#define VCARD_INV 82
#define EINLAD_INV 83
#define GERAET_INV 84
#define ASCHE_INV 85
#define PIRANHA_INV 86
#define SCHALL_INV 87
#define ARTIFACT_INV 88
#define GALA_INV 89
#define PARROT_INV 90
#define DRINK_COUPON_INV 91
#define CLINT_500_INV 92
#define CLINT_1500_INV 93
#define CLINT_3000_INV 94
#define B_MARY_INV 95
#define VIDEO_INV 96
#define B_MARY2_INV 97
#define KARTE_INV 98
#define MACHETE_INV 99
#define RUBBER_INV 100
#define FOOD_CERTIFICATE_INV 101
#define DIARY_INV 109
#define SIB_SLIME 3
#define NO_MOV_OBJ 127
#define CHEWY_OBJ 255
#define HOWARD_OBJ 254
#define NICHELLE_OBJ 253
#define AUTO_OBJ0 0
#define AUTO_OBJ1 1
#define AUTO_OBJ2 2
#define AUTO_OBJ3 3
#define AUTO_OBJ4 4
#define MAX_OBJ_MOV 3
#define INV_USE_ATS_MAX 500
#define ATS_ACTION_VOR 0
#define ATS_ACTION_NACH 1
#define FCUT_000 0 // Chewy escapes the prison cell
#define FCUT_001 1 // Burger
#define FCUT_002 2 // Chewy mocks an alien and he trips on a rope
#define FCUT_003 3 // Jumping rat-line creature
#define FCUT_004 4 // Chewy sticks his hand in the rat's hole (custom callback: Room6::cut_serv1)
#define FCUT_005 5 // Chewy sticks the burger in the rat's hole and catches it (custom callback: Room6::cut_serv2)
#define FCUT_006 6 // Chewy pushes the big red button and a huge anvil drops on him
#define FCUT_007 7 // Chewy paints "don't" in front of "push this"
#define FCUT_008 8 // Alien pushes the big red button and a huge anvil drops on him
#define FCUT_009 9 // Chewy tries the transporter (custom callback: Room11::cut_serv)
#define FCUT_010 10 // Chewy uses a deflated alien in the transporter (custom callback: Room12::cut_serv)
#define FCUT_011 11 // Four panel video, where Chewy flies in a spaceship
#define FCUT_012 12 // Chewy messes with a conveyor belt
#define FCUT_013 13 // Chewy is transported in place of an alien
#define FCUT_014 14 // Chewy jumps on a conveyor belt
#define FCUT_015 15 // Transporter
#define FCUT_016 16 // Transporter
#define FCUT_017 17 // Chewy drops from a conveyor belt into a dumpster
#define FCUT_SPACECHASE_18 18 // Space chase: Chewy escapes F5 with spaceship
#define FCUT_SPACECHASE_19 19 // Space chase: Spaceship flight
#define FCUT_SPACECHASE_20 20 // Space chase: Spaceship flight
#define FCUT_SPACECHASE_21 21 // Space chase: Aliens chasing Chewy's spaceship
#define FCUT_SPACECHASE_22 22 // Space chase: Dogfight with Chewy and alien spaceship
#define FCUT_SPACECHASE_23 23 // Space chase: Chewy's spaceship enters bumper field and black hole
#define FCUT_SPACECHASE_24 24 // Space chase: Chewy's spaceship travels through black hole
#define FCUT_SPACECHASE_25 25 // Space chase: Chewy's spaceship approaches earth
#define FCUT_SPACECHASE_26 26 // Space chase: Chewy's spaceship starts descending
#define FCUT_SPACECHASE_27 27 // Space chase: Chewy's spaceship approaches farm
#define FCUT_SPACECHASE_28 28 // Space chase: Chewy's spaceship performs crash landing near farm
#define FCUT_029 29 // Chewy wakes up after crash landing
#define FCUT_030 30 // Chewy douses shaceship fire
#define FCUT_031 31 // Chewy uses kitchen appliance
#define FCUT_032 32 // TV: Farmer speaking (custom callback: Room39::setup_func)
#define FCUT_033 33 // TV: Gasp ghost show intro
#define FCUT_034 34 // TV: Gasp ghost show (custom callback: Room39::setup_func)
#define FCUT_035 35 // TV: Book sale show (custom callback: Room39::setup_func)
#define FCUT_036 36 // TV: Laura letter - head chopping block
#define FCUT_037 37 // TV: Tied girl and aliens (custom callback: Room39::setup_func)
#define FCUT_038 38 // TV: Flap news (custom callback: Room39::setup_func)
#define FCUT_039 39 // TV: Flap news with alien (custom callback: Room39::setup_func)
#define FCUT_040 40 // TV: Cooking show (custom callback: Room39::setup_func)
#define FCUT_041 41 // Using translator on TV to learn English
#define FCUT_042 42 // Turning on TV
#define FCUT_043 43 // Chewy trying to wake up Howard
#define FCUT_044 44 // Chewy using head band with typewriter
#define FCUT_045 45 // Using translator on cat
#define FCUT_046 46 // Using rat in the attic
#define FCUT_047 47 // Using chicken feed on seesaw
#define FCUT_048 48 // Using fishing pole and bone to grab the dog dentures
#define FCUT_049 49 // Closeup of Chewy having taken the dog dentures
#define FCUT_050 50 // Barking dog
#define FCUT_051 51 // Barking dog without dentures
#define FCUT_052 52 // Using translator on chicken
#define FCUT_053 53 // Chewy watching a fight
#define FCUT_054 54 // Chewy mocking animal
#define FCUT_055 55 // Using rat on old car
#define FCUT_056 56 // Using rat in front of old car, flower appears
#define FCUT_057 57 // Chewy with pumpkin head in the mail office using the vending machine
#define FCUT_058 58 // Zombie girl jumping on train tracks
#define FCUT_059 59 // Zombie girl talking to the pumpkin dummy, causing its head to explode
#define FCUT_060 60 // Zombie girl talking to the pumpkin dummy and crashing into the store
#define FCUT_061 61 // Zombie girl getting scared, shrinks and is placed in bottle by Howard (custom callback: Room43::setup_func)
#define FCUT_062 62 // Zombie girl talks from inside the bottle
#define FCUT_063 63 // Howard and Chewy walking beside a moving truck
#define FCUT_064 64 // Giant pumpkin bursts through the house
#define FCUT_065 65 // Policeman fighting Howard and Chewy
#define FCUT_066 66 // Policeman loses from Howard and Chewy
#define FCUT_067 67 // Chewy throws smoke at kid, so it spits a chewing gum at Howard
#define FCUT_068 68 // Man runs out of room full of spiders
#define FCUT_069 69 // Chewy enters phone booth, transforms into blonde woman
#define FCUT_070 70 // Woman runs out of room full of spiders
#define FCUT_071 71 // Best seller book presentation
#define FCUT_072 72 // Chewy removes his woman disguise
#define FCUT_073 73 // Train moving
#define FCUT_074 74 // Howard and Chewy at docks, another man appears
#define FCUT_075 75 // Howard and Chewy at docks, get thrown out of store
#define FCUT_076 76 // Howard inside box, lid closes
#define FCUT_077 77 // Chewy turns TV host into alien
#define FCUT_078 78 // Fire alarm in TV console room
#define FCUT_079 79 // Running away in the sewers
#define FCUT_080 80 // Gasp ghost show TV set, rain starts
#define FCUT_081 81 // Gasp ghost show TV set, Chewy and alien
#define FCUT_082 82 // Gasp ghost show TV set, large monster prop is dropped on alien
#define FCUT_083 83 // Lady screaming at piranha in cocktail glass
#define FCUT_084 84 // Dropping inside trap in jungle
#define FCUT_085 85 // Dropping inside trap in jungle (with Howard)
#define FCUT_086 86 // King kong chasing hunters
#define FCUT_087 87 // King kong fights alien spaceships
#define FCUT_088 88 // King kong shouting
#define FCUT_089 89 // Lasers shot at heroes outside temple (custom callback: Room87::proc5)
#define FCUT_090 90 // Aliens abduct Nichelle
#define FCUT_091 91 // Alien ship flies away with Nichelle
#define FCUT_092 92 // Chewy taunts aliens opposite a cave
#define FCUT_093 93 // Chewy, pink ball and statue turning into pink alien
#define FCUT_094 94 // Pink alien talking (custom callback: Room87::proc3)
#define FCUT_095 95 // Pink alien talking (custom callback: Room87::proc5)
#define FCUT_096 96 // Pink alien jumping down
#define FCUT_097 97 // Aliens coming out of door and shooting
#define FCUT_098 98 // Chewy and pink alien running away from aliens
#define FCUT_099 99 // Pink alien taking pink ball
#define FCUT_100 100 // Heroes running away from aliens
#define FCUT_101 101 // Heroes falling off waterfall
#define FCUT_102 102 // Spaceship flying away from jungle and King Kong
#define FCUT_103 103 // Spaceship flying
#define FCUT_104 104 // Howard and Chewy beaming down
#define FCUT_105 105 // Spaceship beams up the heroes and flies away
#define FCUT_106 106 // Pink alien beams down the heroes
#define FCUT_107 107 // Chewy shooting at slime police zeppelin (custom callback: Room90::proc5)
#define FCUT_108 108 // Aliens entering hotel
#define FCUT_109 109 // Rat jumping closeup
#define FCUT_110 110 // Aliens at docks
#define FCUT_111 111 // Rat closeup
#define FCUT_112 112 // Alien band playing music (custom callback: Room56::proc1)
#define FCUT_113 113 // Howard and Chewy beaming up
#define FCUT_114 114 // Howard and Chewy opening a door leading outside building
#define FCUT_115 115 // Aliens falling off building
#define FCUT_116 116 // Ship in ocean
#define FCUT_117 117 // Volcano erupting, F5 emerges from inside
#define FCUT_118 118 // Ship flying above town
#define FCUT_119 119 // Ship flying above town
#define FCUT_120 120 // Howard and Chewy beaming down, shooting starts
#define FCUT_121 121 // Zombie sheriff shoots small winding pink aliens
#define FCUT_122 122 // Alien chases small winding pink alien
#define FCUT_123 123 // Howard and Chewy on a wagon jumping a gap on train track
#define FCUT_124 124 // Howard and Chewy on wagon
#define FCUT_125 125 // Wagon crashes into alien
#define FCUT_126 126 // Wagon running next to shooting alien
#define FCUT_127 127 // Wagon reaching the end of the tracks
#define FCUT_128 128 // Wagon reaching bridge
#define FCUT_129 129 // Wagon crossing bridge
#define FCUT_130 130 // Wagon crossing bridge
#define FCUT_131 131 // Wagon moving
#define FCUT_132 132 // Wagon moving
#define FCUT_133 133 // Howard and Chewy on wagon
#define FCUT_134 134 // Red spaceships (custom callback: flic_user_function)
#define FCUT_135 135 // Intro - red spaceships (custom callback: flic_user_function)
#define FCUT_136 136 // Red spaceship shooting spaceship (custom callback: flic_user_function)
#define FCUT_137 137 // Dogfight between red spaceship and spaceship (custom callback: flic_user_function)
#define FCUT_138 138 // Spaceships flying from F5 (custom callback: flic_user_function)
#define FCUT_139 139 // Chewy's spaceship enters bumper field (custom callback: flic_user_function)
#define FCUT_140 140 // Purple aliens talking from inside spaceships (custom callback: flic_user_function)
#define FCUT_141 141 // Purple alien talking from inside spaceship (custom callback: flic_user_function)
#define FCUT_142 142 // Purple alien talking from inside spaceship (custom callback: flic_user_function)
#define FCUT_143 143 // Purple alien talking from inside spaceship (custom callback: flic_user_function)
#define FCUT_144 144 // Purple alien talking from inside spaceship (custom callback: flic_user_function)
#define FCUT_145 145 // Purple alien talking from inside spaceship
#define FCUT_146 146 // Purple alien talking from inside spaceship (custom callback: flic_user_function)
#define FCUT_147 147 // Red space ship approaching Earth (custom callback: flic_user_function)
#define FCUT_148 148 // Purple alien entering F5 and getting pink orb (custom callback: flic_user_function)
#define FCUT_149 149 // Space ship shooting green bullet (custom callback: flic_user_function)
#define FCUT_150 150 // Space ship generating force field (custom callback: flic_user_function)
#define FCUT_151 151 // Alien talking from inside spaceship (custom callback: flic_user_function)
#define FCUT_152 152 // Purple alien crash landing outside temple, natives appear (custom callback: flic_user_function)
#define FCUT_153 153 // Red space ship crash landing in jungle (custom callback: flic_user_function)
#define FCUT_154 154 // Red space ship being chased (custom callback: flic_user_function)
#define FCUT_155 155 // Intro logos (German)
#define FCUT_156 156 // Red space ship entering black hole (custom callback: flic_user_function)
#define FCUT_157 157 // Red space ship traveling inside black hole (custom callback: flic_user_function)
#define FCUT_158 158 // Howard and Chewy waking up
#define FCUT_159 159 // Credits
#define FCUT_160 160 // Intro logos (English)
#define EXIT_LEFT 1
#define EXIT_RIGHT 2
#define EXIT_TOP 3
#define EXIT_BOTTOM 4
#define WAIT_TASTE_LOS while (g_events->getSwitchCode() != -1 \
&& !SHOULD_QUIT) { g_events->update(); }
} // namespace Chewy
#endif

616
engines/chewy/detail.cpp Normal file
View File

@@ -0,0 +1,616 @@
/* 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/>.
*
*/
#include "chewy/detail.h"
#include "chewy/globals.h"
#include "chewy/mcga_graphics.h"
#include "chewy/memory.h"
#include "chewy/sound.h"
#include "chewy/resource.h"
namespace Chewy {
#define ANI_ON 1
#define ANI_OFF 0
bool RoomInfo::load(Common::SeekableReadStream *src) {
_roomNr = src->readByte();
_imageNr = src->readByte();
_autoMovNr = src->readByte();
_tafLoad = src->readByte();
src->read(_tafName, 14);
_zoomFactor = src->readByte();
_dummy = src->readByte();
return true;
}
bool RoomAutoMov::load(Common::SeekableReadStream *src) {
_x = src->readSint16LE();
_y = src->readSint16LE();
_sprNr = src->readByte();
_dummy = src->readByte();
return true;
}
bool SoundDefBlk::load(Common::SeekableReadStream *src) {
int i;
src->skip(MAX_SOUNDS * 2); // sound_enable flags
for (i = 0; i < MAX_SOUNDS; ++i)
sound_index[i] = src->readSint16LE();
for (i = 0; i < MAX_SOUNDS; ++i)
sound_start[i] = src->readSint16LE();
for (i = 0; i < MAX_SOUNDS; ++i)
channel[i] = src->readSint16LE();
for (i = 0; i < MAX_SOUNDS; ++i)
volume[i] = src->readSint16LE();
for (i = 0; i < MAX_SOUNDS; ++i)
repeats[i] = src->readSint16LE();
for (i = 0; i < MAX_SOUNDS; ++i)
stereo[i] = src->readSint16LE();
return true;
}
bool AniDetailInfo::load(Common::SeekableReadStream *src) {
x = src->readSint16LE();
y = src->readSint16LE();
start_flag = src->readByte();
repeat = src->readByte();
start_ani = src->readSint16LE();
end_ani = src->readSint16LE();
ani_count = src->readSint16LE();
delay = src->readSint16LE();
delay_count = src->readSint16LE();
reverse = src->readSint16LE();
timer_start = src->readSint16LE();
z_ebene = src->readSint16LE();
load_flag = src->readByte();
zoom = src->readByte();
sfx.load(src);
show_1_phase = src->readSint16LE();
phase_nr = src->readSint16LE();
return true;
}
bool StaticDetailInfo::load(Common::SeekableReadStream *src) {
x = src->readSint16LE();
y = src->readSint16LE();
SprNr = src->readSint16LE();
z_ebene = src->readSint16LE();
hide = src->readByte();
Dummy = src->readByte();
return true;
}
bool RoomDetailInfo::load(Common::SeekableReadStream *src) {
int i;
_staticDetailNr = src->readSint16LE();
_aniDetailNr = src->readSint16LE();
src->skip(4); // dptr
for (i = 0; i < MAXDETAILS; ++i)
Ainfo[i].load(src);
for (i = 0; i < MAXDETAILS; ++i)
staticSprite[i].load(src);
for (i = 0; i < MAX_M_ITEMS * 4; ++i)
mvect[i] = src->readSint16LE();
for (i = 0; i < MAX_M_ITEMS; ++i)
mtxt[i] = src->readSint16LE();
Ri.load(src);
for (i = 0; i < MAX_AUTO_MOV; ++i)
autoMove[i].load(src);
for (i = 0; i < MAXDETAILS * MAX_SOUNDS; ++i)
detailSfxIndex[i] = src->readSint16LE();
src->skip(4 * MAXDETAILS * MAX_SOUNDS); // sample offsets
return true;
}
bool RdiDataHeader::load(Common::SeekableReadStream *src) {
src->read(_id, 4);
_nr = src->readSint16LE();
return true;
}
Detail::Detail() {
int16 size = sizeof(RoomDetailInfo);
char *tptr = (char *)&_rdi;
for (int16 i = 0; i < size; i++)
*tptr++ = 0;
for (int16 i = 0; i < MAXDETAILS; i++) {
_rdi.staticSprite[i].SprNr = -1;
_rdi.Ainfo[i].start_ani = -1;
}
for (int16 i = 0; i < (MAX_M_ITEMS - 1) << 2; i += 4)
_rdi.mvect[i] = -1;
for (int16 i = 0; i < 4; ++i)
_rdiDataHeader._id[i] = 0;
_rdiDataHeader._nr = -1;
_globalDelay = 0;
_aniFreezeflag = false;
_fullTaf = false;
_rdi.dptr = nullptr;
_tafName = "";
for (int16 i = 0; i < (MAXDETAILS * MAX_SOUNDS); i++) {
_rdi.detailSfxIndex[i] = -1;
}
_directTafAni = ANI_OFF;
}
Detail::~Detail() {
_directTafAni = ANI_OFF;
}
void Detail::load_rdi(const char *fname_, int16 room_nr) {
Common::File f;
TafInfo *tmprdi = _rdi.dptr;
if (fname_ && f.open(fname_)) {
if (_rdiDataHeader.load(&f)) {
if (!scumm_strnicmp(_rdiDataHeader._id, "RDI", 3)) {
f.seek(room_nr * RoomDetailInfo::SIZE(), SEEK_CUR);
if (!_rdi.load(&f)) {
error("load_rdi error");
}
} else {
error("load_rdi error");
}
} else {
error("load_rdi error");
}
f.close();
} else {
error("load_rdi error");
}
_rdi.dptr = tmprdi;
}
void Detail::load_rdi_taf(const char *filename, int16 load_flag) {
if (!_tafName.equalsIgnoreCase(filename)) {
if (_rdi.dptr) {
if (_fullTaf) {
free(_rdi.dptr);
_rdi.dptr = nullptr;
_fullTaf = false;
} else {
del_taf_tbl(_rdi.dptr);
}
}
_tafName = filename;
if (!load_flag) {
_rdi.dptr = init_taf_tbl(filename);
load_taf_tbl(_rdi.dptr);
} else {
_rdi.dptr = _G(mem)->taf_adr(filename);
_fullTaf = true;
}
} else if (!_fullTaf)
load_taf_tbl(_rdi.dptr);
}
void Detail::del_dptr() {
if (_rdi.dptr) {
if (_fullTaf)
free((char *)_rdi.dptr);
else {
del_taf_tbl(_rdi.dptr);
_rdi.dptr = nullptr;
_tafName.clear();
}
_rdi.dptr = nullptr;
}
}
void Detail::load_taf_tbl(TafInfo *fti) {
if (!fti) {
fti = _rdi.dptr;
}
if (fti) {
for (int16 i = 0; i < MAXDETAILS; i++) {
if (_rdi.staticSprite[i].SprNr != -1)
load_taf_seq(_rdi.staticSprite[i].SprNr, 1, fti);
if (_rdi.Ainfo[i].start_ani != -1 &&
_rdi.Ainfo[i].end_ani != -1 && !_rdi.Ainfo[i].load_flag)
load_taf_seq(_rdi.Ainfo[i].start_ani, (_rdi.Ainfo[i].end_ani - _rdi.Ainfo[i].start_ani) + 1, fti);
}
}
}
TafInfo *Detail::init_taf_tbl(const char *fname_) {
TafInfo *Tt = nullptr;
SpriteResource *res = new SpriteResource(_tafName);
int16 nr = res->getChunkCount();
byte *tmp = (byte *)MALLOC((int32)nr * sizeof(byte *) + sizeof(TafInfo));
Tt = (TafInfo *)tmp;
Tt->count = nr;
Tt->correction = (int16 *)MALLOC((int32)Tt->count * 2 * sizeof(int16));
Tt->image = (byte **)(tmp + sizeof(TafInfo));
memcpy(Tt->correction, (byte *)res->getSpriteCorrectionsTable(), Tt->count * 2 * sizeof(int16));
Tt->palette = nullptr;
delete res;
return Tt;
}
void Detail::del_taf_tbl(TafInfo *Tt) {
if (!Tt) {
Tt = _rdi.dptr;
}
for (int16 i = 0; i < Tt->count; i++) {
free(Tt->image[i]);
}
free(Tt->correction);
free(Tt);
}
void Detail::del_taf_tbl(int16 start, int16 nr, TafInfo *Tt) {
if (!Tt)
Tt = _rdi.dptr;
for (int16 i = start; i < start + nr && i < Tt->count; i++) {
free(Tt->image[i]);
Tt->image[i] = nullptr;
}
}
void Detail::load_taf_seq(int16 sprNr, int16 sprCount, TafInfo *Tt) {
if (!Tt)
Tt = _rdi.dptr;
SpriteResource *res = new SpriteResource(_tafName);
for (int16 i = 0; i < sprCount; i++) {
if (!Tt->image[sprNr + i]) {
res->getSpriteData(sprNr + i, &Tt->image[sprNr + i], true);
}
}
delete res;
}
void Detail::hideStaticSpr(int16 nr) {
if (nr >= 0 && nr < MAXDETAILS)
_rdi.staticSprite[nr].hide = true;
}
void Detail::showStaticSpr(int16 nr) {
if (nr >= 0 && nr < MAXDETAILS)
_rdi.staticSprite[nr].hide = false;
}
void Detail::setStaticPos(int16 detNr, int16 x, int16 y, bool hideFl, bool correctionFlag) {
if (correctionFlag) {
int16 *Cxy = &_rdi.dptr->correction[_rdi.staticSprite[detNr].SprNr * 2];
x += Cxy[0];
y += Cxy[1];
}
_rdi.staticSprite[detNr].x = x;
_rdi.staticSprite[detNr].y = y;
_rdi.staticSprite[detNr].hide = hideFl;
}
void Detail::setDetailPos(int16 detNr, int16 x, int16 y) {
_rdi.Ainfo[detNr].x = x;
_rdi.Ainfo[detNr].y = y;
}
void Detail::getAniValues(int16 aniNr, int16 *start, int16 *end) {
*start = _rdi.Ainfo[aniNr].start_ani;
*end = _rdi.Ainfo[aniNr].end_ani;
}
AniDetailInfo *Detail::getAniDetail(int16 aniNr) {
return &_rdi.Ainfo[aniNr];
}
void Detail::init_taf(TafInfo *dptr) {
_rdi.dptr = dptr;
}
TafInfo *Detail::get_taf_info() {
return _rdi.dptr;
}
RoomDetailInfo *Detail::getRoomDetailInfo() {
return &_rdi;
}
void Detail::freezeAni() {
_aniFreezeflag = true;
}
void Detail::unfreezeAni() {
_aniFreezeflag = false;
}
void Detail::set_static_ani(int16 ani_nr, int16 static_nr) {
_rdi.Ainfo[ani_nr].show_1_phase = true;
if (static_nr != -1)
_rdi.Ainfo[ani_nr].phase_nr = static_nr;
}
void Detail::del_static_ani(int16 ani_nr) {
_rdi.Ainfo[ani_nr].show_1_phase = false;
}
void Detail::plot_ani_details(int16 scrx, int16 scry, int16 start, int16 end, int16 zoomx, int16 zoomy) {
if (start > end)
SWAP(start, end);
if (start >= MAXDETAILS)
start = 0;
if (end >= MAXDETAILS)
end = MAXDETAILS - 1;
for (int16 i = start; (i <= end); i++) {
AniDetailInfo *adiptr = &_rdi.Ainfo[i];
if (adiptr->start_flag && (adiptr->start_ani != -1) && (adiptr->end_ani != -1)) {
int16 sprnr = adiptr->ani_count;
int16 *Cxy = _rdi.dptr->correction + sprnr * 2;
int16 kx = Cxy[0];
int16 ky = Cxy[1];
if (zoomx != 0 || zoomy != 0)
calc_zoom_kor(&kx, &ky, zoomx, zoomy);
int16 x = adiptr->x + kx - scrx;
int16 y = adiptr->y + ky - scry;
if (adiptr->load_flag == 1) {
load_taf_ani_sprite(sprnr);
_G(out)->scale_set(_tafLoadBuffer, x, y, zoomx, zoomy, 0);
} else
_G(out)->scale_set(_rdi.dptr->image[sprnr], x, y, zoomx, zoomy, 0);
Sound *sound = g_engine->_sound;
for (int16 k = 0; k < MAX_SOUNDS; k++) {
const int16 sfxSlot = adiptr->sfx.sound_index[k];
if (sfxSlot != -1) {
const int16 sfxIndex = _rdi.detailSfxIndex[sfxSlot];
if (adiptr->sfx.sound_start[k] == adiptr->ani_count &&
!adiptr->delay_count) {
const uint channel = adiptr->sfx.channel[k] & 7;
sound->playSound(sfxIndex, channel, adiptr->sfx.repeats[k], adiptr->sfx.volume[k], adiptr->sfx.stereo[k]);
}
}
}
if (!_aniFreezeflag) {
if (adiptr->reverse) {
if (adiptr->delay_count > 0)
--adiptr->delay_count;
else {
adiptr->delay_count = adiptr->delay + _globalDelay;
if (adiptr->ani_count > adiptr->start_ani)
--adiptr->ani_count;
else {
adiptr->ani_count = adiptr->end_ani;
if (adiptr->start_flag != 255) {
--adiptr->start_flag;
}
}
}
} else {
if (adiptr->delay_count > 0)
--adiptr->delay_count;
else {
adiptr->delay_count = adiptr->delay + _globalDelay;
if (adiptr->ani_count < adiptr->end_ani)
++adiptr->ani_count;
else {
adiptr->ani_count = adiptr->start_ani;
if (adiptr->start_flag != 255) {
--adiptr->start_flag;
}
}
}
}
}
} else {
adiptr->start_flag = 0;
if (adiptr->show_1_phase) {
_rdi.staticSprite[adiptr->phase_nr].hide = false;
plot_static_details(scrx, scry, adiptr->phase_nr, adiptr->phase_nr);
_rdi.staticSprite[adiptr->phase_nr].hide = true;
}
}
}
}
void Detail::plot_static_details(int16 scrx, int16 scry, int16 start, int16 end) {
if (start > end)
SWAP(start, end);
if (start >= MAXDETAILS)
start = 0;
if (end >= MAXDETAILS)
end = MAXDETAILS - 1;
for (int16 i = start; i <= end; i++) {
if (_rdi.staticSprite[i].SprNr != -1 && !_rdi.staticSprite[i].hide) {
int16 x = _rdi.staticSprite[i].x - scrx;
int16 y = _rdi.staticSprite[i].y - scry;
byte *spriteImage = _rdi.dptr->image[_rdi.staticSprite[i].SprNr];
_G(out)->spriteSet(spriteImage, x, y, 0);
}
}
}
void Detail::startDetail(int16 nr, int16 rep, int16 reverse) {
if (nr != -1) {
AniDetailInfo *adiptr = &_rdi.Ainfo[nr];
if (rep)
adiptr->start_flag = rep;
else
adiptr->start_flag = adiptr->repeat;
adiptr->reverse = reverse;
if (reverse)
adiptr->ani_count = adiptr->end_ani;
else
adiptr->ani_count = adiptr->start_ani;
}
}
void Detail::stopDetail(int16 nr) {
if (nr >= 0 && nr < 32) {
_rdi.Ainfo[nr].start_flag = 0;
}
}
void Detail::playSound(int16 nr, int16 slot) {
const int16 sfxSlot = _rdi.Ainfo[nr].sfx.sound_index[slot];
if (sfxSlot != -1) {
const int16 sfxIndex = _rdi.detailSfxIndex[sfxSlot];
g_engine->_sound->playSound(sfxIndex, slot,
_rdi.Ainfo[nr].sfx.repeats[slot], _rdi.Ainfo[nr].sfx.volume[slot], _rdi.Ainfo[nr].sfx.stereo[slot]);
}
}
void Detail::stopSound(int16 slot) {
g_engine->_sound->stopSound(slot);
}
int16 Detail::maus_vector(int16 x, int16 y) {
int16 i = -1;
for (int16 j = 0; (j < (MAX_M_ITEMS - 1) << 2) && (i == -1); j += 4) {
if (_rdi.mvect[j] != -1) {
if ((x >= _rdi.mvect[j]) && (x <= _rdi.mvect[j + 2]) &&
(y >= _rdi.mvect[j + 1]) && (y <= _rdi.mvect[j + 3]))
i = j / 4;
}
}
return i;
}
int16 Detail::get_ani_status(int16 det_nr) {
return (_rdi.Ainfo[det_nr].start_flag > 0) ? 1 : 0;
}
SprInfo Detail::plot_detail_sprite(int16 scrx, int16 scry, int16 det_nr, int16 spr_nr, int16 mode) {
if (det_nr >= MAXDETAILS)
det_nr = MAXDETAILS - 1;
AniDetailInfo *adiptr = &_rdi.Ainfo[det_nr];
if (spr_nr < adiptr->start_ani)
spr_nr = adiptr->start_ani;
if (spr_nr > adiptr->end_ani)
spr_nr = adiptr->end_ani - 1;
int16 *Cxy = &_rdi.dptr->correction[spr_nr << 1];
int16 *Xy = (int16 *)_rdi.dptr->image[spr_nr];
_sprInfo._image = _rdi.dptr->image[spr_nr];
_sprInfo._x = adiptr->x + Cxy[0] - scrx;
_sprInfo._y = adiptr->y + Cxy[1] - scry;
_sprInfo.X1 = _sprInfo._x + Xy[0];
_sprInfo.Y1 = _sprInfo._y + Xy[1];
if (mode)
_G(out)->spriteSet(_sprInfo._image, _sprInfo._x, _sprInfo._y, 0);
Sound *sound = g_engine->_sound;
for (int16 k = 0; k < MAX_SOUNDS; k++) {
int16 soundEffect = adiptr->sfx.sound_index[k];
if (soundEffect != -1) {
if (adiptr->sfx.sound_start[k] == spr_nr) {
const uint channel = adiptr->sfx.channel[k] & 7;
sound->playSound(soundEffect, channel, adiptr->sfx.repeats[k], adiptr->sfx.volume[k], adiptr->sfx.stereo[k]);
}
}
}
return _sprInfo;
}
void Detail::set_global_delay(int16 delay) {
_globalDelay = delay - 2;
}
void Detail::calc_zoom_kor(int16 *kx, int16 *ky, int16 xzoom, int16 yzoom) {
float tmpx = (float)(((float)*kx / 100.0) * ((float)xzoom));
float tmpy = (float)(((float)*ky / 100.0) * ((float)yzoom));
float tmpx1 = tmpx - (int16)tmpx;
if (fabs(tmpx1) > 0.5)
++tmpx;
float tmpy1 = tmpy - (int16)tmpy;
if (fabs(tmpy1) > 0.5)
++tmpy;
*kx += (int16)tmpx;
*ky += (int16)tmpy;
}
int16 Detail::mouse_on_detail(int16 mouse_x, int16 mouse_y, int16 scrx, int16 scry) {
int16 ok = false;
int16 detail_nr = -1;
for (int16 i = 0; i < MAXDETAILS && !ok; i++) {
AniDetailInfo *adiptr = &_rdi.Ainfo[i];
if ((adiptr->start_flag) && (adiptr->start_ani != -1) && (adiptr->end_ani != -1)) {
int16 sprnr = adiptr->ani_count;
int16 *Cxy = _rdi.dptr->correction + (sprnr << 1);
int16 x = adiptr->x + Cxy[0] - scrx;
int16 y = adiptr->y + Cxy[1] - scry;
int16 *Xy;
if (adiptr->load_flag == 1) {
Xy = (int16 *)_tafLoadBuffer;
} else {
Xy = (int16 *)_rdi.dptr->image[sprnr];
}
if (mouse_x >= x && mouse_x <= x + Xy[0] &&
mouse_y >= y && mouse_y <= y + Xy[1]) {
ok = true;
detail_nr = i;
}
}
}
return detail_nr;
}
void Detail::set_taf_ani_mem(byte *load_area) {
_tafLoadBuffer = load_area;
_directTafAni = ANI_ON;
}
void Detail::load_taf_ani_sprite(int16 nr) {
SpriteResource *res = new SpriteResource(_tafName);
res->getSpriteData(nr, &_tafLoadBuffer, false);
delete res;
}
} // namespace Chewy

240
engines/chewy/detail.h Normal file
View File

@@ -0,0 +1,240 @@
/* 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/>.
*
*/
#ifndef CHEWY_DETAIL_H
#define CHEWY_DETAIL_H
#include "common/path.h"
#include "common/scummsys.h"
#include "common/stream.h"
#include "chewy/ngstypes.h"
namespace Chewy {
#define SAVE_ROOM 0
#define RESTORE_ROOM 1
#define MAX_SOUNDS 3
#define MAX_AUTO_MOV 20
struct RoomInfo {
uint8 _roomNr;
uint8 _imageNr;
uint8 _autoMovNr;
uint8 _tafLoad;
char _tafName[14];
uint8 _zoomFactor;
uint8 _dummy;
bool load(Common::SeekableReadStream *src);
static constexpr int SIZE() {
return 4 * 1 + 14 + 1 + 1;
}
};
struct RoomAutoMov {
int16 _x;
int16 _y;
uint8 _sprNr;
uint8 _dummy;
bool load(Common::SeekableReadStream *src);
static constexpr int SIZE() {
return 2 + 2 + 1 + 1;
}
};
#define MAXDETAILS 32
#define MAX_M_ITEMS 50
struct SprInfo {
byte *_image = nullptr;
int16 _zLevel = 0;
int16 _x = 0;
int16 _y = 0;
int16 X1 = 0;
int16 Y1 = 0;
};
struct SoundDefBlk {
// 2 * MAX_SOUNDS sound_enable flags
int16 sound_index[MAX_SOUNDS];
int16 sound_start[MAX_SOUNDS];
int16 channel[MAX_SOUNDS];
int16 volume[MAX_SOUNDS];
int16 repeats[MAX_SOUNDS];
int16 stereo[MAX_SOUNDS];
bool load(Common::SeekableReadStream *src);
static constexpr int SIZE() {
return 7 * 2 * MAX_SOUNDS;
}
};
struct AniDetailInfo {
int16 x;
int16 y;
uint8 start_flag;
uint8 repeat;
int16 start_ani;
int16 end_ani;
int16 ani_count;
int16 delay;
int16 delay_count;
int16 reverse;
int16 timer_start;
int16 z_ebene;
uint8 load_flag;
uint8 zoom;
SoundDefBlk sfx;
int16 show_1_phase;
int16 phase_nr;
bool load(Common::SeekableReadStream *src);
static constexpr int SIZE() {
return 2 + 2 + 1 + 1 + 2 * 8 + 1 + 1 +
SoundDefBlk::SIZE() + 2 + 2;
}
};
struct StaticDetailInfo {
int16 x;
int16 y;
int16 SprNr;
int16 z_ebene;
bool hide;
uint8 Dummy;
bool load(Common::SeekableReadStream *src);
static constexpr int SIZE() {
return 2 + 2 + 2 + 2 + 1 + 1;
}
};
struct RoomDetailInfo {
int16 _staticDetailNr = 0;
int16 _aniDetailNr = 0;
TafInfo *dptr = nullptr;
AniDetailInfo Ainfo[MAXDETAILS];
StaticDetailInfo staticSprite[MAXDETAILS];
int16 mvect[MAX_M_ITEMS * 4] = { 0 };
int16 mtxt[MAX_M_ITEMS] = { 0 };
RoomInfo Ri;
RoomAutoMov autoMove[MAX_AUTO_MOV];
int16 detailSfxIndex[MAXDETAILS * MAX_SOUNDS] = { 0 };
bool load(Common::SeekableReadStream *src);
static constexpr int SIZE() {
return 2 + 2 + 4 +
(AniDetailInfo::SIZE() * MAXDETAILS) +
(StaticDetailInfo::SIZE() * MAXDETAILS) +
(2 * MAX_M_ITEMS * 4) +
(2 * MAX_M_ITEMS) +
RoomInfo::SIZE() +
(RoomAutoMov::SIZE() * MAX_AUTO_MOV) +
(2 * MAXDETAILS * MAX_SOUNDS) +
(4 * MAXDETAILS * MAX_SOUNDS);
}
};
struct RdiDataHeader {
char _id[4];
int16 _nr;
bool load(Common::SeekableReadStream *src);
};
class Detail {
public:
Detail();
~Detail();
void load_rdi(const char *fname, int16 room_nr);
void load_rdi_taf(const char *fname, int16 load_flag);
void setStaticPos(int16 detNr, int16 x, int16 y, bool hideFl, bool correctionFlag);
void setDetailPos(int16 detNr, int16 x, int16 y);
void hideStaticSpr(int16 detNr);
void showStaticSpr(int16 detNr);
void freezeAni();
void unfreezeAni();
void getAniValues(int16 aniNr, int16 *start, int16 *end);
AniDetailInfo *getAniDetail(int16 aniNr);
void init_taf(TafInfo *dptr);
TafInfo *get_taf_info();
RoomDetailInfo *getRoomDetailInfo();
void set_static_ani(int16 ani_nr, int16 static_nr);
void del_static_ani(int16 ani_nr);
void startDetail(int16 nr, int16 rep, int16 reverse);
void stopDetail(int16 nr);
void playSound(int16 nr, int16 slot);
void stopSound(int16 slot);
void plot_ani_details(int16 scrx, int16 scry, int16 start, int16 end,
int16 zoomx, int16 zoomy);
void plot_static_details(int16 scrx, int16 scry, int16 start, int16 end);
int16 maus_vector(int16 x, int16 y);
int16 get_ani_status(int16 det_nr);
SprInfo plot_detail_sprite(int16 scrx, int16 scry, int16 det_nr,
int16 spr_nr, int16 mode);
void set_global_delay(int16 delay);
TafInfo *init_taf_tbl(const char *fname);
void del_taf_tbl(TafInfo *Tt);
void del_taf_tbl(int16 start, int16 nr, TafInfo *Tt);
void load_taf_seq(int16 sprNr, int16 sprCount, TafInfo *Tt);
void load_taf_tbl(TafInfo *fti);
void del_dptr();
void calc_zoom_kor(int16 *kx, int16 *ky, int16 xzoom,
int16 yzoom);
int16 mouse_on_detail(int16 mouse_x, int16 mouse_y,
int16 scrx, int16 scry);
void set_taf_ani_mem(byte *load_area);
private:
void load_taf_ani_sprite(int16 nr);
RoomDetailInfo _rdi;
RdiDataHeader _rdiDataHeader;
SprInfo _sprInfo;
int16 _globalDelay = 0;
bool _aniFreezeflag = false;
bool _fullTaf = false;
Common::Path _tafName;
byte *_tafLoadBuffer = nullptr;
int16 _directTafAni = 0;
};
} // namespace Chewy
#endif

127
engines/chewy/detection.cpp Normal file
View File

@@ -0,0 +1,127 @@
/* 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/>.
*
*/
#include "base/plugins.h"
#include "engines/advancedDetector.h"
#include "chewy/detection.h"
static const PlainGameDescriptor chewyGames[] = {
{"chewy", "Chewy: Esc from F5"},
{nullptr, nullptr}
};
namespace Chewy {
static const ChewyGameDescription gameDescriptions[] = {
{
{
"chewy",
nullptr,
AD_ENTRY1s("txt/atds.tap", "e6050c144dd4f23d79ea4f89a8ef306e", 218857),
Common::EN_ANY,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
GUIO2(GUIO_NOMIDI, GAMEOPTION_ORIGINAL_SAVELOAD)
},
},
{
// Chewy - ESC from F5 - Spanish fanmade translation
{
"chewy",
nullptr,
AD_ENTRY1s("txt/atds.tap", "b1210066a524fe0f88862f44671ed97d", 226988),
Common::ES_ESP,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
GUIO2(GUIO_NOMIDI, GAMEOPTION_ORIGINAL_SAVELOAD)
},
},
{
{
"chewy",
nullptr,
AD_ENTRY1s("txt/atds.tap", "c117e884cc5b4bbe50ae1217d13916c4", 231071),
Common::DE_DEU,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
GUIO2(GUIO_NOMIDI, GAMEOPTION_ORIGINAL_SAVELOAD)
},
},
{
{
"chewy",
nullptr,
AD_ENTRY1s("txt/atds.tap", "e22f97761c0e7772ec99660f2277b1a4", 231001),
Common::DE_DEU,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
GUIO2(GUIO_NOMIDI, GAMEOPTION_ORIGINAL_SAVELOAD)
},
},
{
// Chewy - ESC von F5 - German demo
// Demo version 1.1 (CHEWY.EXE - offset 0x8A520)
// From Blue Byte News Version III/97
// The source CD-ROM has the Matrix code SONOPRESS T-2037 A
// CD-ROM has the label "DEMO"
{
"chewy",
nullptr,
AD_ENTRY1s("txt/atds.tap", "c3be5641e90dd01274309b778cf8146d", 230686),
Common::DE_DEU,
Common::kPlatformDOS,
ADGF_DEMO | ADGF_UNSUPPORTED,
GUIO2(GUIO_NOMIDI, GAMEOPTION_ORIGINAL_SAVELOAD)
},
},
{ AD_TABLE_END_MARKER }
};
} // namespace Chewy
class ChewyMetaEngineDetection : public AdvancedMetaEngineDetection<Chewy::ChewyGameDescription> {
public:
ChewyMetaEngineDetection() : AdvancedMetaEngineDetection(Chewy::gameDescriptions, chewyGames) {
_maxScanDepth = 2;
_flags = kADFlagMatchFullPaths;
}
const char *getName() const override {
return "chewy";
}
const char *getEngineName() const override {
return "Chewy: Esc from F5";
}
const char *getOriginalCopyright() const override {
return "Chewy: Esc from F5 (C) 1995 New Generation Software";
}
};
REGISTER_PLUGIN_STATIC(CHEWY_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, ChewyMetaEngineDetection);

37
engines/chewy/detection.h Normal file
View File

@@ -0,0 +1,37 @@
/* 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/>.
*
*/
#ifndef CHEWY_DETECTION_H
#define CHEWY_DETECTION_H
namespace Chewy {
struct ChewyGameDescription {
AD_GAME_DESCRIPTION_HELPERS(desc);
ADGameDescription desc;
};
#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS1
} // End of namespace Chewy
#endif

View File

@@ -0,0 +1,196 @@
/* 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/>.
*
*/
#include "chewy/dialogs/cinema.h"
#include "chewy/cursor.h"
#include "chewy/events.h"
#include "chewy/font.h"
#include "chewy/globals.h"
#include "chewy/main.h"
#include "chewy/mcga_graphics.h"
#include "chewy/sound.h"
namespace Chewy {
namespace Dialogs {
static constexpr int CINEMA_LINES = 12;
static const uint8 CINEMA_FLICS[35] = {
FCUT_000, FCUT_002, FCUT_006, FCUT_009, FCUT_015,
FCUT_012, FCUT_011, FCUT_SPACECHASE_18, FCUT_003, FCUT_048,
FCUT_031, FCUT_044, FCUT_055, FCUT_058, FCUT_045,
FCUT_065, FCUT_067, FCUT_068, FCUT_069, FCUT_080,
FCUT_074, FCUT_083, FCUT_084, FCUT_088, FCUT_093,
FCUT_087, FCUT_106, FCUT_108, FCUT_107, FCUT_113,
FCUT_110, FCUT_121, FCUT_123, FCUT_122, FCUT_117
};
void Cinema::execute() {
int topIndex = 0;
int selected = 0;
bool flag = true;
int delay = 0;
Common::Array<int> cutscenes;
Common::String cutsceneName;
getCutscenes(cutscenes);
_G(fontMgr)->setFont(_G(font6));
_G(room)->load_tgp(4, &_G(room_blk), 1, false, GBOOK);
showCur();
EVENTS_CLEAR;
g_events->_kbInfo._scanCode = 0;
for (bool endLoop = false; !endLoop;) {
_G(out)->setPointer(_G(workptr));
_G(out)->map_spr2screen(_G(ablage)[_G(room_blk).AkAblage], 0, 0);
if (!cutscenes.empty()) {
// Render cut-scene list
for (int i = 0; i < CINEMA_LINES; ++i) {
if ((topIndex + i) >= (int)cutscenes.size())
continue;
cutsceneName = _G(atds)->getTextEntry(98,
546 + cutscenes[topIndex + i] - 1, ATS_DATA);
int yp = i * 10 + 68;
if (i == selected)
_G(out)->boxFill(37, yp, 308, yp + 10, 42);
_G(out)->printxy(40, yp, 14, 300, 0, cutsceneName.c_str());
}
} else {
// No cut-scene seen yet
cutsceneName = _G(atds)->getTextEntry(98, 545, ATS_DATA);
_G(out)->printxy(40, 68, 14, 300, _G(scr_width), cutsceneName.c_str());
}
if (_G(minfo).button == 1 && !flag) {
flag = true;
switch (_G(out)->findHotspot(_G(cinematicsHotspots))) {
case 0:
g_events->_kbInfo._scanCode = Common::KEYCODE_UP;
break;
case 1:
g_events->_kbInfo._scanCode = Common::KEYCODE_DOWN;
break;
case 2: {
int selLine = (g_events->_mousePos.y - 68) / 10;
int selIndex = topIndex + selLine;
if (selIndex < (int)cutscenes.size()) {
selected = selLine;
g_events->_kbInfo._scanCode = Common::KEYCODE_RETURN;
}
break;
}
default:
break;
}
} else if (_G(minfo).button == 2 && !flag) {
g_events->_kbInfo._scanCode = Common::KEYCODE_ESCAPE;
flag = true;
} else if (_G(minfo).button != 1) {
delay = 0;
} else if (flag) {
g_events->update();
if (--delay <= 0)
flag = false;
}
switch (g_events->_kbInfo._scanCode) {
case Common::KEYCODE_ESCAPE:
endLoop = true;
g_events->_kbInfo._scanCode = 0;
break;
case Common::KEYCODE_UP:
case Common::KEYCODE_KP8:
if (selected > 0) {
--selected;
} else if (topIndex > 0) {
--topIndex;
}
g_events->_kbInfo._scanCode = 0;
break;
case Common::KEYCODE_DOWN:
case Common::KEYCODE_KP2:
{
int newIndex = selected + 1;
if (selected >= 11) {
if ((topIndex + newIndex) < (int)cutscenes.size())
++topIndex;
} else {
if ((topIndex + newIndex) < (int)cutscenes.size())
++selected;
}
g_events->_kbInfo._scanCode = 0;
break;
}
case Common::KEYCODE_RETURN:
hideCur();
_G(out)->cls();
_G(out)->setPointer((byte *)g_screen->getPixels());
_G(fx)->blende1(_G(workptr), _G(pal), 0, 0);
flic_cut(CINEMA_FLICS[cutscenes[topIndex + selected] - 1]);
_G(fontMgr)->setFont(_G(font6));
showCur();
delay = 0;
flag = false;
break;
default:
break;
}
// The below are hacks to get the dialog to work in ScummVM
g_events->_kbInfo._scanCode = 0;
_G(minfo).button = 0;
_G(cur)->updateCursor();
if (flag) {
flag = false;
_G(out)->setPointer((byte *)g_screen->getPixels());
_G(room)->set_ak_pal(&_G(room_blk));
_G(fx)->blende1(_G(workptr), _G(pal), 0, 0);
} else {
_G(out)->copyToScreen();
}
g_events->update();
SHOULD_QUIT_RETURN;
}
_G(room)->set_ak_pal(&_G(room_blk));
hideCur();
_G(uhr)->resetTimer(0, 5);
}
} // namespace Dialogs
} // namespace Chewy

View File

@@ -0,0 +1,38 @@
/* 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/>.
*
*/
#ifndef CHEWY_DIALOGS_CINEMA_H
#define CHEWY_DIALOGS_CINEMA_H
#include "common/scummsys.h"
namespace Chewy {
namespace Dialogs {
class Cinema {
public:
static void execute();
};
} // namespace Dialogs
} // namespace Chewy
#endif

View File

@@ -0,0 +1,271 @@
/* 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/>.
*
*/
#include "chewy/dialogs/credits.h"
#include "chewy/events.h"
#include "chewy/font.h"
#include "chewy/globals.h"
#include "chewy/mcga_graphics.h"
#include "chewy/text.h"
namespace Chewy {
namespace Dialogs {
static const int16 CREDITS_POS[65][2] = {
{40, 160}, {80, 170}, {40, 190}, {80, 200}, {80, 210},
{40, 230}, {80, 240}, {80, 250}, {80, 260}, {40, 280},
{80, 290}, {80, 300}, {80, 310}, {80, 320}, {40, 340},
{80, 350}, {80, 360}, {40, 380}, {80, 390}, {40, 410},
{80, 420}, {40, 440}, {80, 450}, {40, 470}, {80, 480},
{80, 490}, {80, 500}, {80, 510}, {80, 520}, {40, 540},
{80, 550}, {80, 560}, {80, 570}, {80, 580}, {40, 600},
{80, 610}, {80, 620}, {80, 630}, {80, 640}, {80, 650},
{80, 660}, {80, 670}, {80, 680}, {80, 690}, {80, 700},
{80, 710}, {80, 720}, {80, 730}, {80, 740}, {80, 750},
{80, 760}, {40, 780}, {40, 790}, {40, 800}, {40, 810},
{40, 820}, {40, 840}, {80, 850}, {40, 870}, {80, 880},
{80, 890}, {80, 910}, {80, 920}, {80, 930}, {80, 940}
};
static const bool CREDITS_TYPE[65] = {
true, false, true, false, false, true, false, false, false, true,
false, false, false, false, true, false, false, true, false, true,
false, true, false, true, false, false, false, false, false, true,
false, false, false, false, true, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false,
false, true, true, true, true, true, true, false, true, false,
false, true, true, true, true
};
static const char *CREDITS_TEXT_EN[65] = {
"Idea & Story:",
"Carsten Wieland",
"Programming:",
"Helmut Theuerkauf",
"Alexander Diessner",
"Graphics & Animation:",
"Carsten Wieland",
"Nihat Keesen",
"Stefan Frank",
"Text & Dialogues:",
"Helmut Theuerkauf",
"Alexander Diessner",
"Carsten Wieland",
"Wolfgang Walk",
"Music:",
"Carsten Wieland",
"Stelter Studios",
"Sound FX:",
"Helmut Theuerkauf",
"Producer & Lecturer:",
"Wolfgang Walk",
"Minister of financial affairs:",
"Carsten (Dagobert) Korte",
"Testers:",
"Lutz Rafflenbeul",
"Thomas Friedmann",
"Bernhard Ewers",
"Christian von der Hotline",
"Carsten Korte",
"The voices:",
"Chewy......Renier Baaken",
"Howard.....Wolfgang Walk",
"Nichelle...Indhira Mohammed",
"Clint......Alexander Schottky",
"Also cast:",
"Renier Baaken",
"Guido B\x94sherz",
"Gerhard Fehn",
"Alice Krause",
"Reinhard Lie\xE1",
"Willi Meyer",
"Nicole Meister",
"Lutz Rafflenbeul",
"Alexander Schottky",
"Bernd Schulze",
"Susanne Simenec",
"Helmut Theuerkauf",
"Andreas Vogelpoth",
"Mark Wagener",
"Wolfgang Walk",
"Thomas Piet Wiesenm\x81ller",
"Speech recorded by",
"tmp Studio, Moers by Willi Meyer",
"Cut by Hartmut Stelter",
"Studios Hamburg and",
"Carsten Wieland",
"Soundsystem:",
"AIL (c) Miles Design",
"Adventure Engine:",
"I.C.M. developed by",
"New Generation Software",
"Song Boo Boo Ba Baby composed",
"by Haiko Ruttmann,",
"Lyrics Wolfgang Walk,",
"featuring Indhira Mohammed."
};
static const char *CREDITS_TEXT_DE[65] = {
"Idee & Story:",
"Carsten Wieland",
"Programmierung:",
"Helmut Theuerkauf",
"Alexander Diessner",
"Grafiken & Animationen:",
"Carsten Wieland",
"Nihat Keesen",
"Stefan Frank",
"Text & Dialoge:",
"Helmut Theuerkauf",
"Alexander Diessner",
"Carsten Wieland",
"Wolfgang Walk",
"Musik:",
"Carsten Wieland",
"Stelter Studios",
"Soundeffekte:",
"Helmut Theuerkauf",
"Produzent & Lektor:",
"Wolfgang Walk",
"Minister f\x81r Finanzen",
"Carsten (Dagobert) Korte",
"Tester:",
"Lutz Rafflenbeul",
"Thomas Friedmann",
"Bernhard Ewers",
"Christian von der Hotline",
"Carsten Korte",
"Die Stimmen:",
"Chewy......Renier Baaken",
"Howard.....Wolfgang Walk",
"Nichelle...Indhira Mohammed",
"Clint......Alexander Schottky",
"In weiteren Rollen:",
"Renier Baaken",
"Guido B\x94sherz",
"Gerhard Fehn",
"Alice Krause",
"Reinhard Lie\xE1",
"Willi Meyer",
"Nicole Meister",
"Lutz Rafflenbeul",
"Alexander Schottky",
"Bernd Schulze",
"Susanne Simenec",
"Helmut Theuerkauf",
"Andreas Vogelpoth",
"Mark Wagener",
"Wolfgang Walk",
"Thomas Piet Wiesenm\x81ller",
"Die Sprache wurde aufgenommen",
"im tmp Studio, Moers von Willi Meyer",
"Nachbearbeitung in den Hartmut Stelter",
"Studios Hamburg und",
"Carsten Wieland",
"Soundsystem:",
"AIL (c) Miles Design",
"Adventure Engine:",
"I.C.M. entwickelt von",
"New Generation Software",
"Song Boo Boo Ba Baby komponiert",
"von Haiko Ruttmann,",
"Text Wolfgang Walk,",
"Gesang Indhira Mohammed."
};
void Credits::execute() {
int lineScrolled = 0;
int fontCol;
_G(room)->load_tgp(5, &_G(room_blk), 1, false, GBOOK);
_G(gameState).scrollx = 0;
_G(gameState).scrolly = 0;
_G(out)->setPointer((byte *)g_screen->getPixels());
_G(room)->set_ak_pal(&_G(room_blk));
_G(fx)->blende1(_G(workptr), _G(pal), 0, 0);
for (int16 i = 0; i < 6; ++i) {
int color = 63 - (6 * i);
_G(out)->raster_col(6 - i, color, 0, 0);
_G(out)->raster_col(7 + i, color, 0, 0);
color = 63 - (4 * i);
_G(out)->raster_col(37 - i, color, color, color);
_G(out)->raster_col(38 + i, color, color, color);
}
_G(gameState).DelaySpeed = 2;
for (;;) {
if (g_events->getSwitchCode() == Common::KEYCODE_ESCAPE || SHOULD_QUIT)
break;
// Display the starfield background
_G(out)->setPointer(_G(workptr));
_G(out)->map_spr2screen(_G(ablage)[_G(room_blk).AkAblage],
_G(gameState).scrollx, _G(gameState).scrolly);
// Animate moving the background
if (++_G(gameState).scrollx >= 320)
_G(gameState).scrollx = 0;
if (g_events->getSwitchCode() == Common::KEYCODE_ESCAPE)
break;
++lineScrolled;
g_events->delay(50);
bool stillScrolling = false;
for (int i = 0; i < 65; ++i) {
int destY = CREDITS_POS[i][1] - lineScrolled;
if (destY >= 160 || destY <= 40)
continue;
if (CREDITS_TYPE[i]) {
fontCol = 32;
_G(fontMgr)->setFont(_G(font6));
} else {
fontCol = 1;
_G(fontMgr)->setFont(_G(font8));
}
stillScrolling = true;
int fgCol = fontCol + (160 - destY) / 10;
_G(out)->printxy(CREDITS_POS[i][0], destY, fgCol, 300, _G(scr_width), g_engine->getLanguage() == Common::Language::DE_DEU ? CREDITS_TEXT_DE[i] : CREDITS_TEXT_EN[i]);
}
if (!stillScrolling)
break;
_G(out)->setPointer(nullptr);
_G(out)->copyToScreen();
}
_G(fontMgr)->setFont(_G(font8));
_G(room)->set_ak_pal(&_G(room_blk));
hideCur();
_G(uhr)->resetTimer(0, 5);
}
} // namespace Dialogs
} // namespace Chewy

View File

@@ -0,0 +1,36 @@
/* 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/>.
*
*/
#ifndef CHEWY_DIALOGS_CREDITS_H
#define CHEWY_DIALOGS_CREDITS_H
namespace Chewy {
namespace Dialogs {
class Credits {
public:
static void execute();
};
} // namespace Dialogs
} // namespace Chewy
#endif

View File

@@ -0,0 +1,309 @@
/* 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/>.
*
*/
#include "common/config-manager.h"
#include "chewy/dialogs/files.h"
#include "chewy/dialogs/options.h"
#include "chewy/cursor.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/mcga_graphics.h"
#include "chewy/memory.h"
namespace Chewy {
namespace Dialogs {
#define NUM_VISIBLE_SLOTS 6
enum Widget {
SCROLL_UP = 0, SCROLL_DOWN = 1, SAVE = 2, LOAD = 3,
GAME = 4, QUIT = 5, OPTIONS = 6, W7 = 7, W8 = 8
};
// Returns true if the game should exit to main menu
bool Files::execute(bool isInGame) {
int16 key = 0;
Common::Point pt[8];
int16 mode[9];
bool visibility[8];
bool ret = false;
bool flag = false;
if (!ConfMan.getBool("original_menus")) {
g_engine->showGmm(isInGame);
_G(flags).mainMouseFlag = false;
_G(minfo).button = 0;
const int16 roomNum = _G(gameState)._personRoomNr[P_CHEWY];
return isInGame ? false : (roomNum == 98);
}
TafInfo *ti = _G(mem)->taf_adr(OPTION_TAF);
EVENTS_CLEAR;
_G(room)->load_tgp(1, &_G(room_blk), GBOOK_TGP, false, GBOOK);
_G(out)->setPointer(_G(workptr));
_G(out)->map_spr2screen(_G(ablage)[_G(room_blk).AkAblage], 0, 0);
_G(out)->setPointer((byte *)g_screen->getPixels());
_G(room)->set_ak_pal(&_G(room_blk));
_G(fx)->blende1(_G(workptr), _G(pal), 0, 0);
_G(out)->setPointer(_G(workptr));
showCur();
pt[SCROLL_UP] = pt[SCROLL_DOWN] = Common::Point(1, 0);
for (int16 i = SAVE; i <= W7; i++)
pt[i] = Common::Point(5, 5);
Common::fill(visibility, visibility + 8, true);
Common::fill(mode, mode + 8, 0);
mode[W8] = 1;
if (!isInGame) {
visibility[SAVE] = false;
visibility[GAME] = false;
mode[LOAD] = 1;
mode[W8] = 0;
}
int16 text_off = 0; // Top visible save slot
int16 active_slot = 0; // Currently selected slot
SaveStateList saveList = g_engine->listSaves();
while (key != Common::KEYCODE_ESCAPE && !SHOULD_QUIT) {
// Draw the dialog background
_G(out)->map_spr2screen(_G(ablage)[_G(room_blk).AkAblage], 0, 0);
// Draw the buttons at the bottom
for (int16 i = 28, j = SCROLL_UP; j <= OPTIONS; i++, j++) {
if (visibility[j]) {
if (!mode[j])
// Not pressed
_G(out)->spriteSet(
ti->image[i], 16 + ti->correction[i << 1] + pt[j].x,
76 + ti->correction[(i << 1) + 1] + pt[j].y, 0);
else
// Pressed
_G(out)->spriteSet(ti->image[i], 16 + ti->correction[i << 1],
76 + ti->correction[(i << 1) + 1], 0);
}
}
// Write the list of savegame slots
for (int16 i = 0; i < NUM_VISIBLE_SLOTS; i++) {
if (i + text_off >= (int16) saveList.size())
break;
// TODO: This implementation disallows gaps in the save list
if (saveList[i + text_off].getSaveSlot() != i + text_off)
continue;
Common::String slot = Common::String::format("%2d.", text_off + i);
Common::String saveName = saveList[i + text_off].getDescription();
if (i != active_slot) {
_G(out)->printxy(40, 68 + (i * 10), 14, 300, 0, slot.c_str());
_G(out)->printxy(70, 68 + (i * 10), 14, 300, 0, saveName.c_str());
} else {
_G(out)->boxFill(40, 68 + (i * 10), 308, 68 + 8 + (i * 10), 42);
_G(out)->printxy(40, 68 + (i * 10), 255, 300, 0, slot.c_str());
_G(out)->printxy(70, 68 + (i * 10), 255, 300, 0, saveName.c_str());
}
}
key = g_events->getSwitchCode();
if (mode[SCROLL_UP])
--mode[SCROLL_UP];
if (mode[SCROLL_DOWN])
--mode[SCROLL_DOWN];
if (mode[GAME])
--mode[GAME];
if (mode[GAME] == 1)
key = Common::KEYCODE_ESCAPE;
if (mode[QUIT])
--mode[QUIT];
if (mode[QUIT] == 1) {
_G(out)->printxy(120, 138, 255, 300, 0, g_engine->getLanguage() == Common::Language::DE_DEU ? QUIT_MSG_DE : QUIT_MSG_EN);
_G(out)->copyToScreen();
key = getch();
if (key == 'j' || key == 'J' || key == 'y' || key == 'Y' || key == 'z' || key == 'Z') {
ret = true;
key = Common::KEYCODE_ESCAPE;
} else {
key = 0;
}
}
if (mode[OPTIONS])
--mode[OPTIONS];
if (mode[OPTIONS] == 1) {
Dialogs::Options::execute(ti);
}
if (!flag && _G(minfo).button == 1) {
int16 rect = _G(out)->findHotspot(_G(fileHotspots));
flag = true;
key = 0;
switch (rect) {
case 0:
key = Common::KEYCODE_UP;
break;
case 1:
key = Common::KEYCODE_DOWN;
break;
case 2: {
int16 line = (g_events->_mousePos.y - 68) / 10;
if (line == active_slot)
key = Common::KEYCODE_RETURN;
else
active_slot = line;
if (active_slot > 5)
active_slot = 5;
if (!isInGame)
goto enter;
}
break;
case 3:
key = Common::KEYCODE_F1;
break;
case 4:
key = Common::KEYCODE_F2;
break;
case 5:
key = Common::KEYCODE_F3;
break;
case 6:
key = Common::KEYCODE_F4;
break;
case 7:
key = Common::KEYCODE_F5;
break;
default:
break;
}
} else if (flag && _G(minfo).button == 0) {
flag = false;
}
switch (key) {
case Common::KEYCODE_F1:
if (visibility[SAVE]) {
mode[LOAD] = 0;
mode[SAVE] = 1;
mode[W8] = 0;
goto enter;
}
break;
case Common::KEYCODE_F2:
mode[LOAD] = 1;
mode[SAVE] = 0;
mode[W8] = 0;
goto enter;
break;
case Common::KEYCODE_F3:
if (visibility[GAME])
mode[GAME] = 10;
break;
case Common::KEYCODE_F4:
mode[QUIT] = 10;
break;
case Common::KEYCODE_F5:
mode[OPTIONS] = 10;
break;
case Common::KEYCODE_UP:
mode[SCROLL_UP] = 10;
if (active_slot > 0)
--active_slot;
else if (text_off > 0)
--text_off;
break;
case Common::KEYCODE_DOWN:
mode[SCROLL_DOWN] = 10;
if (active_slot < (NUM_VISIBLE_SLOTS - 1))
++active_slot;
else if (text_off < (999 - NUM_VISIBLE_SLOTS))
++text_off;
break;
case Common::KEYCODE_RETURN:
case Common::KEYCODE_RETURN + ALT:
enter:
if (mode[LOAD]) {
const int16 slotNum = text_off + active_slot;
for (uint j = 0; j < saveList.size(); ++j) {
if (saveList[j].getSaveSlot() == slotNum) {
_G(cur)->hideCursor();
g_engine->loadGameState(slotNum);
key = Common::KEYCODE_ESCAPE;
break;
}
}
} else if (mode[SAVE]) {
_G(out)->copyToScreen();
_G(out)->setPointer((byte *)g_screen->getPixels());
char slotName[81];
slotName[0] = '\0';
key = _G(out)->scanxy(70, 68 + (active_slot * 10),
255, 42, 14, 0, "%36s36", slotName);
_G(out)->setPointer(_G(workptr));
if (key != Common::KEYCODE_ESCAPE) {
g_engine->saveGameState(text_off + active_slot, slotName);
saveList = g_engine->listSaves();
}
key = Common::KEYCODE_ESCAPE;
}
break;
default:
break;
}
_G(cur)->updateCursor();
_G(out)->copyToScreen();
EVENTS_UPDATE;
}
free(ti);
_G(room)->load_tgp(_G(gameState)._personRoomNr[P_CHEWY], &_G(room_blk), EPISODE1_TGP, true, EPISODE1);
_G(fx_blend) = BLEND1;
_G(room)->set_ak_pal(&_G(room_blk));
return ret;
}
} // namespace Dialogs
} // namespace Chewy

View File

@@ -0,0 +1,44 @@
/* 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/>.
*
*/
#ifndef CHEWY_DIALOGS_FILES_H
#define CHEWY_DIALOGS_FILES_H
#include "common/scummsys.h"
namespace Chewy {
namespace Dialogs {
class Files {
public:
/**
* Shows the file dialog
* @param isInGame True when called in-game,
* false when called from the main menu
* @returns Returns true if quit was selected
*/
static bool execute(bool isInGame);
};
} // namespace Dialogs
} // namespace Chewy
#endif

View File

@@ -0,0 +1,725 @@
/* 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/>.
*
*/
#include "chewy/dialogs/inventory.h"
#include "chewy/rooms/room44.h"
#include "chewy/rooms/room58.h"
#include "chewy/cursor.h"
#include "chewy/events.h"
#include "chewy/font.h"
#include "chewy/globals.h"
#include "chewy/menus.h"
#include "chewy/sound.h"
namespace Chewy {
namespace Dialogs {
int16 Inventory::inv_rand_x;
int16 Inventory::inv_rand_y;
void Inventory::plot_menu() {
_G(out)->setPointer(_G(workptr));
buildMenu(WIN_INVENTORY);
// Draw inventory slots grid
for (int16 j = 0; j < 3; j++) {
for (int16 i = 0; i < 5; i++) {
_G(out)->boxFill(
WIN_INF_X + 14 + i * 54,
WIN_INF_Y + 6 + 30 + j * 32,
WIN_INF_X + 14 + i * 54 + 40,
WIN_INF_Y + 6 + 30 + j * 32 + 24,
12
);
}
}
int16 y;
int16 hotspotId = _G(out)->findHotspot(_G(inventoryHotspots));
// Highlight hotspots
if (hotspotId != -1) {
if (hotspotId < 5) {
_G(out)->boxFill(
_G(inventoryHotspots)[hotspotId].left,
_G(inventoryHotspots)[hotspotId].top,
_G(inventoryHotspots)[hotspotId].right + 1,
_G(inventoryHotspots)[hotspotId].bottom + 5,
41
);
} else {
const int16 x = (g_events->_mousePos.x - (WIN_INF_X)) / 54;
y = (g_events->_mousePos.y - (WIN_INF_Y + 4 + 30)) / 30;
hotspotId = x + (y * 5);
hotspotId += _G(gameState).InventY * 5;
if (hotspotId < (_G(gameState).InventY + 3) * 5) {
_G(out)->boxFill(
WIN_INF_X + 14 + x * 54,
WIN_INF_Y + 6 + 30 + y * 32,
WIN_INF_X + 14 + x * 54 + 40,
WIN_INF_Y + 6 + 30 + y * 32 + 24,
41
);
}
}
}
if (inv_rand_x != -1) {
_G(out)->boxFill(
WIN_INF_X + 14 + inv_rand_x * 54,
WIN_INF_Y + 6 + 30 + inv_rand_y * 32,
WIN_INF_X + 14 + inv_rand_x * 54 + 40,
WIN_INF_Y + 6 + 30 + inv_rand_y * 32 + 24,
41
);
_G(out)->box(
WIN_INF_X + 14 + inv_rand_x * 54 - 1,
WIN_INF_Y + 6 + 30 + inv_rand_y * 32 - 1,
WIN_INF_X + 14 + inv_rand_x * 54 + 40 + 1,
WIN_INF_Y + 6 + 30 + inv_rand_y * 32 + 24 + 1,
14
);
}
const int16 ANI_INVENT_END[3] = {7, 16, 24};
// Draw inventory action icons (look and use, to the left of the dialog)
for (int16 i = 0; i < 2; i++) {
_G(ani_invent_delay)[i][0] -= 1;
if (_G(ani_invent_delay)[i][0] <= 0) {
_G(ani_invent_delay)[i][0] = _G(ani_invent_delay)[i][1];
++_G(ani_count)[i];
if (_G(ani_count)[i] > ANI_INVENT_END[i]) {
_G(ani_count)[i] = _G(ani_invent_anf)[i];
_G(ani_invent_delay)[i][0] = 30000;
}
}
y = (i == 2) ? 3 : 0;
_G(out)->spriteSet(
_G(cur)->getCursorSprite(_G(ani_count)[i]),
WIN_INF_X + 8 + i * 32,
WIN_INF_Y + 12 - y,
_G(scr_width),
_G(cur)->getCursorWidth(_G(ani_count)[i]),
_G(cur)->getCursorHeight(_G(ani_count)[i])
);
}
// Draw inventory arrows (up and down, to the right of the dialog)
for (int16 i = 0; i < 2; i++) {
_G(out)->spriteSet(
_G(menutaf)->image[ARROW_UP + i],
WIN_INF_X + 200 + i * 40,
WIN_INF_Y + 12,
_G(scr_width)
);
}
y = WIN_INF_Y + 6 + 30;
// Draw inventory items
for (int16 j = 0; j < 3; j++) {
for (int16 i = 0; i < 5; i++) {
const int slot = (_G(gameState).InventY + j) * 5 + i;
const int16 invSlot = _G(gameState).InventSlot[slot];
if (invSlot != -1) {
const int16 *xy = (const int16 *)_G(inv_spr)[invSlot];
const int16 x1 = (40 - xy[0]) / 2;
const int16 y1 = (24 - xy[1]) / 2;
_G(out)->spriteSet(
_G(inv_spr)[invSlot],
x1 + WIN_INF_X + 14 + i * 54,
y1 + y + 32 * j,
_G(scr_width)
);
}
}
}
// Show up arrow, if needed
if (_G(gameState).InventY) {
const char c[2] = { 24, 0 };
_G(out)->printxy(225, 32, 19, 300, _G(scr_width), c);
}
// Show down arrow, if needed
for (int i = 5 * (_G(gameState).InventY + 3); i < 140; ++i) {
if (_G(gameState).InventSlot[i] != -1) {
const char c[2] = { 25, 0 };
_G(out)->printxy(265, 29, 19, 300, _G(scr_width), c);
break;
}
}
}
bool checkInventorykey() {
return g_events->_kbInfo._scanCode == Common::KEYCODE_RETURN ||
g_events->_kbInfo._scanCode == Common::KEYCODE_F1 ||
g_events->_kbInfo._scanCode == Common::KEYCODE_F2;
}
void Inventory::menu() {
_G(flags).InventMenu = true;
const int16 oldDispFlag = _G(gameState).DispFlag;
_G(gameState).DispFlag = false;
const uint16 oldAutoAniPlay = _G(flags).AutoAniPlay;
_G(flags).AutoAniPlay = true;
_G(flags).StopAutoObj = true;
_G(menu_display) = 0;
_G(cur)->move(152, 92);
g_events->_mousePos.x = 152;
g_events->_mousePos.y = 92;
_G(invent_cur_mode) = CUR_USE;
if (!_G(cur)->usingInventoryCursor()) {
_G(invent_cur_mode) = CUR_USE;
cursorChoice(CUR_USE);
}
int16 menu_flag1 = MENU_DISPLAY;
int16 taste_flag = 28;
_G(minfo).button = 0;
g_events->_kbInfo._keyCode = '\0';
g_events->_kbInfo._scanCode = '\0';
for (int16 i = 0; i < 3; i++) {
_G(ani_invent_delay)[i][0] = 30000;
_G(ani_count)[i] = _G(ani_invent_anf)[i];
}
int16 ret_look = -1;
bool menuFirstFl = false;
_G(show_invent_menu) = 1;
while (_G(show_invent_menu) == 1 && !SHOULD_QUIT) {
if (_G(minfo).button == 1 || checkInventorykey()) {
int16 k = _G(out)->findHotspot(_G(inventoryHotspots));
if (g_events->_kbInfo._scanCode == Common::KEYCODE_F1)
k = 0;
else if (g_events->_kbInfo._scanCode == Common::KEYCODE_F2)
k = 1;
else if (g_events->_kbInfo._scanCode == Common::KEYCODE_RETURN)
k = 5;
_G(minfo).button = 0;
g_events->_kbInfo._keyCode = '\0';
g_events->_kbInfo._scanCode = '\0';
switch (k) {
case 0:
_G(invent_cur_mode) = CUR_USE;
_G(menu_item) = CUR_USE;
if (!_G(cur)->usingInventoryCursor()) {
cursorChoice(CUR_USE);
}
break;
case 1:
if (_G(cur)->usingInventoryCursor()) {
inv_rand_x = -1;
inv_rand_y = -1;
ret_look = look(_G(cur)->getInventoryCursor(), INV_ATS_MODE, -1);
taste_flag = Common::KEYCODE_ESCAPE;
} else {
_G(invent_cur_mode) = CUR_LOOK;
_G(menu_item) = CUR_LOOK;
cursorChoice(CUR_LOOK);
}
break;
case 3:
g_events->setHotKey(Common::KEYCODE_PAGEUP);
break;
case 4:
g_events->setHotKey(Common::KEYCODE_PAGEDOWN);
break;
case 5:
inv_rand_x = (g_events->_mousePos.x - (WIN_INF_X)) / 54;
inv_rand_y = (g_events->_mousePos.y - (WIN_INF_Y + 4 + 30)) / 30;
k = inv_rand_x + (inv_rand_y * 5);
k += _G(gameState).InventY * 5;
if (_G(invent_cur_mode) == CUR_USE) {
if (!_G(cur)->usingInventoryCursor()) {
if (_G(gameState).InventSlot[k] != -1 && calc_use_invent(_G(gameState).InventSlot[k]) == false) {
_G(menu_item) = CUR_USE;
_G(cur)->setInventoryCursor(_G(gameState).InventSlot[k]);
del_invent_slot(_G(gameState).InventSlot[k]);
}
} else if (_G(gameState).InventSlot[k] != -1)
evaluateObj(_G(gameState).InventSlot[k], INVENTORY_NORMAL);
else {
_G(gameState).InventSlot[k] = _G(cur)->getInventoryCursor();
_G(obj)->sort();
_G(cur)->setInventoryCursor(-1);
_G(menu_item) = _G(invent_cur_mode);
cursorChoice(_G(invent_cur_mode));
}
} else if (_G(invent_cur_mode) == CUR_LOOK && _G(gameState).InventSlot[k] != -1 && calc_use_invent(_G(gameState).InventSlot[k]) == false) {
ret_look = look(_G(gameState).InventSlot[k], INV_ATS_MODE, -1);
cursorChoice(_G(invent_cur_mode));
taste_flag = Common::KEYCODE_ESCAPE;
}
break;
default:
break;
}
} else if (_G(minfo).button == 2 || g_events->_kbInfo._keyCode == Common::KEYCODE_ESCAPE) {
// Set virtual key
g_events->setHotKey(Common::KEYCODE_ESCAPE);
_G(minfo).button = 0;
g_events->_kbInfo._keyCode = '\0';
g_events->_kbInfo._scanCode = '\0';
}
if (ret_look == 0) {
_G(invent_cur_mode) = CUR_USE;
_G(menu_item) = CUR_USE;
if (!_G(cur)->usingInventoryCursor())
cursorChoice(CUR_USE);
} else if (ret_look == 5) {
taste_flag = false;
_G(minfo).button = 1;
}
ret_look = -1;
int16 keyCode = g_events->getSwitchCode();
// The original hid the cursor here
if (taste_flag) {
if (keyCode != taste_flag)
taste_flag = 0;
} else {
switch (keyCode) {
case Common::KEYCODE_ESCAPE:
if (!menuFirstFl) {
_G(cur)->showCursor();
while (g_events->getSwitchCode() == Common::KEYCODE_ESCAPE) {
SHOULD_QUIT_RETURN;
setupScreen(NO_SETUP);
inv_rand_x = -1;
inv_rand_y = -1;
plot_menu();
_G(cur)->updateCursor();
_G(out)->copyToScreen();
}
} else {
if (menu_flag1 != MENU_DISPLAY) {
menu_flag1 = MENU_HIDE;
_G(show_invent_menu) = false;
}
}
break;
case Common::KEYCODE_RIGHT:
if (g_events->_mousePos.x < 320 - _G(cur)->getCursorWidth())
g_events->_mousePos.x += 3;
break;
case Common::KEYCODE_LEFT:
if (g_events->_mousePos.x > 2)
g_events->_mousePos.x -= 3;
break;
case Common::KEYCODE_UP:
if (g_events->_mousePos.y > 2)
g_events->_mousePos.y -= 3;
break;
case Common::KEYCODE_DOWN:
if (g_events->_mousePos.y < 197 - _G(cur)->getCursorHeight())
g_events->_mousePos.y += 3;
break;
case Common::KEYCODE_PAGEUP:
if (_G(gameState).InventY > 0)
--_G(gameState).InventY;
g_events->_kbInfo._keyCode = '\0';
g_events->_kbInfo._scanCode = '\0';
break;
case Common::KEYCODE_PAGEDOWN:
if (_G(gameState).InventY < (MAX_MOV_OBJ / 5) - 3)
++_G(gameState).InventY;
g_events->_kbInfo._keyCode = '\0';
g_events->_kbInfo._scanCode = '\0';
break;
default:
break;
}
menuFirstFl = true;
}
if (_G(show_invent_menu) != 2) {
setupScreen(NO_SETUP);
if (menu_flag1 != MENU_HIDE) {
inv_rand_x = -1;
inv_rand_y = -1;
plot_menu();
}
if (menu_flag1 == false)
_G(cur)->updateCursor();
_G(out)->setPointer(nullptr);
if (menu_flag1 == MENU_DISPLAY) {
_G(fx)->blende1(_G(workptr), nullptr, 0, 300);
} else if (menu_flag1 == MENU_HIDE)
_G(fx)->blende1(_G(workptr), nullptr, 1, 300);
menu_flag1 = false;
_G(out)->copyToScreen();
} else {
showCur();
}
}
_G(cur)->move(_G(maus_old_x), _G(maus_old_y));
g_events->_mousePos.x = _G(maus_old_x);
g_events->_mousePos.y = _G(maus_old_y);
_G(minfo).button = 0;
while (g_events->getSwitchCode() == Common::KEYCODE_ESCAPE && !SHOULD_QUIT) {
setupScreen(NO_SETUP);
_G(cur)->updateCursor();
_G(out)->copyToScreen();
}
_G(flags).InventMenu = false;
_G(flags).AutoAniPlay = oldAutoAniPlay;
_G(gameState).DispFlag = oldDispFlag;
_G(menu_display) = _G(tmp_menu);
_G(flags).StopAutoObj = false;
}
int16 Inventory::look(int16 invent_nr, int16 mode, int16 ats_nr) {
int16 lineCount = 0;
int16 xoff = 0;
int16 yoff = 0;
int16 visibleCount = 0;
Common::String itemName;
Common::StringArray itemDesc;
char c[2] = { 0 };
int16 ret = -1;
bool endLoop = false;
int16 startLine = 0;
bool mouseFl = true;
bool firstTime = true;
if (mode == INV_ATS_MODE) {
itemName = _G(atds)->getTextEntry(invent_nr, TXT_MARK_NAME, INV_ATS_DATA);
itemDesc = _G(atds)->getTextArray(invent_nr, TXT_MARK_LOOK, INV_ATS_DATA);
lineCount = itemDesc.size();
xoff = itemName.size();
xoff *= _G(font8)->getDataWidth();
xoff = (254 - xoff) / 2;
visibleCount = 2;
yoff = 10;
} else if (mode == INV_USE_ATS_MODE) {
visibleCount = 3;
yoff = 0;
if (ats_nr >= 15000)
itemDesc = _G(atds)->getTextArray(0, ats_nr - 15000, INV_USE_DEF, -1);
else
itemDesc = _G(atds)->getTextArray(0, ats_nr, INV_USE_DATA, -1);
lineCount = itemDesc.size();
if (itemDesc.size() == 0)
endLoop = true;
} else {
endLoop = true;
}
const int16 speechId = _G(atds)->getLastSpeechId();
while (!endLoop) {
int16 rect = _G(out)->findHotspot(_G(inventoryHotspots));
if (_G(minfo).button) {
if (_G(minfo).button == 2) {
if (!mouseFl)
g_events->_kbInfo._scanCode = Common::KEYCODE_ESCAPE;
} else if (_G(minfo).button == 1) {
if (!mouseFl) {
switch (rect) {
case 0:
endLoop = true;
ret = 0;
break;
case 1:
endLoop = true;
ret = 1;
break;
case 3:
case 6:
g_events->_kbInfo._scanCode = Common::KEYCODE_UP;
break;
case 4:
case 7:
g_events->_kbInfo._scanCode = Common::KEYCODE_DOWN;
break;
case 5:
ret = 5;
endLoop = true;
break;
default:
break;
}
}
}
mouseFl = true;
} else {
mouseFl = false;
}
switch (g_events->_kbInfo._scanCode) {
case Common::KEYCODE_F1:
g_events->setHotKey(Common::KEYCODE_F1);
break;
case Common::KEYCODE_F2:
g_events->setHotKey(Common::KEYCODE_F2);
break;
case Common::KEYCODE_ESCAPE:
endLoop = true;
break;
case Common::KEYCODE_UP:
if (startLine > 0)
--startLine;
break;
case Common::KEYCODE_DOWN:
if (startLine < lineCount - visibleCount)
++startLine;
break;
default:
break;
}
g_events->_kbInfo._scanCode = Common::KEYCODE_INVALID;
setupScreen(NO_SETUP);
plot_menu();
if (mode == INV_ATS_MODE) {
_G(fontMgr)->setFont(_G(font8));
_G(out)->printxy(WIN_LOOK_X + xoff, WIN_LOOK_Y, 255, 300,
_G(scr_width), itemName.c_str());
}
_G(fontMgr)->setFont(_G(font6));
if (lineCount > visibleCount) {
if (startLine > 0) {
if (rect == 6)
_G(out)->boxFill(WIN_INF_X + 262, WIN_INF_Y + 136, WIN_INF_X + 272,
WIN_INF_Y + 136 + 14, 41);
c[0] = 24;
_G(out)->printxy(WIN_LOOK_X + 250, WIN_LOOK_Y + 4, 14, 300,
_G(scr_width), c);
}
if (startLine < lineCount - visibleCount) {
if (rect == 7)
_G(out)->boxFill(WIN_INF_X + 262, WIN_INF_Y + 156, WIN_INF_X + 272,
WIN_INF_Y + 156 + 14, 41);
c[0] = 25;
_G(out)->printxy(WIN_LOOK_X + 250, WIN_LOOK_Y + 24, 14, 300, _G(scr_width), c);
}
}
int16 k = 0;
if (itemDesc.size() > 0) {
for (int16 i = startLine; i < lineCount && i < startLine + visibleCount; i++) {
_G(out)->printxy(WIN_LOOK_X, WIN_LOOK_Y + yoff + k * 10, 14, 300,
_G(scr_width), itemDesc[i].c_str());
++k;
}
if (g_engine->_sound->speechEnabled() && speechId >= 0 && firstTime) {
g_engine->_sound->playSpeech(speechId, false);
firstTime = false;
}
}
_G(cur)->updateCursor();
_G(out)->copyToScreen();
SHOULD_QUIT_RETURN0;
}
while (g_events->getSwitchCode() == Common::KEYCODE_ESCAPE) {
setupScreen(NO_SETUP);
plot_menu();
_G(cur)->updateCursor();
_G(out)->copyToScreen();
SHOULD_QUIT_RETURN0;
}
return ret;
}
void Inventory::look_screen(int16 txt_mode, int16 txt_nr) {
int16 ok;
int16 m_mode = 0;
if (!_G(flags).AtsAction) {
if (txt_nr != -1) {
switch (txt_mode) {
case INVENTORY_NORMAL:
case INVENTORY_STATIC:
ok = true;
switch (_G(menu_item)) {
case CUR_LOOK:
m_mode = TXT_MARK_LOOK;
break;
case CUR_USE:
case CUR_USER:
case CUR_HOWARD:
case CUR_NICHELLE:
m_mode = TXT_MARK_USE;
if (_G(cur)->usingInventoryCursor())
ok = false;
break;
case CUR_WALK:
m_mode = TXT_MARK_WALK;
break;
case CUR_TALK:
m_mode = TXT_MARK_TALK;
break;
default:
break;
}
if (_G(atds)->getControlBit(txt_nr, ATS_ACTION_BIT)) {
atsAction(txt_nr, m_mode, ATS_ACTION_VOR);
}
if (ok) {
startAtsWait(txt_nr, m_mode, 14, ATS_DATA);
}
if (_G(atds)->getControlBit(txt_nr, ATS_ACTION_BIT))
atsAction(txt_nr, m_mode, ATS_ACTION_NACH);
if (_G(menu_item) == CUR_USE)
_G(flags).StaticUseTxt = true;
break;
default:
break;
}
}
}
}
bool Inventory::calc_use_invent(int16 invNr) {
bool retVal = false;
if (_G(menu_item) == CUR_LOOK) {
switch (invNr) {
case ZEITUNG_INV:
Rooms::Room44::look_news();
break;
case CUTMAG_INV:
_G(show_invent_menu) = 2;
retVal = true;
Rooms::Room58::look_cut_mag(58);
break;
case SPARK_INV:
_G(show_invent_menu) = 2;
retVal = true;
save_person_rnr();
Rooms::Room58::look_cut_mag(60);
break;
case DIARY_INV:
showDiary();
retVal = true;
break;
default:
break;
}
} else if (_G(menu_item) == CUR_USE && invNr == NOTEBOOK_INV) {
int16 id = del_invent_slot(NOTEBOOK_INV);
_G(gameState).InventSlot[id] = NOTEBOOK_OPEN_INV;
_G(obj)->changeInventory(NOTEBOOK_INV, NOTEBOOK_OPEN_INV, &_G(room_blk));
retVal = true;
}
return retVal;
}
// Shows the Hermit's diary
void Inventory::showDiary() {
int16 scrollx = _G(gameState).scrollx,
scrolly = _G(gameState).scrolly;
_G(gameState).scrollx = 0;
_G(gameState).scrolly = 0;
_G(cur)->hideCursor();
_G(room)->load_tgp(DIARY_START, &_G(room_blk), GBOOK_TGP, false, GBOOK);
_G(out)->setPointer(_G(workptr));
_G(out)->map_spr2screen(_G(ablage)[_G(room_blk).AkAblage], _G(gameState).scrollx, _G(gameState).scrolly);
_G(out)->copyToScreen();
_G(room)->set_ak_pal(&_G(room_blk));
_G(out)->setPointer(nullptr);
_G(fx)->blende1(_G(workptr), _G(pal), 0, 0);
while (g_events->getSwitchCode() != Common::KEYCODE_ESCAPE) {
g_events->update();
SHOULD_QUIT_RETURN;
}
_G(room)->load_tgp(_G(gameState)._personRoomNr[P_CHEWY], &_G(room_blk), EPISODE1_TGP, true, EPISODE1);
_G(gameState).scrollx = scrollx;
_G(gameState).scrolly = scrolly;
setupScreen(NO_SETUP);
plot_menu();
_G(out)->setPointer(nullptr);
_G(room)->set_ak_pal(&_G(room_blk));
_G(fx)->blende1(_G(workptr), _G(pal), 0, 0);
_G(cur)->showCursor();
}
} // namespace Dialogs
} // namespace Chewy

View File

@@ -0,0 +1,47 @@
/* 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/>.
*
*/
#ifndef CHEWY_DIALOGS_INVENTORY_H
#define CHEWY_DIALOGS_INVENTORY_H
#include "chewy/ngstypes.h"
namespace Chewy {
namespace Dialogs {
class Inventory {
private:
static int16 inv_rand_x;
static int16 inv_rand_y;
static bool calc_use_invent(int16 invNr);
static void showDiary();
public:
static void plot_menu();
static void menu();
static int16 look(int16 invent_nr, int16 mode, int16 ats_nr);
static void look_screen(int16 txt_mode, int16 txt_nr);
};
} // namespace Dialogs
} // namespace Chewy
#endif

View File

@@ -0,0 +1,257 @@
/* 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/>.
*
*/
#include "common/config-manager.h"
#include "chewy/dialogs/main_menu.h"
#include "chewy/dialogs/cinema.h"
#include "chewy/dialogs/credits.h"
#include "chewy/dialogs/files.h"
#include "chewy/cursor.h"
#include "chewy/events.h"
#include "chewy/font.h"
#include "chewy/globals.h"
#include "chewy/main.h"
#include "chewy/mcga_graphics.h"
#include "chewy/sound.h"
namespace Chewy {
namespace Dialogs {
int MainMenu::_selection;
int MainMenu::_personAni[3];
void MainMenu::execute() {
// Convenience during testing to not keep showing title sequence
if (!ConfMan.getBool("skip_title")) {
g_engine->_sound->playMusic(17);
// NOTE: Originally, this was set to play video 200, but this actually
// jumped to the very last video in the file, so we play it explicitly
flic_cut(g_engine->getLanguage() == Common::Language::DE_DEU ? FCUT_155 : FCUT_160);
g_engine->_sound->stopMusic();
}
show_intro();
_G(cur)->move(152, 92);
g_events->_mousePos.x = 152;
g_events->_mousePos.y = 92;
_G(cur)->setInventoryCursor(-1);
_G(menu_display) = 0;
bool done = false;
while (!done && !SHOULD_QUIT) {
g_engine->_sound->stopAllSounds();
_G(SetUpScreenFunc) = screenFunc;
cursorChoice(CUR_POINT);
_selection = -1;
_G(gameState).scrollx = _G(gameState).scrolly = 0;
_G(gameState)._personRoomNr[P_CHEWY] = 98;
_G(room)->loadRoom(&_G(room_blk), 98, &_G(gameState));
g_engine->_sound->playRoomMusic(98);
_G(fx)->border(_G(workpage), 0, 0);
_G(out)->setPalette(_G(pal));
_G(gameState)._personHide[P_CHEWY] = true;
showCur();
// Wait for a selection to be made on the main menu
do {
animate();
if (SHOULD_QUIT)
return;
} while (_selection == -1);
switch (_selection) {
case MM_START_GAME:
EVENTS_CLEAR;
startGame();
playGame();
break;
case MM_VIEW_INTRO:
_G(fx)->border(_G(workpage), 0, 0);
_G(out)->setPointer(_G(workptr));
_G(flags).NoPalAfterFlc = true;
flic_cut(FCUT_135);
break;
case MM_LOAD_GAME:
if (loadGame())
playGame();
break;
case MM_CINEMA:
cursorChoice(CUR_SAVE);
_G(cur)->move(152, 92);
g_events->_mousePos.x = 152;
g_events->_mousePos.y = 92;
Dialogs::Cinema::execute();
break;
case MM_QUIT:
_G(out)->setPointer(nullptr);
_G(out)->cls();
done = true;
break;
case MM_CREDITS:
_G(fx)->border(_G(workpage), 0, 0);
_G(flags).NoPalAfterFlc = true;
flic_cut(FCUT_159);
_G(fx)->border(_G(workpage), 0, 0);
Dialogs::Credits::execute();
break;
default:
break;
}
}
}
void MainMenu::screenFunc() {
int vec = _G(det)->maus_vector(g_events->_mousePos.x + _G(gameState).scrollx, g_events->_mousePos.y + _G(gameState).scrolly);
if (g_events->getSwitchCode() == 28 || _G(minfo).button == 1) {
_selection = vec;
}
}
void MainMenu::animate() {
if (_G(ani_timer)->_timeFlag) {
_G(uhr)->resetTimer(0, 0);
_G(gameState).DelaySpeed = _G(FrameSpeed) / _G(gameState).FramesPerSecond;
_G(moveState)->Delay = _G(gameState).DelaySpeed + _G(spz_delay)[0];
_G(FrameSpeed) = 0;
_G(det)->set_global_delay(_G(gameState).DelaySpeed);
}
++_G(FrameSpeed);
_G(out)->setPointer(_G(workptr));
_G(out)->map_spr2screen(_G(ablage)[_G(room_blk).AkAblage],
_G(gameState).scrollx, _G(gameState).scrolly);
if (_G(SetUpScreenFunc) && !_G(menu_display) && !_G(flags).InventMenu) {
_G(SetUpScreenFunc)();
_G(out)->setPointer(_G(workptr));
}
spriteEngine();
kb_mov(1);
calcMouseText(g_events->_mousePos.x, g_events->_mousePos.y, 1);
_G(cur)->updateCursor();
_G(mouseLeftClick) = false;
_G(out)->setPointer(nullptr);
_G(out)->copyToScreen();
g_screen->update();
g_events->update();
}
void MainMenu::startGame() {
hideCur();
animate();
exit_room(-1);
uint8 framesPerSecond = _G(gameState).FramesPerSecond;
var_init();
_G(gameState).FramesPerSecond = framesPerSecond;
_G(gameState)._personRoomNr[P_CHEWY] = 0;
_G(room)->loadRoom(&_G(room_blk), 0, &_G(gameState));
_G(moveState)[P_CHEWY].Phase = 6;
_G(moveState)[P_CHEWY].PhAnz = _G(chewy_ph_nr)[6];
setPersonPos(160, 80, P_CHEWY, P_RIGHT);
_G(fx_blend) = BLEND3;
_G(gameState)._personHide[P_CHEWY] = false;
_G(menu_item) = CUR_WALK;
cursorChoice(CUR_WALK);
enter_room(-1);
_G(auto_obj) = 0;
}
bool MainMenu::loadGame() {
_G(flags).SaveMenu = true;
savePersonAni();
_G(out)->setPointer((byte *)g_screen->getPixels());
_G(fontMgr)->setFont(_G(font6));
cursorChoice(CUR_SAVE);
_G(cur)->move(152, 92);
g_events->_mousePos.x = 152;
g_events->_mousePos.y = 92;
_G(savegameFlag) = true;
int result = Files::execute(false);
cursorChoice((_G(cur)->usingInventoryCursor() && _G(menu_item) == CUR_USE) ? 8 : 0);
restorePersonAni();
_G(flags).SaveMenu = false;
if (result == 0) {
_G(fx_blend) = BLEND1;
return true;
} else {
return false;
}
}
void MainMenu::playGame() {
// unused1 = 0;
_G(inv_disp_ok) = false;
_G(tmp_menu_item) = 0;
_G(mouseLeftClick) = false;
g_events->_kbInfo._scanCode = Common::KEYCODE_INVALID;
_G(flags).mainMouseFlag = false;
_G(flags).MainInput = true;
_G(flags).ShowAtsInvTxt = true;
_G(cur)->showCursor();
_G(moveState)[P_CHEWY].Count = 0;
_G(uhr)->resetTimer(0, 0);
while (!SHOULD_QUIT && !mainLoop(1)) {
}
_G(auto_obj) = 0;
}
void MainMenu::savePersonAni() {
for (int i = 0; i < MAX_PERSON; ++i) {
_personAni[i] = _G(PersonAni)[i];
_G(PersonAni)[i] = -1;
delete _G(PersonTaf)[i];
_G(PersonTaf)[i] = nullptr;
}
}
void MainMenu::restorePersonAni() {
for (int i = 0; i < MAX_PERSON; ++i) {
load_person_ani(_personAni[i], i);
}
}
} // namespace Dialogs
} // namespace Chewy

View File

@@ -0,0 +1,90 @@
/* 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/>.
*
*/
#ifndef CHEWY_MAIN_MENU_H
#define CHEWY_MAIN_MENU_H
#include "chewy/events.h"
namespace Chewy {
namespace Dialogs {
enum MainMenuSelection {
MM_START_GAME = 0,
MM_VIEW_INTRO = 1,
MM_LOAD_GAME = 2,
MM_CINEMA = 3,
MM_QUIT = 4,
MM_CREDITS = 5
};
class MainMenu {
private:
static int _selection;
static int _personAni[3];
/**
* Screen rendering function for the main menu
*/
static void screenFunc();
/**
* Animates the contents of the main menu,
* and checks for any option selection
*/
static void animate();
/**
* Starts a new game
*/
static void startGame();
/**
* Starts a new game
*/
static bool loadGame();
/**
* Saves the personAni array
*/
static void savePersonAni();
/**
* Restores the personAni array
*/
static void restorePersonAni();
public:
/**
* Displays the menu
*/
static void execute();
/**
* Plays the game
*/
static void playGame();
};
} // namespace Dialogs
} // namespace Chewy
#endif

View File

@@ -0,0 +1,263 @@
/* 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/>.
*
*/
#include "chewy/dialogs/options.h"
#include "chewy/cursor.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/mcga_graphics.h"
#include "chewy/sound.h"
#include "common/config-manager.h"
namespace Chewy {
namespace Dialogs {
#define SURIMY_START 0
#define SURIMY_END 7
#define SCHNULLER 8
#define SCHNULL_BAND 22
#define MUND_START 9
#define MUND_END 11
#define SCHNULL_OFF 23
#define TDISP_START 12
#define TDISP_END 13
#define TDISP_EIN 20
#define TDISP_AUS 21
#define MUSIC_OFF 24
#define MUSIC_ON1 25
#define MUSIC_ON2 26
#define EXIT 27
void Options::execute(TafInfo *ti) {
long akt_clock = 0, stop_clock = 0;
_G(room)->load_tgp(0, &_G(room_blk), GBOOK_TGP, false, GBOOK);
_G(out)->setPointer(_G(workptr));
_G(out)->map_spr2screen(_G(ablage)[_G(room_blk).AkAblage], 0, 0);
_G(out)->setPointer((byte *)g_screen->getPixels());
_G(room)->set_ak_pal(&_G(room_blk));
_G(fx)->blende1(_G(workptr), _G(pal), 0, 0);
_G(out)->setPointer(_G(workptr));
int16 key = 0;
int16 surimy_ani = SURIMY_START;
int16 mund_ani = MUND_START;
int16 mund_delay = 3;
int16 mund_count = mund_delay;
_G(FrameSpeed) = 0;
int16 delay_count = _G(gameState).DelaySpeed;
//warning("stop_clock = (clock() / CLK_TCK) + 1;");
while (key != Common::KEYCODE_ESCAPE) {
_G(out)->map_spr2screen(_G(ablage)[_G(room_blk).AkAblage], 0, 0);
++_G(FrameSpeed);
//warning("akt_clock = clock() / CLK_TCK;");
if (akt_clock >= stop_clock) {
//TmpFrame = _G(FrameSpeed);
_G(gameState).DelaySpeed = (_G(FrameSpeed) >> 1) / _G(gameState).FramesPerSecond;
_G(FrameSpeed) = 0;
//warning("stop_clock = (clock() / CLK_TCK) + 1;");
}
_G(out)->spriteSet(ti->image[surimy_ani], 18 + ti->correction[surimy_ani << 1],
8 + ti->correction[(surimy_ani << 1) + 1], 0);
short bar_off = (_G(gameState).FramesPerSecond - 6) * 16;
_G(out)->boxFill(33 + bar_off, 65, 33 + 17 + bar_off, 65 + 8, 0);
Common::String fps = Common::String::format("%d", _G(gameState).FramesPerSecond << 1);
_G(out)->printxy(36 + bar_off, 65, 255, 300, 0, fps.c_str());
if (g_engine->_sound->speechEnabled()) {
_G(out)->spriteSet(ti->image[mund_ani],
18 + ti->correction[mund_ani << 1],
8 + ti->correction[(mund_ani << 1) + 1], 0);
_G(out)->spriteSet(ti->image[SCHNULL_OFF],
18 + ti->correction[SCHNULL_OFF << 1],
8 + ti->correction[(SCHNULL_OFF << 1) + 1], 0);
} else {
_G(out)->spriteSet(ti->image[SCHNULLER],
18 + ti->correction[SCHNULLER << 1],
8 + ti->correction[(SCHNULLER << 1) + 1], 0);
_G(out)->spriteSet(ti->image[SCHNULL_BAND],
18 + ti->correction[SCHNULL_BAND << 1],
8 + ti->correction[(SCHNULL_BAND << 1) + 1], 0);
}
const int soundVolume = MAX(1, g_engine->_sound->getUserSoundVolume() * 32 / Audio::Mixer::kMaxMixerVolume);
_G(out)->pop_box(32 - 2, 104 - 12, 42 + 4, 136 + 2, 192, 183, 182);
_G(out)->printxy(32 + 3, 104 - 10, 15, 300, 0, "S");
_G(out)->boxFill(33, 136 - soundVolume, 42, 136, 15);
const int musicVolume = MAX(1, g_engine->_sound->getUserMusicVolume() * 32 / Audio::Mixer::kMaxMixerVolume);
_G(out)->pop_box(52 - 2, 104 - 12, 62 + 4, 136 + 2, 192, 183, 182);
_G(out)->printxy(52 + 3, 104 - 10, 31, 300, 0, "M");
_G(out)->boxFill(53, 136 - musicVolume, 62, 136, 31);
if (g_engine->_sound->musicEnabled()) {
_G(out)->spriteSet(ti->image[MUSIC_ON1],
18 + ti->correction[MUSIC_ON1 << 1],
8 + ti->correction[(MUSIC_ON1 << 1) + 1], 0);
_G(out)->spriteSet(ti->image[MUSIC_ON2],
18 + ti->correction[MUSIC_ON2 << 1],
8 + ti->correction[(MUSIC_ON2 << 1) + 1], 0);
} else
_G(out)->spriteSet(ti->image[MUSIC_OFF],
18 + ti->correction[MUSIC_OFF << 1],
8 + ti->correction[(MUSIC_OFF << 1) + 1], 0);
if (g_engine->_sound->soundEnabled()) {
_G(out)->spriteSet(ti->image[TDISP_START],
ti->correction[TDISP_START << 1],
ti->correction[(TDISP_START << 1) + 1], 0);
_G(out)->spriteSet(ti->image[TDISP_EIN],
18 + ti->correction[TDISP_EIN << 1],
8 + ti->correction[(TDISP_EIN << 1) + 1], 0);
} else {
_G(out)->spriteSet(ti->image[TDISP_END],
ti->correction[TDISP_END << 1],
ti->correction[(TDISP_END << 1) + 1], 0);
_G(out)->spriteSet(ti->image[TDISP_AUS],
18 + ti->correction[TDISP_AUS << 1],
8 + ti->correction[(TDISP_AUS << 1) + 1], 0);
}
_G(out)->spriteSet(ti->image[EXIT],
18 + ti->correction[EXIT << 1],
8 + ti->correction[(EXIT << 1) + 1], 0);
key = g_events->getSwitchCode();
if ((_G(minfo).button == 1) || (key == Common::KEYCODE_RETURN)) {
// TODO This line breaks screen updates. Not sure what it does
// otherwise; options screen seems to work without it.
//WAIT_TASTE_LOS
int16 rect = _G(out)->findHotspot(_G(optionHotspots));
switch (rect) {
case 0: // Hamster wheel arrow left (speed down)
if (_G(gameState).FramesPerSecond > 6)
--_G(gameState).FramesPerSecond;
break;
case 1: // Hamster wheel arrow right (speed up)
if (_G(gameState).FramesPerSecond < 10)
++_G(gameState).FramesPerSecond;
break;
case 2: // Mouth (speech/subtitles)
if (!g_engine->_sound->speechEnabled()) {
g_engine->_sound->toggleSubtitles(false);
g_engine->_sound->toggleSpeech(true);
} else {
g_engine->_sound->toggleSubtitles(true);
g_engine->_sound->toggleSpeech(false);
}
g_engine->syncSoundSettings();
break;
case 3:
case 4: // Speaker (sound)
if (g_engine->_sound->soundEnabled()) {
g_engine->_sound->toggleSound(false);
} else {
g_engine->_sound->toggleSound(true);
}
g_engine->syncSoundSettings();
break;
case 5: // Guitarist (music)
if (g_engine->_sound->musicEnabled()) {
g_engine->_sound->toggleMusic(false);
g_engine->_sound->stopMusic();
} else {
g_engine->_sound->toggleMusic(true);
g_engine->_sound->playRoomMusic(_G(gameState)._personRoomNr[P_CHEWY]);
}
g_engine->syncSoundSettings();
break;
case 6: // Door (exit)
key = Common::KEYCODE_ESCAPE;
break;
case 7: // S volume gauge
g_engine->_sound->setUserSoundVolume(MIN(32, 136 - g_events->_mousePos.y) * Audio::Mixer::kMaxMixerVolume / 32);
g_engine->syncSoundSettings();
break;
case 8: // M volume gauge
g_engine->_sound->setUserMusicVolume(MIN(32, 136 - g_events->_mousePos.y) * Audio::Mixer::kMaxMixerVolume / 32);
g_engine->syncSoundSettings();
break;
default:
break;
}
_G(minfo).button = 0;
}
switch (key) {
case Common::KEYCODE_UP:
_G(cur)->move(g_events->_mousePos.x, --g_events->_mousePos.y);
break;
case Common::KEYCODE_DOWN:
_G(cur)->move(g_events->_mousePos.x, ++g_events->_mousePos.y);
break;
case Common::KEYCODE_LEFT:
_G(cur)->move(--g_events->_mousePos.x, g_events->_mousePos.y);
break;
case Common::KEYCODE_RIGHT:
_G(cur)->move(++g_events->_mousePos.x, g_events->_mousePos.y);
break;
default:
break;
}
_G(cur)->updateCursor();
_G(out)->copyToScreen();
EVENTS_UPDATE;
SHOULD_QUIT_RETURN;
if (!delay_count) {
if (surimy_ani < SURIMY_END)
++surimy_ani;
else
surimy_ani = SURIMY_START;
if (mund_count > 0)
--mund_count;
else {
if (mund_ani < MUND_END)
++mund_ani;
else
mund_ani = MUND_START;
mund_count = mund_delay;
}
delay_count = _G(gameState).DelaySpeed;
} else
--delay_count;
}
_G(room)->load_tgp(1, &_G(room_blk), GBOOK_TGP, false, GBOOK);
_G(out)->setPointer(_G(workptr));
_G(out)->map_spr2screen(_G(ablage)[_G(room_blk).AkAblage], 0, 0);
_G(out)->setPointer((byte *)g_screen->getPixels());
_G(room)->set_ak_pal(&_G(room_blk));
_G(fx)->blende1(_G(workptr), _G(pal), 0, 0);
_G(out)->setPointer(_G(workptr));
}
} // namespace Dialogs
} // namespace Chewy

View File

@@ -0,0 +1,38 @@
/* 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/>.
*
*/
#ifndef CHEWY_DIALOGS_OPTIONS_H
#define CHEWY_DIALOGS_OPTIONS_H
#include "chewy/ngstypes.h"
namespace Chewy {
namespace Dialogs {
class Options {
public:
static void execute(TafInfo *ti);
};
} // namespace Dialogs
} // namespace Chewy
#endif

165
engines/chewy/effect.cpp Normal file
View File

@@ -0,0 +1,165 @@
/* 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/>.
*
*/
#include "chewy/effect.h"
#include "chewy/globals.h"
#include "chewy/mcga_graphics.h"
namespace Chewy {
Effect::Effect() {
}
Effect::~Effect() {
}
void Effect::rnd_blende(byte *rnd_speicher, byte *sram_speicher, byte *screen, byte *palette, int16 col) {
byte *sp = (byte *)MALLOC(8 * 8 + 4);
int16 *rnd_zeiger = (int16 *)rnd_speicher;
if (col < 256) {
for (int16 i = 0; i < 1002; i++) {
int16 x;
int16 y = (rnd_zeiger[i] / 40) * 8;
if (rnd_zeiger[i] > 39)
x = (rnd_zeiger[i] - (40 * (y / 8))) * 8;
else
x = rnd_zeiger[i] * 8;
_G(out)->boxFill(x, y, x + 8, y + 8, col);
}
_G(out)->setPalette(palette);
}
for (int16 i = 0; i < 1000; i++) {
int16 x;
int16 y = (rnd_zeiger[i] / 40) * 8;
if (rnd_zeiger[i] > 39)
x = (rnd_zeiger[i] - (40 * (y / 8))) * 8;
else
x = rnd_zeiger[i] * 8;
_G(out)->setPointer(sram_speicher);
_G(out)->spriteSave(sp, x, y, 8, 8);
_G(out)->setPointer(screen);
_G(out)->spriteSet(sp, x, y, 0);
}
free(sp);
}
void Effect::blende1(byte *memPtr, byte *palette, uint8 mode, int16 color) {
byte *screen = (byte *)g_screen->getPixels();
byte *sp = (byte *)MALLOC(8 * 8 + 4);
if (color < 256) {
for (int16 i = 0; i < 13; i++) {
int16 x, y, x1;
for (x = i; x < 39 - i; x++)
_G(out)->boxFill(x * 8, i * 8, x * 8 + 8, i * 8 + 8, color);
for (y = i; y < 24 - i; y++)
_G(out)->boxFill(x * 8, y * 8, x * 8 + 8, y * 8 + 8, color);
for (x1 = 39 - i; x1 > i; x1--)
_G(out)->boxFill(x1 * 8, y * 8, x1 * 8 + 8, y * 8 + 8, color);
for (int16 y1 = 24 - i; y1 >= i; y1--)
_G(out)->boxFill(x1 * 8, y1 * 8, x1 * 8 + 8, y1 * 8 + 8, color);
}
_G(out)->setPalette(palette);
}
switch (mode) {
case 0:
for (int16 i = 13; i >= 0; i--) {
int16 x, y, x1;
for (x = i; x < 39 - i; x++) {
_G(out)->setPointer(memPtr);
_G(out)->spriteSave(sp, x * 8, i * 8, 8, 8);
_G(out)->setPointer(screen);
_G(out)->spriteSet(sp, x * 8, i * 8, 0);
}
for (y = i; y < 24 - i; y++) {
_G(out)->setPointer(memPtr);
_G(out)->spriteSave(sp, x * 8, y * 8, 8, 8);
_G(out)->setPointer(screen);
_G(out)->spriteSet(sp, x * 8, y * 8, 0);
}
for (x1 = 39 - i; x1 > i; x1--) {
_G(out)->setPointer(memPtr);
_G(out)->spriteSave(sp, x1 * 8, y * 8, 8, 8);
_G(out)->setPointer(screen);
_G(out)->spriteSet(sp, x1 * 8, y * 8, 0);
}
for (int16 y1 = 24 - i; y1 > i; y1--) {
_G(out)->setPointer(memPtr);
_G(out)->spriteSave(sp, x1 * 8, y1 * 8, 8, 8);
_G(out)->setPointer(screen);
_G(out)->spriteSet(sp, x1 * 8, y1 * 8, 0);
}
}
break;
case 1:
for (int16 i = 0; i < 13; i++) {
int16 x, y, x1;
for (x = i; x < 39 - i; x++) {
_G(out)->setPointer(memPtr);
_G(out)->spriteSave(sp, x * 8, i * 8, 8, 8);
_G(out)->setPointer(screen);
_G(out)->spriteSet(sp, x * 8, i * 8, 0);
}
for (y = i; y < 24 - i; y++) {
_G(out)->setPointer(memPtr);
_G(out)->spriteSave(sp, x * 8, y * 8, 8, 8);
_G(out)->setPointer(screen);
_G(out)->spriteSet(sp, x * 8, y * 8, 0);
}
for (x1 = 39 - i; x1 > i; x1--) {
_G(out)->setPointer(memPtr);
_G(out)->spriteSave(sp, x1 * 8, y * 8, 8, 8);
_G(out)->setPointer(screen);
_G(out)->spriteSet(sp, x1 * 8, y * 8, 0);
}
for (int16 y1 = 24 - i; y1 > i; y1--) {
_G(out)->setPointer(memPtr);
_G(out)->spriteSave(sp, x1 * 8, y1 * 8, 8, 8);
_G(out)->setPointer(screen);
_G(out)->spriteSet(sp, x1 * 8, y1 * 8, 0);
}
}
break;
default:
break;
}
free(sp);
}
void Effect::border(byte *workpage_, uint8 mode, int16 color) {
if (mode) {
for (int i = 0, x = 0; i < 20; ++i, x += 8) {
_G(out)->setPointer(workpage_ + 4);
_G(out)->boxFill(152 - x, 0, 152 - x + 8, 200, color);
_G(out)->boxFill(x + 160, 0, x + 168, 200, color);
_G(out)->copyToScreen();
}
} else {
for (int i = 0, x = 0; i < 20; ++i, x += 8) {
_G(out)->setPointer(workpage_ + 4);
_G(out)->boxFill(x, 0, x + 8, 200, color);
_G(out)->boxFill(312 - x, 0, 31 - x + 8, 200, color);
_G(out)->copyToScreen();
}
}
}
} // namespace Chewy

53
engines/chewy/effect.h Normal file
View File

@@ -0,0 +1,53 @@
/* 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/>.
*
*/
#ifndef CHEWY_EFFECT_H
#define CHEWY_EFFECT_H
#include "common/scummsys.h"
namespace Chewy {
enum BlendMode {
BLEND_NONE = 0,
BLEND1 = 1,
BLEND2 = 2,
BLEND3 = 3,
BLEND4 = 4
};
class Effect {
public:
Effect();
~Effect();
void blende1(byte *memPtr,
byte *palette, uint8 mode, int16 color);
void border(byte *screen, uint8 mode, int16 color);
void rnd_blende(byte *rnd_speicher, byte *sram_speicher,
byte *screen, byte *palette, int16 col);
};
} // namespace Chewy
#endif

276
engines/chewy/events.cpp Normal file
View File

@@ -0,0 +1,276 @@
/* 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/>.
*
*/
#include "common/system.h"
#include "chewy/events.h"
#include "chewy/globals.h"
namespace Chewy {
EventsManager *g_events;
EventsManager::EventsManager(Graphics::Screen *screen, uint refreshRate) : _screen(screen) {
addTimer(updateScreen, refreshRate);
g_events = this;
init_timer_handler();
_kbInfo._scanCode = Common::KEYCODE_INVALID;
}
EventsManager::~EventsManager() {
g_events = nullptr;
}
void EventsManager::init_timer_handler() {
_G(timer_int) = true;
_G(timer_count) = 0;
addTimer(timer_handler, (uint32)(1000 / 18.2));
}
void EventsManager::timer_handler() {
if (!_G(timer_suspend))
++_G(timer_count);
}
void EventsManager::checkTimers() {
uint32 currTime = g_system->getMillis();
for (auto &rec : _timers) {
if (currTime >= rec._nextFrameTime) {
rec._proc();
rec._nextFrameTime = currTime + rec._interval;
}
}
}
void EventsManager::updateScreen() {
if (g_events->_screen)
g_events->_screen->update();
else
g_system->updateScreen();
}
void EventsManager::handleEvent(const Common::Event &event) {
if (event.type >= Common::EVENT_MOUSEMOVE && event.type <= Common::EVENT_MBUTTONUP)
handleMouseEvent(event);
else if (event.type == Common::EVENT_KEYUP)
handleKbdEvent(event);
}
void EventsManager::handleMouseEvent(const Common::Event &event) {
_pendingEvents.push(event);
_mousePos = event.mouse;
bool isWheelEnabled = !_G(menu_display) && !_G(flags).InventMenu &&
g_engine->canSaveAutosaveCurrently() &&
_G(menu_item) >= CUR_WALK && _G(menu_item) <= CUR_TALK;
// Different event types handling
if (event.type != Common::EVENT_MOUSEMOVE)
_G(minfo).button = 0;
switch (event.type) {
case Common::EVENT_LBUTTONUP:
_G(minfo).button = 1;
break;
case Common::EVENT_RBUTTONUP:
_G(minfo).button = 2;
break;
case Common::EVENT_WHEELUP:
// Cycle backwards through cursors
if (isWheelEnabled) {
if (--_G(menu_item) < 0)
_G(menu_item) = CUR_TALK;
cursorChoice(_G(menu_item));
}
return;
case Common::EVENT_WHEELDOWN:
// Cycle forwards through cursors
if (isWheelEnabled) {
if (++_G(menu_item) > CUR_TALK)
_G(menu_item) = CUR_WALK;
cursorChoice(_G(menu_item));
}
return;
case Common::EVENT_MBUTTONDOWN:
// Toggle between walk and look cursor
if (isWheelEnabled) {
_G(menu_item) = (_G(menu_item) == CUR_WALK) ? CUR_LOOK : CUR_WALK;
cursorChoice(_G(menu_item));
}
return;
default:
break;
}
// Set mouse position
g_events->_mousePos.x = event.mouse.x;
g_events->_mousePos.y = event.mouse.y;
}
void EventsManager::handleKbdEvent(const Common::Event &event) {
_pendingKeyEvents.push(event);
if (event.type == Common::EVENT_KEYUP) {
_kbInfo._keyCode = event.kbd.ascii;
_kbInfo._scanCode = event.kbd.keycode;
if (event.kbd.flags & Common::KBD_ALT)
_kbInfo._scanCode |= ALT;
}
}
void EventsManager::delay(size_t time) {
uint32 expiryTime = g_system->getMillis() + time;
uint32 currTime;
do {
update();
currTime = g_system->getMillis();
} while (currTime < expiryTime);
}
void EventsManager::clearEvents() {
processEvents();
_pendingEvents.clear();
_pendingKeyEvents.clear();
_kbInfo._scanCode = Common::KEYCODE_INVALID;
_kbInfo._keyCode = '\0';
_G(minfo).button = 0;
}
void EventsManager::update() {
// Brief pause to prevent 100% CPU usage
g_system->delayMillis(10);
// Check for any timers that have to be triggered
checkTimers();
// Process events
processEvents();
}
#define MOUSE_MOVE \
if (moveEvent.type != Common::EVENT_INVALID) { \
handleEvent(moveEvent); \
moveEvent.type = Common::EVENT_INVALID; \
}
void EventsManager::processEvents() {
Common::Event e;
Common::Event moveEvent;
while (g_system->getEventManager()->pollEvent(e)) {
switch (e.type) {
case Common::EVENT_QUIT:
case Common::EVENT_RETURN_TO_LAUNCHER:
return;
case Common::EVENT_KEYUP:
MOUSE_MOVE;
handleEvent(e);
break;
default:
if (e.type == Common::EVENT_MOUSEMOVE) {
// Mouse move events get cached so the engine isn't
// spammed with multiple sequential move events
moveEvent = e;
} else {
MOUSE_MOVE;
handleEvent(e);
return;
}
break;
}
}
MOUSE_MOVE;
}
#undef MOUSE_MOVE
void EventsManager::warpMouse(const Common::Point &newPos) {
_mousePos = newPos;
g_system->warpMouse(newPos.x, newPos.y);
}
int16 EventsManager::getSwitchCode() {
int16 switch_code = -1;
if (_G(minfo).button == 2)
switch_code = Common::KEYCODE_ESCAPE;
else if (_G(minfo).button == 1)
switch_code = Common::MOUSE_BUTTON_LEFT;
else if (_G(minfo).button == 4)
switch_code = Common::MOUSE_BUTTON_MIDDLE;
if (g_events->_kbInfo._keyCode != 0)
switch_code = (int16)g_events->_kbInfo._keyCode;
// Virtual key, set when an item is taken from the inventory
if (_hotkey != Common::KEYCODE_INVALID) {
switch_code = _hotkey;
_hotkey = Common::KEYCODE_INVALID;
}
//debug("Mouse button: %d, key: %d, hotkey: %d", _G(minfo).button, g_events->_kbInfo._keyCode, _hotkey);
return switch_code;
}
void delay(size_t time) {
g_events->delay(time);
}
bool kbhit() {
return g_events->_kbInfo._keyCode != 0;
}
char getch() {
if (g_events->_kbInfo._keyCode) {
char c = g_events->_kbInfo._keyCode;
g_events->_kbInfo._keyCode = 0;
g_events->_kbInfo._scanCode = 0;
return c;
}
Common::Event e;
while (!SHOULD_QUIT) {
g_system->delayMillis(10);
g_events->update();
while (!g_system->getEventManager()->pollEvent(e) && !SHOULD_QUIT) {
if (e.type == Common::EVENT_KEYUP)
return e.kbd.ascii;
}
}
return 0;
}
} // namespace Chewy

168
engines/chewy/events.h Normal file
View File

@@ -0,0 +1,168 @@
/* 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/>.
*
*/
#ifndef CHEWY_EVENTS_H
#define CHEWY_EVENTS_H
#include "common/events.h"
#include "common/queue.h"
#include "graphics/screen.h"
namespace Chewy {
struct KbdInfo {
char _keyCode = '\0';
int _scanCode = Common::KEYCODE_INVALID;
};
typedef void (*TimerProc)();
class EventsManager {
struct TimerRecord {
TimerProc _proc;
uint32 _interval;
uint32 _nextFrameTime;
TimerRecord(TimerProc proc, uint32 interval) : _proc(proc), _interval(interval), _nextFrameTime(0) {
}
};
typedef Common::List<TimerRecord> TimerList;
private:
void init_timer_handler();
static void timer_handler();
void handleMouseEvent(const Common::Event &event);
void handleKbdEvent(const Common::Event &event);
TimerList _timers;
Common::Queue<Common::Event> _pendingEvents;
Common::Queue<Common::Event> _pendingKeyEvents;
int16 _hotkey = Common::KEYCODE_INVALID;
/**
* Checks for timers' expiration
*/
void checkTimers();
/**
* Timer proc for regularly updating the screen
*/
static void updateScreen();
/**
* Adds a new timer method
* @param proc Timer method to execute
* @param interval Interval in milliseconds between calls
*/
void addTimer(TimerProc proc, uint interval) {
_timers.push_back(TimerRecord(proc, interval));
}
/**
* Process any pending events
*/
void processEvents();
/**
* Handles pending event
*/
void handleEvent(const Common::Event &event);
public:
KbdInfo _kbInfo;
Common::Point _mousePos;
bool _flag1 = false;
bool _flag2 = false;
EventsManager(Graphics::Screen *screen, uint refreshRate = 1000 / 50);
virtual ~EventsManager();
void delay(size_t time);
Graphics::Screen *_screen;
/**
* Handles doing a brief delay, checking for timer updates,
* and polling events
*/
void update();
/**
* Returns true if any unprocessed keyboard events are pending
*/
bool keyEventPending() {
processEvents();
return !_pendingKeyEvents.empty();
}
/**
* Returns true if any unprocessed event other than key events
* are pending
*/
bool eventPending() {
processEvents();
return !_pendingEvents.empty();
}
/**
* Returns the next pending unprocessed keyboard event
*/
Common::Event getPendingKeyEvent() {
processEvents();
return _pendingKeyEvents.empty() ? Common::Event() : _pendingKeyEvents.pop();
}
/**
* Returns the next event, if any
*/
Common::Event getPendingEvent() {
processEvents();
return _pendingEvents.empty() ? Common::Event() : _pendingEvents.pop();
}
/**
* Sets the mouse position
*/
void warpMouse(const Common::Point &newPos);
/**
* Clear any pending events
*/
void clearEvents();
void setHotKey(Common::KeyCode key) { _hotkey = key; }
int16 getSwitchCode();
};
extern EventsManager *g_events;
extern void delay(size_t time);
extern bool kbhit();
extern char getch();
#define EVENTS_UPDATE g_events->update()
#define EVENTS_CLEAR g_events->clearEvents()
#define ALT 0x1000
} // namespace Chewy
#endif

106
engines/chewy/font.cpp Normal file
View File

@@ -0,0 +1,106 @@
/* 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/>.
*
*/
#include "common/file.h"
#include "common/rect.h"
#include "chewy/font.h"
namespace Chewy {
ChewyFont::ChewyFont(const Common::Path &filename) {
const uint32 headerFont = MKTAG('T', 'F', 'F', '\0');
Common::File stream;
stream.open(filename);
uint32 header = stream.readUint32BE();
if (header != headerFont)
error("Invalid resource - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
stream.skip(4); // total memory
_count = stream.readUint16LE();
_first = stream.readUint16LE();
_last = stream.readUint16LE();
_deltaX = _dataWidth = stream.readUint16LE();
_dataHeight = stream.readUint16LE();
_displayWidth = _dataWidth;
_displayHeight = _dataHeight;
_fontSurface.create(_dataWidth * _count, _dataHeight, Graphics::PixelFormat::createFormatCLUT8());
int bitIndex = 7;
byte curr = stream.readByte();
for (uint n = 0; n < _count; n++) {
for (uint y = 0; y < _dataHeight; y++) {
byte *p = (byte *)_fontSurface.getBasePtr(n * _dataWidth, y);
for (uint x = n * _dataWidth; x < n * _dataWidth + _dataWidth; x++) {
*p++ = (curr & (1 << bitIndex)) ? 0 : 0xFF;
bitIndex--;
if (bitIndex < 0) {
bitIndex = 7;
curr = stream.readByte();
}
}
}
}
}
ChewyFont::~ChewyFont() {
_fontSurface.free();
}
void ChewyFont::setDisplaySize(uint16 width, uint16 height) {
_displayWidth = width;
_displayHeight = height;
}
void ChewyFont::setDeltaX(uint16 deltaX) {
_deltaX = deltaX;
}
Graphics::Surface *ChewyFont::getLine(const Common::String &texts) {
Graphics::Surface *line = new Graphics::Surface();
if (texts.size() == 0)
return line;
Common::Rect subrect(0, 0, _dataWidth, _dataHeight);
line->create(texts.size() * _deltaX, _dataHeight, Graphics::PixelFormat::createFormatCLUT8());
line->fillRect(Common::Rect(line->w, line->h), 0xFF);
for (uint i = 0; i < texts.size(); i++) {
subrect.moveTo(((byte)texts[i] - _first) * _dataWidth, 0);
line->copyRectToSurface(_fontSurface, i * (_deltaX - 2), 0, subrect);
}
return line;
}
Graphics::Surface *FontMgr::getLine(const Common::String &texts) {
return _font->getLine(texts);
}
} // namespace Chewy

69
engines/chewy/font.h Normal file
View File

@@ -0,0 +1,69 @@
/* 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/>.
*
*/
#ifndef CHEWY_FONT_H
#define CHEWY_FONT_H
#include "common/str.h"
#include "graphics/surface.h"
namespace Chewy {
class ChewyFont {
public:
ChewyFont(const Common::Path &filename);
virtual ~ChewyFont();
Graphics::Surface *getLine(const Common::String &texts);
void setDisplaySize(uint16 width, uint16 height);
void setDeltaX(uint16 deltaX);
uint16 getDataWidth() const { return _dataWidth; }
uint16 getDataHeight() const { return _dataHeight; }
uint16 getFirst() const { return _first; }
uint16 getLast() const { return _last; }
private:
uint16 _count, _first, _last;
uint16 _dataWidth, _dataHeight;
uint16 _displayWidth, _displayHeight;
uint16 _deltaX;
Graphics::Surface _fontSurface;
};
class FontMgr {
public:
FontMgr() : _font(nullptr) {};
virtual ~FontMgr() {};
Graphics::Surface *getLine(const Common::String &texts);
void setFont(ChewyFont *font) { _font = font; }
ChewyFont *getFont() { return _font; }
private:
ChewyFont *_font;
};
} // namespace Chewy
#endif

41
engines/chewy/globals.cpp Normal file
View File

@@ -0,0 +1,41 @@
/* 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/>.
*
*/
#include "chewy/globals.h"
namespace Chewy {
#define MAX_RAND_NO_USE 6
const uint8 RAND_NO_USE[MAX_RAND_NO_USE] = { 0, 1, 3, 4, 5, 6 };
Globals *g_globals = nullptr;
Globals::Globals() {
g_globals = this;
}
Globals::~Globals() {
g_globals = nullptr;
}
} // namespace Chewy

527
engines/chewy/globals.h Normal file
View File

@@ -0,0 +1,527 @@
/* 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/>.
*
*/
#ifndef CHEWY_GLOBALS_H
#define CHEWY_GLOBALS_H
#include "common/array.h"
#include "common/rect.h"
#include "chewy/chewy.h"
#include "chewy/types.h"
#include "chewy/atds.h"
#include "chewy/room.h"
#include "chewy/movclass.h"
#include "chewy/timer.h"
#include "chewy/barriers.h"
#include "chewy/text.h"
#include "chewy/object.h"
#include "chewy/effect.h"
namespace Chewy {
#define MAX_ZOBJ 60
#define MAX_RAND_NO_USE 6
#define R45_MAX_PERSON 9
extern const uint8 RAND_NO_USE[MAX_RAND_NO_USE];
class ChewyFont;
class Cursor;
class FontMgr;
class McgaGraphics;
class Memory;
class Globals {
class CurrentScreen : public Graphics::Surface {
public:
CurrentScreen() {
w = pitch = SCREEN_WIDTH;
h = SCREEN_HEIGHT;
format = Graphics::PixelFormat::createFormatCLUT8();
}
CurrentScreen &operator=(byte *p) {
setPixels(p);
return *this;
}
byte *getPixels() { return (byte *)Graphics::Surface::getPixels(); }
};
struct ZObjSort {
uint8 ObjArt;
uint8 ObjNr;
int16 ObjZ;
};
public:
Globals();
~Globals();
public:
int16 _ani_invent_anf[3] = { 38, 39, 21 };
int16 _ani_invent_delay[3][2] = {
{ 12, 12 }, { 10, 10 }, { 11, 11 }
};
int16 _ani_count[3] = { 38, 39, 21 };
int16 _timer_nr[MAX_TIMER_OBJ] = { 0 };
public:
CurrentScreen _currentScreen;
GameState _gameState;
int16 _pfeil_ani = 0;
int16 _pfeil_delay = 0;
int16 _auto_p_nr = 0;
int16 _zoom_horizont = 0;
int16 _zoom_mov_fak = 0;
int16 _auto_obj = 0;
int16 _mouseLeftClick = 0;
Common::String _calc_inv_text_str1, _calc_inv_text_str2;
bool _stopAutoMove[3] = { false };
bool _e_streifen = false;
int16 _r45_delay = 0;
int16 _r56koch_flug = 0;
int16 _r62Delay = 0;
int16 _r62TalkAni = 0;
int16 _r64TalkAni = 0;
int16 _r63ChewyAni = 0;
int16 _r63Schalter = 0;
int16 _r63RunDia = 0;
int16 _r65tmp_scrollx = 0;
int16 _r65tmp_scrolly = 0;
int16 _r65tmp_ch_x = 0;
int16 _r65tmp_ch_y = 0;
int16 _r65tmp_ho_x = 0;
int16 _r65tmp_ho_y = 0;
int16 _r68HohesC = 0;
// global.cpp
const uint8 *_chewy_ph_nr;
const uint8 *_chewy_ph;
byte *_pal = nullptr;
int16 _scr_width = 0;
BlendMode _fx_blend = BLEND_NONE;
void (*_SetUpScreenFunc)() = nullptr;
int16 _FrameSpeed = 0;
int16 _FrameSpeedTmp = 0;
byte **_ablage = nullptr;
byte *_workpage = nullptr;
byte *_workptr = nullptr;
byte *_spblende = nullptr;
char **_dialogCloseupItemPtr = nullptr;
int16 _ads_dia_nr = 0;
int16 _ads_item_nr = 0;
int16 _ads_blk_nr = 0;
int16 _ads_push = 0;
int16 _ads_tmp_dsp = 0;
int8 _menu_display = 0;
int16 _menu_lauflicht = 0;
int16 _menu_item = 0;
int16 _menu_item_vorwahl = 0;
int16 _maus_old_x = 0;
int16 _maus_old_y = 0;
int16 _inventoryNr = 0;
int16 _invent_cur_mode = 0;
byte *_inv_spr[MAX_MOV_OBJ] = { nullptr };
int16 _person_tmp_hide[MAX_PERSON] = { 0 };
int16 _person_tmp_room[MAX_PERSON] = { 0 };
int16 _talk_start_ani = -1;
int16 _talk_hide_static = -1;
bool _savegameFlag = false;
int _timer_action_ctr = 0;
AutoMov _auto_mov[MAX_AUTO_MOV];
int16 _HowardMov = 0;
TafSeqInfo *_spz_tinfo = nullptr;
int16 _SpzDelay = 0;
int16 _spz_spr_nr[MAX_SPZ_PHASEN] = { 0 };
int16 _spz_start = 0;
int16 _spz_akt_id = 0;
int16 _spz_p_nr = 0;
int16 _spz_delay[MAX_PERSON] = { 0 };
int16 _spz_count = 0;
int16 _spz_ani[MAX_PERSON] = { 0 };
int16 _AkChewyTaf = 0;
int16 _PersonAni[MAX_PERSON] = { 0 };
TafSeqInfo *_PersonTaf[MAX_PERSON] = { nullptr };
uint8 _PersonSpr[MAX_PERSON][8] = {{ 0 }};
RoomDetailInfo *_Rdi = nullptr;
StaticDetailInfo *_Sdi = nullptr;
AniDetailInfo *_Adi = nullptr;
TafInfo *_menutaf = nullptr;
TafSeqInfo *_howard_taf = nullptr;
TafInfo *_chewy = nullptr;
Barriers *_barriers = nullptr;
Text *_txt = nullptr;
Room *_room = nullptr;
Object *_obj = nullptr;
Timer *_uhr = nullptr;
Detail *_det = nullptr;
Effect *_fx = nullptr;
Atdsys *_atds = nullptr;
MovClass *_mov = nullptr;
ObjMov _moveState[MAX_PERSON];
SprInfo _spr_info[MAX_PROG_ANI];
MovInfo _spieler_mi[MAX_PERSON];
ObjMov _auto_mov_vector[MAX_OBJ_MOV];
MovInfo _auto_mov_obj[MAX_OBJ_MOV];
MovPhasen _mov_phasen[MAX_OBJ_MOV];
MovLine _mov_line[MAX_OBJ_MOV][5];
TimerBlk _ani_timer[MAX_TIMER_OBJ];
int16 _person_end_phase[MAX_PERSON] = { 0 };
int16 _ani_stand_count[MAX_PERSON] = { 0 };
bool _ani_stand_flag[MAX_PERSON] = { false };
MouseInfo _minfo;
RaumBlk _room_blk;
Flags _flags = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
byte *_tempArea = nullptr;
GotoPkt _gpkt;
bool _disableScreen = false;
int16 _r45_pinfo[R45_MAX_PERSON][4] = {
{ 0, 4, 1490, 1500 },
{ 0, 1, 180, 190 },
{ 0, 1, 40, 60 },
{ 0, 1, 40, 150 },
{ 0, 1, 40, 230 },
{ 0, 1, 40, 340 },
{ 0, 1, 49, 50 },
{ 0, 1, 5, 90 },
{ 0, 1, 7, 190 }
};
// main.cpp
bool _inv_disp_ok = 0;
int16 _txt_aus_click = 0;
int16 _txt_nummer = 0;
int16 _tmp_menu_item = 0;
int16 _cur_ausgang_flag = 0;
int16 _room_start_nr = 0;
int16 _TmpFrameSpeed = 0;
Memory *_mem = nullptr;
McgaGraphics *_out = nullptr;
Cursor *_cur = nullptr;
ChewyFont *_font6 = nullptr;
ChewyFont *_font8 = nullptr;
FontMgr *_fontMgr = nullptr;
int16 _scroll_delay = 0;
// mcga.cpp
int _spriteWidth = 0;
// mcga_graphics.cpp
int16 _gcurx = 0, _gcury = 0;
// menus.cpp
int8 _m_flip = 0;
int16 _tmp_menu = 0;
int16 _show_invent_menu = 0;
// sprite.cpp
int16 _z_count = 0;
ZObjSort _z_obj_sort[MAX_ZOBJ];
char _new_vector = false;
// timer.cpp
bool _timer_int = false;
int _timer_count = 0;
bool _timer_suspend = false;
// Hotspot rect arrays
const Common::Rect _cinematicsHotspots[4] = {
{ 10, 80, 32, 105 },
{ 10, 150, 32, 175 },
{ 36, 64, 310, 188 },
{ -1, -1, -1, -1 }
};
const Common::Rect _fileHotspots[9] = {
{ 14, 73, 32, 94 },
{ 14, 96, 32, 118 },
{ 36, 64, 310, 128 },
{ 16, 143, 76, 193 },
{ 78, 143, 130, 193 },
{ 132, 143, 178, 193 },
{ 180, 143, 228, 193 },
{ 232, 143, 310, 193 },
{ -1, -1, -1, -1 }
};
const Common::Rect _inventoryHotspots[9] = {
{ 21, 25, 51, 39 },
{ 53, 25, 83, 39 },
{ -2, -2, -2, -2 },
{ 213, 25, 243, 39 },
{ 253, 25, 283, 39 },
{ 21, 45, 283, 135 },
{ 257, 151, 307, 165 },
{ 257, 171, 307, 185 },
{ -1, -1, -1, -1 }
};
const Common::Rect _optionHotspots[10] = {
{ 18, 61, 40, 76 },
{ 112, 61, 130, 76 },
{ 82, 104, 144, 139 },
{ 164, 93, 194, 115 },
{ 198, 80, 206, 115 },
{ 210, 55, 302, 138 },
{ 126, 146, 210, 198 },
{ 22, 92, 44, 136 },
{ 50, 92, 72, 136 },
{ -1, -1, -1, -1 }
};
};
extern Globals *g_globals;
#define _G(FIELD) g_globals->_##FIELD
void cursorChoice(int16 nr);
void hideCur();
void showCur();
void alloc_buffers();
bool mainLoop(int16 mode);
void setupScreen(SetupScreenMode mode);
void kb_mov(int16 mode);
void kb_cur_action(int16 key, int16 mode);
void mouseAction();
void evaluateObj(int16 objectId, int16 txt_nr);
void swap_if_l(int16 *x1, int16 *x2);
void printShadowed(int16 x, int16 y, int16 fgCol, int16 bgCol, int16 shadowFgCol,
int16 scrWidth, const char *txtPtr);
bool autoMove(int16 movNr, int16 playerNum);
void get_user_key(int16 mode);
void clear_prog_ani();
void set_ani_screen();
void delInventory(int16 nr);
bool isCurInventory(int16 nr);
void setShadowPalette(int16 palIdx, bool setPartialPalette);
void get_scroll_off(int16 x, int16 y, int16 pic_x, int16 pic_y,
int16 *sc_x, int16 *sc_y);
void calc_scroll(int16 x, int16 y, int16 pic_x, int16 pic_y,
int16 *sc_x, int16 *sc_y);
void auto_scroll(int16 scrx, int16 scry);
int16 calc_mouse_mov_obj(int16 *auto_nr);
void check_mouse_exit(int16 x, int16 y);
void calcExit(int16 x, int16 y);
void goAutoXy(int16 x, int16 y, int16 personNum, int16 mode);
void calc_auto_go();
void disable_timer();
void enable_timer();
int16 is_mouse_person(int16 x, int16 y);
void calc_mouse_person(int16 x, int16 y);
void hide_person();
void show_person();
void save_person_rnr();
void set_person_rnr();
bool is_chewy_busy();
void standard_init();
void tidy();
void init_load();
void var_init();
void new_game();
void show_intro();
void register_cutscene(int cutsceneNum);
void getCutscenes(Common::Array<int> &cutscenes);
void init_room();
void buildMenu(int16 x, int16 y, int16 xNr, int16 yNr, int16 col, int16 mode);
void autoMenu(int16 *x, int16 *y, int16 lineNr, int16 zeilen_hoehe,
char *txt, int16 mode);
void cur_2_inventory();
void inventory_2_cur(int16 nr);
void new_invent_2_cur(int16 inv_nr);
void invent_2_slot(int16 nr);
int16 del_invent_slot(int16 nr);
void remove_inventory(int16 nr);
void getDisplayCoord(int16 *x, int16 *y, int16 nr);
void calcTxtXy(int16 *x, int16 *y, char *txtAdr, int16 txtNr);
void calcTxtXy(int16 *x, int16 *y, Common::StringArray &desc);
void handleDialogCloseupMenu();
void stopDialogCloseupDialog();
void play_scene_ani(int16 nr, int16 direction);
void timer_action(int16 t_nr);
void check_ged_action(int16 index);
void enter_room(int16 eib_nr);
void exit_room(int16 eib_nr);
void flic_cut(int16 nr);
int16 sib_event_no_inv(int16 sib_nr);
void sib_event_inv(int16 sib_nr);
uint16 exit_flip_flop(int16 ani_nr, int16 eib_nr1, int16 eib_nr2,
int16 ats_nr1, int16 ats_nr2, int16 sib_nr,
int16 spr_nr1, int16 spr_nr2, int16 flag);
void loadDialogCloseup(int16 diaNr);
void setSsiPos();
int16 atsAction(int16 txtNr, int16 txtMode, int16 MODE);
void selectDialogOption(int16 diaNr, int16 blkNr, int16 strEndNr);
void endDialogCloseup(int16 diaNr, int16 blkNr, int16 strEndNr);
void atdsStringStart(int16 diaNr, int16 strNr, int16 personNr,
int16 mode);
void useItemWithInvItem(int16 itemId);
bool calc_inv_no_use(int16 test_nr, int16 mode);
int16 calc_person_txt(int16 p_nr);
int16 calc_person_click(int16 p_nr);
void calc_person_dia(int16 p_nr);
void spriteEngine();
void calc_z_ebene();
void startAniBlock(int16 nr, const AniBlock *ab);
void startSetAILWait(int16 aniNr, int16 rep, int16 mode);
void startDetailFrame(int16 aniNr, int16 rep, int16 mode,
int16 frame);
void waitDetail(int16 detNr);
void waitShowScreen(int16 frames);
void zoom_mov_anpass(ObjMov *om, MovInfo *mi);
void calc_zoom(int16 y, int16 zoomFactorX, int16 zoomFactorY,
ObjMov *om);
bool startAtsWait(int16 txtNr, int16 txtMode, int16 col, int16 mode);
void startAadWait(int16 diaNr);
void start_aad(int16 diaNr);
void aadWait(int16 strNr);
void startDialogCloseupWait(int16 diaNr);
void start_aad(int16 diaNr, int16 ssiNr, bool continueWhenSpeechEnds = false);
void wait_auto_obj(int16 nr);
void stop_auto_obj(int16 nr);
void continue_auto_obj(int16 nr, int16 repeat);
void new_auto_line(int16 nr);
void init_auto_obj(int16 auto_nr, const int16 *phasen, int16 lines,
const MovLine *pkt);
int16 mouse_auto_obj(int16 nr, int16 xoff, int16 yoff);
int16 auto_obj_status(int16 nr);
int16 mouse_on_prog_ani();
void set_spz_delay(int16 delay);
void start_spz_wait(int16 ani_id, int16 count, bool reverse, int16 p_nr);
bool start_spz(int16 ani_id, int16 count, bool reverse, int16 p_nr);
void stop_spz();
void calc_person_spz_ani(ObjMov *om);
void setPersonPos(int16 x, int16 y, int16 personNr, int16 direction);
void setPersonSpr(int16 nr, int16 personNr);
void stopPerson(int16 personNr);
void mov_objekt(ObjMov *om, MovInfo *mi);
void calc_person_end_ani(ObjMov *om, int16 p_nr);
void get_phase(ObjMov *om, MovInfo *mi);
void get_lr_phase(ObjMov *om, int16 obj_mode);
void load_person_ani(int16 ani_id, int16 p_nr);
void calc_person_ani();
} // namespace Chewy
#endif

264
engines/chewy/inits.cpp Normal file
View File

@@ -0,0 +1,264 @@
/* 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/>.
*
*/
#include "common/config-manager.h"
#include "common/memstream.h"
#include "chewy/chewy.h"
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/globals.h"
#include "chewy/main.h"
#include "chewy/mcga_graphics.h"
#include "chewy/memory.h"
#include "chewy/sound.h"
namespace Chewy {
void standard_init() {
_G(mem) = new Memory();
_G(out) = new McgaGraphics();
_G(fx) = new Effect();
_G(txt) = new Text();
_G(barriers) = new Barriers();
_G(room) = new Room();
_G(obj) = new Object(&_G(gameState));
_G(uhr) = new Timer(MAX_TIMER_OBJ, _G(ani_timer));
_G(det) = new Detail();
_G(atds) = new Atdsys();
_G(mov) = new MovClass();
_G(out)->init();
_G(out)->cls();
_G(scr_width) = 0;
_G(cur) = new Cursor();
_G(cur)->setAnimation(0, 0, 0);
alloc_buffers();
_G(pal)[765] = 63;
_G(pal)[766] = 63;
_G(pal)[767] = 63;
_G(out)->fadeIn(_G(pal));
_G(room)->set_timer_start(1);
_G(out)->cls();
var_init();
_G(ablage) = _G(room)->get_ablage();
_G(zoom_horizont) = 140;
_G(pal)[765] = 63;
_G(pal)[766] = 63;
_G(pal)[767] = 63;
_G(out)->fadeIn(_G(pal));
_G(out)->cls();
_G(uhr)->setNewTimer(0, 5, SEC_10_MODE);
init_load();
}
void var_init() {
_G(Rdi) = _G(det)->getRoomDetailInfo();
_G(Sdi) = &_G(Rdi)->staticSprite[0];
_G(Adi) = &_G(Rdi)->Ainfo[0];
_G(auto_p_nr) = 0;
_G(menu_item) = CUR_WALK;
_G(inventoryNr) = 0;
new_game();
_G(gameState).MainMenuY = MENU_Y;
_G(gameState).DispFlag = true;
_G(cur)->setInventoryCursor(-1);
_G(gameState).ScrollxStep = 1;
_G(gameState).ScrollyStep = 1;
_G(spieler_mi)[P_CHEWY].HotX = CH_HOT_X;
_G(spieler_mi)[P_CHEWY].HotY = CH_HOT_Y;
_G(spieler_mi)[P_CHEWY].HotMovX = CH_HOT_MOV_X;
_G(spieler_mi)[P_CHEWY].HotMovY = CH_HOT_MOV_Y;
_G(spieler_mi)[P_CHEWY].Vorschub = CH_X_PIX;
_G(spieler_mi)[P_CHEWY].Id = CHEWY_OBJ;
_G(spieler_mi)[P_HOWARD].HotX = HO_HOT_X;
_G(spieler_mi)[P_HOWARD].HotY = HO_HOT_Y ;
_G(spieler_mi)[P_HOWARD].HotMovX = HO_HOT_MOV_X;
_G(spieler_mi)[P_HOWARD].HotMovY = HO_HOT_MOV_Y;
_G(spieler_mi)[P_HOWARD].Vorschub = HO_X_PIX;
_G(spieler_mi)[P_HOWARD].Id = HOWARD_OBJ;
_G(spieler_mi)[P_NICHELLE].HotX = NI_HOT_X;
_G(spieler_mi)[P_NICHELLE].HotY = NI_HOT_Y ;
_G(spieler_mi)[P_NICHELLE].HotMovX = NI_HOT_MOV_X;
_G(spieler_mi)[P_NICHELLE].HotMovY = 62;
_G(spieler_mi)[P_NICHELLE].Vorschub = NI_X_PIX;
_G(spieler_mi)[P_NICHELLE].Id = NICHELLE_OBJ;
_G(spieler_mi)[P_NICHELLE].Mode = true;
for (int16 i = 0; i < MAX_PERSON; i++) {
_G(PersonAni)[i] = -1;
_G(PersonTaf)[i] = nullptr;
_G(spieler_mi)[i].Mode = false;
_G(ani_stand_flag)[i] = false;
_G(spz_delay)[i] = 0;
_G(gameState)._personRoomNr[i] = -1;
_G(gameState).PersonDia[i] = -1;
}
_G(gameState)._personRoomNr[P_CHEWY] = _G(room_start_nr);
_G(gpkt).Vorschub = _G(spieler_mi)[P_CHEWY].Vorschub;
init_room();
_G(gameState).FramesPerSecond = 7;
_G(SetUpScreenFunc) = nullptr;
_G(pfeil_delay) = 0;
_G(pfeil_ani) = 0;
_G(timer_action_ctr) = 0;
_G(savegameFlag) = false;
}
void init_room() {
_G(room_blk).AkAblage = 0;
_G(room_blk).LowPalMem = _G(pal);
_G(room_blk).InvFile = INVENTORY_TAF;
_G(room_blk).DetFile = DETAILTEST;
_G(room_blk).InvSprAdr = &_G(inv_spr)[0];
_G(room_blk).Rmo = _G(gameState).room_m_obj;
_G(room_blk).Rsi = _G(gameState).room_s_obj;
_G(room_blk).AadLoad = true;
}
void new_game() {
_G(gameState).clear();
for (int16 i = 0; i < MAX_MOV_OBJ; i++) {
_G(gameState).room_m_obj[i].RoomNr = -1;
_G(gameState).InventSlot[i] = -1;
}
for (int16 i = 0; i < MAX_FEST_OBJ; i++)
_G(gameState).room_s_obj[i].RoomNr = -1;
for (int16 i = 0; i < MAX_EXIT; i++)
_G(gameState).room_e_obj[i].RoomNr = -1;
_G(obj)->load(INVENTORY_IIB, &_G(gameState).room_m_obj[0]);
_G(obj)->load(INVENTORY_SIB, &_G(gameState).room_s_obj[0]);
_G(obj)->load(EXIT_EIB, &_G(gameState).room_e_obj[0]);
_G(obj)->sort();
for (int16 i = 0; i < _G(obj)->spieler_invnr[0]; i++)
_G(gameState).InventSlot[i] = _G(obj)->spieler_invnr[i + 1];
_G(AkChewyTaf) = 0;
load_chewy_taf(CHEWY_NORMAL);
}
void init_load() {
_G(AkChewyTaf) = 0;
load_chewy_taf(CHEWY_NORMAL);
_G(spz_akt_id) = -1;
_G(spz_tinfo) = nullptr;
set_spz_delay(3);
_G(menutaf) = _G(mem)->taf_adr(MENUTAF);
Common::File f;
if (!f.open("cut/blende.rnd"))
error("Error reading file: cut/blende.rnd");
_G(spblende) = (byte *)MALLOC(f.size() + sizeof(uint32));
WRITE_LE_INT32(_G(spblende), f.size());
f.read(_G(spblende) + sizeof(uint32), f.size());
f.close();
_G(room)->loadRoom(&_G(room_blk), _G(room_start_nr), &_G(gameState));
_G(out)->setPalette(_G(pal));
}
void tidy() {
free_buffers();
_G(obj)->free_inv_spr(&_G(inv_spr)[0]);
delete _G(cur);
delete _G(mov);
delete _G(atds);
delete _G(det);
delete _G(uhr);
delete _G(obj);
delete _G(room);
delete _G(barriers);
delete _G(txt);
delete _G(fx);
delete _G(out);
delete _G(mem);
_G(cur) = nullptr;
_G(mov) = nullptr;
_G(atds) = nullptr;
_G(det) = nullptr;
_G(uhr) = nullptr;
_G(obj) = nullptr;
_G(room) = nullptr;
_G(barriers) = nullptr;
_G(txt) = nullptr;
_G(fx) = nullptr;
_G(out) = nullptr;
_G(mem) = nullptr;
}
void show_intro() {
if (!ConfMan.getBool("shown_intro")) {
ConfMan.setBool("shown_intro", true);
_G(flags).NoPalAfterFlc = true;
flic_cut(FCUT_135);
}
}
static const char *CUTSCENES = "cutscenes";
static const int MAX_CUTSCENES = 35;
void register_cutscene(int cutsceneNum) {
assert(cutsceneNum >= 1 && cutsceneNum <= MAX_CUTSCENES);
Common::String creditsStr;
if (ConfMan.hasKey(CUTSCENES)) {
creditsStr = ConfMan.get(CUTSCENES);
} else {
for (int i = 0; i < MAX_CUTSCENES; ++i)
creditsStr += '0';
}
creditsStr.setChar('1', cutsceneNum - 1);
ConfMan.set(CUTSCENES, creditsStr);
ConfMan.flushToDisk();
}
void getCutscenes(Common::Array<int> &cutscenes) {
cutscenes.clear();
if (!ConfMan.hasKey(CUTSCENES))
return;
Common::String cutStr = ConfMan.get(CUTSCENES);
for (int i = 0; i < MAX_CUTSCENES; ++i) {
if (cutStr[i] == '1')
cutscenes.push_back(i + 1);
}
}
} // namespace Chewy

1848
engines/chewy/main.cpp Normal file

File diff suppressed because it is too large Load Diff

43
engines/chewy/main.h Normal file
View File

@@ -0,0 +1,43 @@
/* 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/>.
*
*/
#ifndef CHEWY_MAIN_H
#define CHEWY_MAIN_H
#include "graphics/surface.h"
namespace Chewy {
void game_main();
void free_buffers();
void plotMainMenu();
void palcopy(byte *destPal, const byte *srcPal, int16 destStartIndex,
int16 srcStartIndex, int16 colorNbr);
short calcMouseText(int16 x, int16 y, int16 mode);
void calc_ani_timer();
void mous_obj_action(int16 nr, int16 mode, int16 txt_mode, int16 txt_nr);
int16 getAniDirection(int16 status);
void menuEntry();
void menuExit();
} // namespace Chewy
#endif

View File

@@ -0,0 +1,944 @@
/* 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/>.
*
*/
#include "common/memstream.h"
#include "common/system.h"
#include "graphics/palette.h"
#include "graphics/paletteman.h"
#include "chewy/chewy.h"
#include "chewy/events.h"
#include "chewy/font.h"
#include "chewy/globals.h"
#include "chewy/mcga_graphics.h"
namespace Chewy {
McgaGraphics::McgaGraphics() {
}
McgaGraphics::~McgaGraphics() {
}
void McgaGraphics::init() {
_G(currentScreen) = (byte *)g_screen->getPixels();
_G(spriteWidth) = 0;
}
void setScummVMPalette(const byte *palette, uint start, uint count) {
byte tempPal[Graphics::PALETTE_SIZE];
byte *dest = &tempPal[0];
for (uint i = 0; i < count * 3; ++i, ++palette, ++dest)
*dest = PALETTE_6BIT_TO_8BIT(*palette);
g_system->getPaletteManager()->setPalette(tempPal, start, count);
}
void McgaGraphics::setPointer(byte *ptr) {
if (ptr) {
_G(currentScreen) = ptr;
} else {
_G(currentScreen) = (byte *)g_screen->getPixels();
}
}
void McgaGraphics::setPalette(byte *palette) {
for (int16 i = 0; i < 768; i++)
_palTable[i] = palette[i];
setScummVMPalette(palette, 0, Graphics::PALETTE_COUNT);
}
void McgaGraphics::raster_col(int16 c, int16 r, int16 g, int16 b) {
_palTable[c * 3] = r;
_palTable[c * 3 + 1] = g;
_palTable[c * 3 + 2] = b;
setScummVMPalette(&_palTable[c * 3], c, 1);
}
void McgaGraphics::fadeIn(byte *palette) {
for (int16 j = 63; j >= 0; j--) {
int16 k = 0;
for (int16 i = 0; i < 256; i++) {
int16 r = palette[k];
int16 g = palette[k + 1];
int16 b = palette[k + 2];
int16 r1 = r - j;
int16 g1 = g - j;
int16 b1 = b - j;
if ((r1 > 0) && (r1 <= r))
_palTable[k] = r1;
if ((g1 > 0) && (r1 <= r))
_palTable[k + 1] = g1;
if ((b1 > 0) && (r1 <= r))
_palTable[k + 2] = b1;
k += 3;
}
setScummVMPalette(_palTable, 0, Graphics::PALETTE_COUNT);
}
}
void McgaGraphics::fadeOut() {
for (int16 j = 0; j < 64; j++) {
int16 k = 0;
for (int16 i = 0; i < 256; i++) {
int16 r = _palTable[k];
int16 g = _palTable[k + 1];
int16 b = _palTable[k + 2];
if (r > 0) --r;
if (g > 0) --g;
if (b > 0) --b;
_palTable[k] = r;
_palTable[k + 1] = g;
_palTable[k + 2] = b;
k += 3;
}
setScummVMPalette(_palTable, 0, Graphics::PALETTE_COUNT);
}
}
void McgaGraphics::set_partialpalette(const byte *palette, int16 startCol, int16 nr) {
int16 k = startCol * 3;
int16 endcol = startCol + nr;
for (int16 i = startCol; i < endcol; i++) {
_palTable[k] = palette[k];
_palTable[k + 1] = palette[k + 1];
_palTable[k + 2] = palette[k + 2];
k += 3;
}
setScummVMPalette(_palTable + startCol * 3, startCol, nr);
}
void McgaGraphics::cls() {
Common::Rect r(0, 0, _G(currentScreen).pitch, _G(currentScreen).h);
_G(currentScreen).fillRect(r, 0);
}
void McgaGraphics::drawLine(int16 x1, int16 y1, int16 x2, int16 y2, int16 color) {
_G(currentScreen).drawLine(x1, y1, x2, y2, color);
}
void McgaGraphics::box(int16 x1, int16 y1, int16 x2, int16 y2, int16 color) {
_G(currentScreen).frameRect(Common::Rect(x1, y1, x2, y2), color);
}
void McgaGraphics::boxFill(int16 x1, int16 y1, int16 x2, int16 y2, int16 color) {
if (x2 == x1)x2++;
int16 h = abs(y2 - y1);
if (h == 0)
h = 1;
for (int16 i = 0; i < h; i++)
drawLine(x1, y1 + i, x2, y1 + i, color);
}
void McgaGraphics::pop_box(int16 x, int16 y, int16 x1, int16 y1, int16 col1, int16 col2, int16 back_col) {
if (back_col < 255)
boxFill(x, y, x1, y1, back_col);
drawLine(x, y1, x1, y1, col2);
drawLine(x1, y, x1, y1, col2);
drawLine(x, y, x1, y, col1);
drawLine(x, y, x, y1 + 1, col1);
}
void McgaGraphics::copyToScreen() {
byte *destP = (byte *)g_screen->getPixels();
const byte *ptr = _G(workpage);
Common::copy(ptr + 4, ptr + 4 + (SCREEN_WIDTH * SCREEN_HEIGHT), destP);
g_screen->markAllDirty();
}
void McgaGraphics::spriteSave(byte *spritePtr, int16 x, int16 y, int16 width, int16 height) {
if (width < 4)
width = 4;
if (height <= 0)
height = 1;
if (x < 0) {
x = 0;
width -= (0 - x);
}
if ((x + width) > 320 + 1)
width = 320 - x;
if (y < 0) {
y = 0;
height -= (0 - y);
}
if ((y + height) > 200 + 1)
height = 200 - y;
if (width < 1)
width = 0;
if (height <= 0)
height = 0;
*((int16 *)spritePtr) = width;
spritePtr += 2;
*((int16 *)spritePtr) = height;
spritePtr += 2;
int pitch = SCREEN_WIDTH;
byte *scrP = _G(currentScreen).getPixels() + y * SCREEN_WIDTH + x;
if (width >= 1 && height >= 1) {
for (int row = 0; row < height; ++row) {
Common::copy(scrP, scrP + width, spritePtr);
scrP += pitch;
spritePtr += width;
}
}
}
static bool mspr_set_mcga_clip(int x, int y, int pitch, int &width, int &height, const byte *&srcP, byte *&destP) {
if (y < 0) {
int yDiff = ABS(0 - y);
height -= yDiff;
srcP += yDiff * width;
y = 0;
}
if (height < 1)
return false;
if (x < 0) {
int xDiff = ABS(0 - x);
width -= xDiff;
srcP += xDiff;
x = 0;
}
if (width < 1)
return false;
int x2 = x + width;
if (x2 > 320) {
int xDiff = x2 - 320;
width -= xDiff;
}
if (width <= 1)
return false;
int y2 = y + height;
if (y2 > 200) {
int yDiff = y2 - 200;
height -= yDiff;
}
if (height < 1)
return false;
destP = _G(currentScreen).getPixels() + pitch * y + x;
return true;
}
void McgaGraphics::spriteSet(byte *sptr, int16 x, int16 y, int16 scrWidth, uint16 spriteWidth, uint16 spriteHeight) {
if (!sptr)
return;
byte *destP;
int width, height;
if (spriteWidth == 0 && spriteHeight == 0) {
width = *((const int16 *)sptr);
sptr += 2;
height = *((const int16 *)sptr);
sptr += 2;
} else {
width = spriteWidth;
height = spriteHeight;
}
const byte *srcP = sptr;
_G(spriteWidth) = width;
if (!(height >= 1 && width >= 4))
return;
int pitch = scrWidth ? scrWidth : SCREEN_WIDTH;
if (!mspr_set_mcga_clip(x, y, pitch, width, height, srcP, destP))
return;
const int destPitchRemainder = pitch - width;
const int srcPitchRemainder = _G(spriteWidth) - width;
for (int row = 0; row < height; ++row,
srcP += srcPitchRemainder, destP += destPitchRemainder) {
for (int col = 0; col < width; ++col, ++srcP, ++destP) {
if (*srcP != 0)
*destP = *srcP;
}
}
}
void McgaGraphics::map_spr2screen(byte *sptr, int16 x, int16 y) {
const int16 width = ((const int16 *)sptr)[0];
const int16 height = ((const int16 *)sptr)[1];
if (width >= 320 || height >= 200) {
sptr += 4 + y * width + x;
for (int row = 0; row < SCREEN_HEIGHT; ++row, sptr += width) {
Common::copy(
sptr,
sptr + SCREEN_WIDTH,
(byte *)_G(currentScreen).getBasePtr(0, row)
);
}
}
}
int16 McgaGraphics::scanxy(int16 x, int16 y, int16 fcol, int16 bcol, int16 cur_col, int16 scrwidth,
const char *string, ...) {
int16 i, j, stelle, stellemax, mode = 0;
int16 disp_stelle = 0, disp_stellemax = 0, disp_akt = 0;
int16 ret = 0;
int16 delay_flag;
int8 ende = 0, zeichen, zaehler, cursor_z;
char zstring[81], z1string[81];
memset(zstring, 0, 81);
memset(z1string, 0, 81);
int8 einfuege_cur = 0;
unsigned char char_anf = 0, char_end = 0;
uint16 vorzeichen = 0;
int8 x_mode = 0;
int8 eing = 0;
uint16 izahl = 0;
uint16 *intzahl = nullptr;
int16 *intzahl1 = nullptr;
uint32 *longzahl = nullptr;
char *charstr = nullptr;
uint32 luzahl;
va_list parptr;
va_start(parptr, string);
if ((x == -1) || (y == -1)) {
x = _G(gcurx);
y = _G(gcury);
} else {
_G(gcurx) = x;
_G(gcury) = y;
}
move(x, y);
i = 0;
ChewyFont *font = _G(fontMgr)->getFont();
while (!ende) {
zeichen = string[i];
++i;
if ((zeichen >= font->getFirst()) && (zeichen <= font->getLast()) && (zeichen != 127)) {
if (zeichen == '%') {
zeichen = string[i];
++i;
zaehler = 0;
if (zeichen == '[') {
char_anf = string[i];
++i;
++i;
char_end = string[i];
++i;
++i;
zeichen = string[i];
++i;
}
while ((zeichen >= '0') && (zeichen <= '9')) {
zaehler *= 10;
zaehler += (zeichen - 48);
if (zaehler > 80)
zaehler = 80;
zeichen = string[i];
++i;
}
if (_einfuegen == 1) {
einfuege_cur = 125;
cursor_z = '_' + einfuege_cur;
} else {
einfuege_cur = 0;
cursor_z = '_';
}
switch (zeichen) {
case 'd':
vorzeichen = '-';
// Fall through
case 'u':
if ((char_anf == 0) && (char_end == 0)) {
char_anf = '0';
char_end = '9';
}
if (!zaehler)
zaehler = 4;
if (zeichen == 'd') {
mode = 4;
intzahl1 = va_arg(parptr, int16 *);
luzahl = intzahl1[0];
} else {
mode = 1;
intzahl = va_arg(parptr, uint16 *);
luzahl = intzahl[0];
}
if (luzahl != 0)
Common::sprintf_s(zstring, "%u", luzahl);
else {
zstring[0] = '0';
zstring[1] = 0 ;
}
break;
case 'l':
vorzeichen = '-';
if ((char_anf == 0) && (char_end == 0))
vorzeichen = '-';
{
char_anf = '0';
char_end = '9';
}
mode = 2;
if (!zaehler)
zaehler = 9;
longzahl = va_arg(parptr, uint32 *);
luzahl = longzahl[0];
if (luzahl != 0)
Common::sprintf_s(zstring, "%u", luzahl);
else {
zstring[0] = '0';
zstring[1] = 0 ;
}
break;
case 's':
if ((char_anf == 0) && (char_end == 0)) {
char_anf = ' ';
char_end = 0xdc;
}
mode = 3;
vorzeichen = 0xFF;
if (!zaehler)
zaehler = 81;
charstr = va_arg(parptr, char *);
Common::strcpy_s(zstring, charstr);
break;
default:
break;
}
zeichen = string[i];
++i;
if (zeichen == 'x') {
x_mode = 1;
zeichen = string[i];
++i;
}
disp_stellemax = 0;
while ((zeichen >= '0') && (zeichen <= '9')) {
disp_stellemax *= 10;
disp_stellemax += (zeichen - 48);
if (disp_stellemax > 80)
disp_stellemax = 80;
zeichen = string[i];
++i;
}
if (!disp_stellemax)
disp_stellemax = zaehler;
stelle = 0;
disp_stelle = 0;
while (zstring[stelle] != 0) {
++stelle;
}
stellemax = stelle;
if (stelle > disp_stellemax) {
disp_stelle = stelle - disp_stellemax;
disp_akt = disp_stellemax;
} else {
disp_akt = stelle;
disp_stelle = 0;
}
for (j = stelle; j < j + 1; j++) {
while ((!kbhit()) || (eing != 0)) {
EVENTS_UPDATE;
eing = 0;
move(x, y);
for (i = disp_stelle; i <= disp_stellemax + disp_stelle; ++i) {
if (zstring[i] != 0) {
putz(zstring[i], fcol, bcol, scrwidth);
_G(gcurx) += _G(fontMgr)->getFont()->getDataWidth();
} else {
putz(zstring[i], fcol, bcol, scrwidth);
_G(gcurx) += _G(fontMgr)->getFont()->getDataWidth();
break;
}
}
for (delay_flag = 0; (delay_flag < 10) && (!kbhit()); delay_flag++) {
izahl = devices();
if (izahl == Common::KEYCODE_RETURN) {
eing = 2;
break;
} else if (izahl == Common::KEYCODE_ESCAPE) {
eing = 2;
break;
}
}
const uint16 fontWidth = _G(fontMgr)->getFont()->getDataWidth();
plot_scan_cur((x + (disp_akt)*fontWidth), _G(gcury), cur_col, 300, scrwidth, cursor_z);
for (delay_flag = 0; (delay_flag < 10) && (!kbhit()); delay_flag++) {
izahl = devices();
if (izahl == Common::KEYCODE_RETURN) {
eing = 2;
break;
} else if (izahl == Common::KEYCODE_ESCAPE) {
eing = 2;
break;
}
}
if (eing == 2)
break;
}
if (eing < 2)
izahl = (uint16)getch();
if (izahl == Common::KEYCODE_RETURN) {
ret = Common::KEYCODE_RETURN;
ende = 1;
break;
}
if (izahl == Common::KEYCODE_ESCAPE) {
ret = Common::KEYCODE_ESCAPE;
ende = 2;
break;
}
if (izahl == Common::KEYCODE_BACKSPACE) {
eing = 1;
while (kbhit())
getch();
if (stelle > 0) {
const uint16 fontWidth = _G(fontMgr)->getFont()->getDataWidth();
Common::strcpy_s(zstring + stelle - 1, sizeof(zstring) - (stelle - 1), zstring + stelle);
plot_scan_cur((x + disp_akt * fontWidth), _G(gcury), bcol, bcol, scrwidth, cursor_z);
--stelle;
--stellemax;
if (disp_stelle > 0)
--disp_stelle;
else if (disp_akt > 0) {
--disp_akt;
}
}
}
if (izahl == 0) {
izahl = getch();
if (izahl == 75) {
while (kbhit())
getch();
eing = 1;
if (stelle <= 0) {
} else {
if (disp_akt > 0) {
--disp_akt;
} else {
if (disp_stelle > 0)
--disp_stelle;
}
--stelle;
}
}
if (izahl == 77) {
eing = 1;
while (kbhit())
getch();
++j;
if (stelle >= stellemax) {
stelle = stellemax;
} else {
if (disp_akt < disp_stellemax) {
++disp_akt;
} else {
if (disp_stelle <= (zaehler - disp_stellemax)) {
++disp_stelle;
}
}
++stelle;
}
}
if (izahl == 71) {
stelle = 0;
disp_akt = 0;
disp_stelle = 0;
}
if (izahl == 79) {
stelle = stellemax;
if (stellemax < disp_stellemax) {
disp_stelle = 0;
disp_akt = stellemax;
} else {
disp_akt = disp_stellemax;
disp_stelle = stelle - disp_stellemax;
}
}
if ((izahl == 83) && (stelle < stellemax)) {
while (kbhit())
getch();
eing = 1;
Common::strcpy_s(zstring + stelle, sizeof(zstring) - stelle, zstring + stelle + 1);
--stellemax;
}
if (izahl == 82) {
g_events->delay(200);
if (!_einfuegen) {
_einfuegen = 1;
einfuege_cur = 125;
cursor_z = '_' + einfuege_cur;
} else {
_einfuegen = 0;
einfuege_cur = 0;
cursor_z = '_';
}
}
izahl = 0;
}
if (izahl < char_anf || izahl > char_end) {
if (vorzeichen == izahl && !stelle);
else {
if (x_mode == 1) {
ende = 1;
ret = izahl;
break;
}
continue;
}
}
if ((stelle == stellemax) && (stellemax >= zaehler)) {
stellemax = zaehler;
} else {
if (disp_akt < disp_stellemax) {
++disp_akt;
} else {
if (disp_stelle <= (zaehler - disp_stellemax)) {
++disp_stelle;
disp_akt = disp_stellemax;
}
}
if (!_einfuegen) {
zstring[stelle] = izahl;
zstring[stellemax + 1] = 0;
if (stelle == stellemax) {
++stelle;
++stellemax;
} else {
++stelle;
}
} else {
Common::strcpy_s(z1string, zstring);
Common::strcpy_s(zstring + stelle + 1, sizeof(zstring) - (stelle + 1), z1string + stelle);
zstring[stelle] = izahl;
zstring[(int)zaehler] = 0;
if (stellemax < zaehler) {
++stelle;
++stellemax;
} else {
++stelle;
}
}
}
if (x_mode == 1) {
ende = 1;
ret = izahl;
break;
}
}
}
}
}
move(x, y);
for (i = disp_stelle; i <= disp_stellemax + disp_stelle; ++i) {
if (zstring[i] != 0) {
putz(zstring[i], fcol, bcol, scrwidth);
_G(gcurx) += _G(fontMgr)->getFont()->getDataWidth();
} else {
putz(zstring[i], fcol, bcol, scrwidth);
_G(gcurx) += _G(fontMgr)->getFont()->getDataWidth();
break;
}
}
if (ende == 1) {
switch (mode) {
case 1:
intzahl[0] = atoi(zstring);
break;
case 2:
longzahl[0] = atol(zstring);
break;
case 3:
Common::strcpy_s(charstr, 81, zstring);
break;
case 4:
intzahl1[0] = atoi(zstring);
break;
default:
break;
}
}
va_end(parptr);
return ret;
}
void McgaGraphics::plot_scan_cur(int16 x, int16 y, int16 fcol, int16 bcol, int16 scrwidth, char cursor_z) {
move(x, y);
putz(cursor_z, fcol, bcol, scrwidth);
}
void McgaGraphics::printxy(int16 x, int16 y, int16 fgCol, int16 bgCol, int16 scrwidth, const char *string) {
ChewyFont *font = _G(fontMgr)->getFont();
Graphics::Surface *textSurface = font->getLine(string);
byte *data = (byte *)textSurface->getPixels();
for (int curX = 0; curX < textSurface->pitch; curX++) {
for (int curY = 0; curY < textSurface->h; curY++) {
if (curX + x < 320 && curY + y < 200) {
byte *src = data + (curY * textSurface->pitch) + curX;
byte *dst = (byte *)_G(currentScreen).getBasePtr(curX + x, curY + y);
if (*src != 0xFF)
*dst = fgCol;
else if (bgCol < 0xFF)
*dst = bgCol;
}
}
}
g_screen->addDirtyRect(Common::Rect(
x, y, x + textSurface->pitch, y + textSurface->h));
textSurface->free();
delete textSurface;
}
void McgaGraphics::move(int16 x, int16 y) {
_G(gcurx) = x;
_G(gcury) = y;
}
int16 McgaGraphics::devices() {
int16 i = 0;
// TODO: This is wrong. 'i' should be initialized to "button status" (BX after a call to Int33h/03
if (i > 1) {
i = 27;
} else if (i == 1)
i = 13;
else
i = 0;
return i;
}
void McgaGraphics::scale_set(byte *sptr, int16 x, int16 y, int16 xdiff_, int16 ydiff_, int16 scrwidth) {
if (xdiff_ || ydiff_)
zoom_set(sptr, x, y, xdiff_, ydiff_, scrwidth);
else
spriteSet(sptr, x, y, scrwidth);
}
void McgaGraphics::putz(unsigned char c, int16 fgCol, int16 bgCol, int16 scrWidth) {
const int16 x = _G(gcurx);
const int16 y = _G(gcury);
ChewyFont *font = _G(fontMgr)->getFont();
Graphics::Surface *textSurface = font->getLine(Common::String(c));
byte *data = (byte *)textSurface->getPixels();
for (int curX = 0; curX < textSurface->pitch; curX++) {
for (int curY = 0; curY < textSurface->h; curY++) {
if (curX + x < 320 && curY + y < 200) {
byte *src = data + (curY * textSurface->pitch) + curX;
byte *dst = (byte *)_G(currentScreen).getBasePtr(curX + x, curY + y);
if (*src != 0xFF)
*dst = fgCol;
else if (bgCol < 0xFF)
*dst = bgCol;
}
}
}
g_screen->addDirtyRect(Common::Rect(
x, y, x + textSurface->pitch, y + textSurface->h));
textSurface->free();
delete textSurface;
}
void McgaGraphics::setXVals() {
if (_zoomSpriteDeltaX2 == 0) {
_zoomSpriteXVal1 = 0;
_zoomSpriteXVal2 = 1;
} else {
_zoomSpriteXVal1 = _G(spriteWidth) / _zoomSpriteDeltaX2;
_zoomSpriteXVal2 = 1000 * (_G(spriteWidth) % _zoomSpriteDeltaX2);
_zoomSpriteXVal2 /= _zoomSpriteDeltaX2;
}
}
void McgaGraphics::setYVals(int spriteHeight) {
if (_zoomSpriteDeltaY2 == 0) {
_zoomSpriteYVal1 = 0;
_zoomSpriteYVal2 = 1;
} else {
_zoomSpriteYVal1 = spriteHeight / _zoomSpriteDeltaY2;
_zoomSpriteYVal2 = 1000 * (spriteHeight % _zoomSpriteDeltaY2);
_zoomSpriteYVal2 /= _zoomSpriteDeltaY2;
}
}
void McgaGraphics::clip(byte *&source, byte *&dest, int16 &x, int16 &y) {
if (y < 0) {
int yCount = 0 - y;
_zoomSpriteDeltaY2 -= yCount;
--yCount;
if (yCount >= 1) {
for (int yc = 0, countY = _zoomSpriteYVal2; yc < yCount; ++yc) {
source += _G(spriteWidth) * _zoomSpriteYVal1;
dest += SCREEN_WIDTH;
while (countY > 1000) {
countY -= 1000;
source += _G(spriteWidth);
}
}
}
}
if (_zoomSpriteDeltaY2 <= 0) {
source = nullptr;
return;
}
if (x < 0) {
int xCount = 0 - x;
_zoomSpriteDeltaX2 -= xCount;
dest += xCount;
--xCount;
if (xCount >= 1) {
for (int xc = 0, countX = _zoomSpriteXVal2; xc < xCount; ++xc) {
source += _zoomSpriteXVal1;
while (countX >= 1000) {
countX -= 1000;
++source;
}
}
}
}
if (_zoomSpriteDeltaX2 > 0) {
int x2 = x + _zoomSpriteDeltaX2;
if (x2 >= 320) {
_zoomSpriteDeltaX2 -= x2 - 320;
}
if (_zoomSpriteDeltaY2 > 0) {
int y2 = y + _zoomSpriteDeltaY2;
if (y2 >= 200) {
_zoomSpriteDeltaY2 -= y2 - 200;
}
if (_zoomSpriteDeltaY2 <= 0)
source = nullptr;
} else {
source = nullptr;
}
} else {
source = nullptr;
}
}
void McgaGraphics::zoom_set(byte *source, int16 x, int16 y, int16 xDiff, int16 yDiff, int16 scrWidth) {
_G(spriteWidth) = ((int16 *)source)[0];
int spriteHeight = ((int16 *)source)[1];
source += 4;
_zoomSpriteDeltaX2 = _G(spriteWidth) + xDiff;
_zoomSpriteDeltaY2 = spriteHeight + yDiff;
setXVals();
setYVals(spriteHeight);
const int16 screenWidth = scrWidth > 0 ? scrWidth : SCREEN_WIDTH;
byte *scrP = _G(currentScreen).getPixels() + y * screenWidth + x;
clip(source, scrP, x, y);
if (source) {
for (int yc = _zoomSpriteDeltaY2, countY = _zoomSpriteYVal2; yc > 0; --yc) {
byte *srcLine = source;
byte *scrLine = scrP;
for (int xc = _zoomSpriteDeltaX2, countX = _zoomSpriteXVal2; xc > 0; --xc) {
if (*source)
*scrP = *source;
++scrP;
source += _zoomSpriteXVal1;
countX += _zoomSpriteXVal2;
while (countX > 1000) {
countX -= 1000;
++source;
}
}
source = srcLine;
scrP = scrLine + SCREEN_WIDTH;
for (int ySkip = 0; ySkip < _zoomSpriteYVal1; ++ySkip) {
source += _G(spriteWidth);
}
countY += _zoomSpriteYVal2;
while (countY > 1000) {
countY -= 1000;
source += _G(spriteWidth);
}
}
}
}
int16 McgaGraphics::findHotspot(const Common::Rect *hotspots) {
int16 i = 0;
do {
if (hotspots[i].contains(g_events->_mousePos))
return i;
i++;
} while (hotspots[i].left != -1);
return -1;
}
} // namespace Chewy

View File

@@ -0,0 +1,89 @@
/* 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/>.
*
*/
#ifndef CHEWY_MCGA_GRAPHICS_H
#define CHEWY_MCGA_GRAPHICS_H
#include "graphics/screen.h"
namespace Chewy {
class McgaGraphics {
public:
McgaGraphics();
~McgaGraphics();
void init();
void setPointer(byte *ptr);
void setPalette(byte *palette);
void raster_col(int16 c, int16 r, int16 g, int16 b);
void fadeIn(byte *palette);
void fadeOut();
void set_partialpalette(const byte *palette, int16 startCol, int16 nr);
void cls();
void drawLine(int16 x1, int16 y1, int16 x2, int16 y2, int16 color);
void box(int16 x1, int16 y1, int16 x2, int16 y2, int16 color);
void boxFill(int16 x1, int16 y1, int16 x2, int16 y2, int16 color);
void pop_box(int16 x, int16 y, int16 x1, int16 y1,
int16 col1, int16 col2, int16 back_col);
void copyToScreen();
void spriteSave(byte *spritePtr, int16 x, int16 y, int16 width,
int16 height);
void spriteSet(byte *sptr, int16 x, int16 y, int16 scrWidth, uint16 spriteWidth = 0, uint16 spriteHeight = 0);
void scale_set(byte *sptr, int16 x, int16 y, int16 xdiff,
int16 ydiff, int16 scrwidth);
void map_spr2screen(byte *sptr, int16 x, int16 y);
void plot_scan_cur(int16 x, int16 y, int16 fcol, int16 bcol, int16 scrwidth,
char cursor);
int16 scanxy(int16 x, int16 y, int16 fcol, int16 bcol, int16 cur_col, int16 scrwidth, const char *string, ...);
void printxy(int16 x, int16 y, int16 fgCol, int16 bgCol, int16 scrwidth,
const char *format);
void move(int16 x, int16 y);
int16 findHotspot(const Common::Rect *hotspots);
private:
int16 devices();
void putz(unsigned char c, int16 fgCol, int16 bgCol, int16 scrWidth);
// Zoom related
void setXVals();
void setYVals(int spriteHeight);
void clip(byte *&source, byte *&dest, int16 &x, int16 &y);
void zoom_set(byte *source, int16 x, int16 y, int16 xDiff, int16 yDiff, int16 scrWidth);
byte _palTable[Graphics::PALETTE_SIZE];
uint8 _einfuegen = 0;
int _zoomSpriteDeltaX2;
int _zoomSpriteDeltaY2;
int _zoomSpriteXVal1, _zoomSpriteXVal2;
int _zoomSpriteYVal1, _zoomSpriteYVal2;
};
} // namespace Chewy
#endif

92
engines/chewy/memory.cpp Normal file
View File

@@ -0,0 +1,92 @@
/* 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/>.
*
*/
#include "common/memstream.h"
#include "chewy/memory.h"
#include "chewy/globals.h"
#include "chewy/types.h"
#include "chewy/resource.h"
namespace Chewy {
TafInfo *Memory::taf_adr(const char *filename) {
SpriteResource *res = new SpriteResource(filename);
int32 imageCount = res->getChunkCount();
uint32 size = res->getAllSize() + imageCount * 8 + sizeof(TafInfo);
uint32 kgroesse = imageCount * sizeof(byte *);
byte *tmp1 = (byte *)MALLOC(size + Graphics::PALETTE_SIZE + kgroesse);
TafInfo *tinfo = (TafInfo *)tmp1;
tinfo->image = (byte **)(tmp1 + sizeof(TafInfo));
tinfo->palette = tmp1 + size;
tinfo->count = imageCount;
memcpy(tinfo->palette, res->getSpritePalette(), Graphics::PALETTE_SIZE);
byte *imgPtr = tmp1 + sizeof(TafInfo) + kgroesse;
for (int i = 0; i < imageCount; i++) {
tinfo->image[i] = imgPtr;
imgPtr += res->getSpriteData(i, &tinfo->image[i], false);
}
tinfo->correction = (int16 *)(tmp1 + (size + 768l));
memcpy(tinfo->correction, res->getSpriteCorrectionsTable(), imageCount * 2 * sizeof(int16));
delete res;
return tinfo;
}
TafSeqInfo *Memory::taf_seq_adr(int16 image_start, int16 image_anz) {
TafSeqInfo *ts_info;
SpriteResource *res = new SpriteResource(CH_SPZ_FILE);
uint32 size = 0;
for (int16 i = 0; i < image_anz; i++) {
TAFChunk *sprite = res->getSprite(i + image_start);
size += sprite->width * sprite->height;
delete sprite;
}
size += image_anz * sizeof(byte *);
size += image_anz * sizeof(char *);
size += ((uint32)sizeof(TafSeqInfo));
byte *tmp1 = (byte *)MALLOC(size + image_anz * sizeof(byte *));
ts_info = (TafSeqInfo *)tmp1;
ts_info->count = image_anz;
ts_info->image = (byte **)(tmp1 + sizeof(TafSeqInfo));
ts_info->correction = (int16 *)(tmp1 + size);
byte *sp_ptr = tmp1 + ((sizeof(TafSeqInfo)) + (image_anz * sizeof(char *)));
for (int16 i = 0; i < image_anz; i++) {
ts_info->image[i] = sp_ptr;
sp_ptr += res->getSpriteData(i + image_start, &ts_info->image[i], false);
}
uint16 *correctionsTable = res->getSpriteCorrectionsTable() + image_start * 2;
memcpy(ts_info->correction, correctionsTable, image_anz * 2 * sizeof(int16));
delete res;
return ts_info;
}
} // namespace Chewy

40
engines/chewy/memory.h Normal file
View File

@@ -0,0 +1,40 @@
/* 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/>.
*
*/
#ifndef CHEWY_MEMORY_H
#define CHEWY_MEMORY_H
#include "chewy/ngstypes.h"
namespace Chewy {
class Memory {
public:
Memory() {}
~Memory() {}
TafInfo *taf_adr(const char *filename);
TafSeqInfo *taf_seq_adr(int16 image_start, int16 image_anz);
};
} // namespace Chewy
#endif

386
engines/chewy/menus.cpp Normal file
View File

@@ -0,0 +1,386 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/detail.h"
#include "chewy/events.h"
#include "chewy/font.h"
#include "chewy/globals.h"
#include "chewy/main.h"
#include "chewy/mcga_graphics.h"
#include "chewy/menus.h"
namespace Chewy {
void plotMainMenu() {
static const int IMAGES[] = { 7, 8, 9, 10, 12, 11 };
int16 zoomX, zoomY;
if (_G(menu_item) != _G(tmp_menu)) {
_G(m_flip) = 0;
_G(tmp_menu) = _G(menu_item);
}
// Don't allow the mouse to warp past the right edge, as this messes
// up the menu screen
if (g_events->_mousePos.x > 266)
g_events->warpMouse(Common::Point(266, g_events->_mousePos.y));
const int16 x = MAX(g_events->_mousePos.x - 32, 0);
_G(menu_item) = (x / (MOUSE_MENU_MAX_X / 5));
int16 *correction = (int16 *)_G(menutaf)->correction;
for (int16 i = MENU_START_SPRITE; i < MAX_MENU_SPRITE; i++) {
int deltaX = 0;
if (i <= 8) {
zoomX = 0;
zoomY = 0;
} else {
zoomX = -3;
zoomY = -3;
if (i == 11)
deltaX = 40;
else if (i == 12)
deltaX = -40;
}
_G(out)->scale_set(_G(menutaf)->image[i],
MENU_X + deltaX + correction[i * 2],
_G(gameState).MainMenuY + correction[i * 2 + 1],
zoomX, zoomY, 0);
}
zoomX = 16;
zoomY = 16;
++_G(m_flip);
if (_G(m_flip) < 12 * (_G(gameState).DelaySpeed + 1)) {
int deltaX = 0;
if (_G(menu_item) == CUR_SAVE)
deltaX = -40;
else if (_G(menu_item) == CUR_INVENT)
deltaX = 40;
int img = IMAGES[_G(menu_item)];
_G(out)->scale_set(_G(menutaf)->image[img],
MENU_X + deltaX + correction[img * 2] - 5,
_G(gameState).MainMenuY + correction[img * 2 + 1] - 10,
zoomX, zoomY, 0);
} else {
if (_G(m_flip) > 15 * (_G(gameState).DelaySpeed + 1))
_G(m_flip) = 0;
}
}
void calcTxtXy(int16 *x, int16 *y, char *txtAdr, int16 txtCount) {
int16 len = 0;
for (int16 i = 0; i < txtCount; i++) {
int16 tmpLen = strlen(_G(txt)->strPos(txtAdr, i));
if (tmpLen > len)
len = tmpLen;
}
len = len * _G(fontMgr)->getFont()->getDataWidth();
int16 pixLen = len / 2;
*x = *x - pixLen + 12;
if (*x > (SCREEN_WIDTH - len))
*x = SCREEN_WIDTH - len;
else if (*x < 0)
*x = 0;
*y = *y - (10 * txtCount);
if (*y < 0)
*y = 0;
}
void calcTxtXy(int16 *x, int16 *y, Common::StringArray &textList) {
int16 len = 0;
for (int16 i = 0; i < (int16)textList.size(); i++) {
if ((int16)textList[i].size() > len)
len = textList[i].size();
}
len = len * _G(fontMgr)->getFont()->getDataWidth();
int16 pixLen = len / 2;
*x = *x - pixLen + 12;
if (*x > (SCREEN_WIDTH - len))
*x = SCREEN_WIDTH - len;
else if (*x < 0)
*x = 0;
*y = *y - (10 * textList.size());
if (*y < 0)
*y = 0;
}
void getDisplayCoord(int16 *x, int16 *y, int16 nr) {
int16 *xy = (int16 *)_G(inv_spr)[nr];
int16 x1 = 48 - xy[0];
x1 /= 2;
*x = x1;
int16 y1 = 48 - xy[1];
y1 /= 2;
*y = y1;
}
void buildMenu(int16 x, int16 y, int16 xNr, int16 yNr, int16 col, int16 mode) {
#define BUILDING_MENU_CORNER_LO 15
#define BUILDING_MENU_CORNER_RO 16
#define BUILDING_MENU_CORNER_LU 17
#define BUILDING_MENU_CORNER_RU 18
#define BUILDING_MENU_BELOW 19
#define BUILDING_MENU_SIDE_L 20
#define BUILDING_MENU_SIDE_R 21
#define BUILDING_MENU_ABOVE 22
#define BUILDING_MENU_ABOVE_L 23
#define BUILDING_MENU_ABOVE_R 24
#define BUILDING_MENU_ABOVE_M 25
int16 i, j;
int16 xy[4][2] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
uint8 spriteCornerNr[4] = { BUILDING_MENU_CORNER_LO, BUILDING_MENU_CORNER_RO, BUILDING_MENU_CORNER_LU, BUILDING_MENU_CORNER_RU };
xy[0][0] = x;
xy[0][1] = y;
xy[1][0] = x + 16 * (xNr - 1);
xy[1][1] = y;
xy[2][0] = x;
xy[2][1] = y + 16 * (yNr - 1);
xy[3][0] = x + 16 * (xNr - 1);
xy[3][1] = y + 16 * (yNr - 1);
for (i = 0; i < 4; i++)
_G(out)->spriteSet(_G(menutaf)->image[(int16)spriteCornerNr[i]],
xy[i][0], xy[i][1], _G(scr_width));
int16 s_nr = BUILDING_MENU_SIDE_L;
for (j = 0; j < 2; j++) {
y = xy[j][1] + 16;
for (i = 0; i < yNr - 2; i++) {
_G(out)->spriteSet(_G(menutaf)->image[s_nr], xy[j][0], y + i * 16, _G(scr_width));
}
++s_nr;
}
s_nr = BUILDING_MENU_ABOVE;
for (j = 0; j < 2; j++) {
x = xy[j * 2][0] + 16;
if ((!mode) || (mode == 1 && j == 1)) {
for (i = 0; i < xNr - 2; i++) {
_G(out)->spriteSet(_G(menutaf)->image[s_nr], x + i * 16, xy[j * 2][1], _G(scr_width));
}
}
s_nr -= 3;
}
if (mode) {
int16 leer = 0;
int16 center;
i = xNr - 7;
if (i == 0)
center = 1;
else if (i < 6)
center = i + 1;
else if (i < 8) {
leer = 1;
center = i - 1;
} else {
leer = 2;
center = i - 3;
}
x = xy[0][0] + 16;
for (j = 0; j < 2; j++) {
for (i = 0; i < leer; i++)
_G(out)->spriteSet(_G(menutaf)->image[BUILDING_MENU_ABOVE], x + i * 16, xy[0][1], _G(scr_width));
x = xy[1][0] - leer * 16;
}
_G(out)->spriteSet(_G(menutaf)->image[BUILDING_MENU_ABOVE_L], xy[0][0] + 16 + leer * 16, xy[0][1], _G(scr_width));
x = xy[0][0] + 16 + leer * 16 + 32;
for (i = 0; i < center; i++)
_G(out)->spriteSet(_G(menutaf)->image[BUILDING_MENU_ABOVE_M], x + i * 16, xy[0][1], _G(scr_width));
_G(out)->spriteSet(_G(menutaf)->image[BUILDING_MENU_ABOVE_R], x + i * 16, xy[0][1], _G(scr_width));
}
_G(out)->boxFill(xy[0][0] + 16, xy[0][1] + 16, xy[0][0] + 16 + (xNr - 2) * 16, xy[0][1] + 16 + (yNr - 2) * 16, col);
}
void autoMenu(int16 *x, int16 *y, int16 lineNr, int16 height, char *text, int16 mode) {
int16 tmp;
int16 x_pix = 0;
for (int16 i = 0; i < lineNr; i++) {
tmp = strlen(_G(txt)->strPos(text, i));
if (x_pix < tmp)
x_pix = tmp;
}
x_pix *= _G(font8)->getDataWidth();
x_pix += 12;
tmp = x_pix;
if (x_pix % 16)
tmp += 16;
int16 tmp1 = lineNr * height + 6 + 11;
if (tmp1 % 16)
tmp1 += 16;
*x -= ((tmp / 16) * 16) / 2;
*y -= ((tmp1 / 16) * 16) / 2;
buildMenu(*x, *y, tmp / 16, tmp1 / 16, 60, mode);
*x += 6 + (((tmp / 16) * 16) - x_pix) / 2;
*y += 5 + ((((tmp1 / 16) * 16) - 4) - (lineNr * height)) / 2;
}
#define ADS_WIN 0,153,20,3,60,1
void handleDialogCloseupMenu() {
int16 curYStart;
int16 col;
if (_G(flags).DialogCloseup) {
_G(flags).ShowAtsInvTxt = false;
_G(flags).MainInput = false;
if (_G(ads_item_nr) > 4)
curYStart = 190;
else
curYStart = 190 - (4 - _G(ads_item_nr)) * 10;
int16 curY = g_events->_mousePos.y;
if (curY < 160 || curY > curYStart + 10)
curY = 255;
else
curY = (curYStart + 8 - curY) / 10;
if (_G(atds)->aadGetStatus() == -1 && _G(ads_push) == false &&
_G(flags).NoDiaBox == false) {
buildMenu(ADS_WIN);
_G(fontMgr)->setFont(_G(font6));
if (_G(ads_item_nr) > 4)
curYStart = 190;
else
curYStart = 190 - (4 - _G(ads_item_nr)) * 10;
for (int16 i = 0; i < _G(ads_item_nr) && i < 4; i++) {
if (curY == i)
col = 255;
else
col = 14;
_G(out)->printxy(4, curYStart - i * 10, col, 300, 0, _G(dialogCloseupItemPtr)[i]);
}
}
switch (g_events->getSwitchCode()) {
case Common::MOUSE_BUTTON_LEFT:
case Common::KEYCODE_RETURN:
if (curY < _G(ads_item_nr) && curY >= 0 && _G(ads_push) == false) {
_G(ads_push) = true;
g_events->_mousePos.y = 159;
DialogCloseupNextBlock *an_blk = _G(atds)->dialogCloseupItemChoice(_G(ads_dia_nr), _G(ads_blk_nr), curY);
if (an_blk->_blkNr == -1) {
selectDialogOption(_G(ads_dia_nr), _G(ads_blk_nr), an_blk->_endNr);
endDialogCloseup(_G(ads_dia_nr), _G(ads_blk_nr), an_blk->_endNr);
stopDialogCloseupDialog();
} else {
an_blk = _G(atds)->calcNextDialogCloseupBlock(_G(ads_dia_nr), _G(ads_blk_nr), curY);
selectDialogOption(_G(ads_dia_nr), _G(ads_blk_nr), an_blk->_endNr);
_G(ads_blk_nr) = an_blk->_blkNr;
_G(dialogCloseupItemPtr) = _G(atds)->dialogCloseupItemPtr(_G(ads_dia_nr), _G(ads_blk_nr), &_G(ads_item_nr));
}
_G(det)->stopDetail(_G(talk_start_ani));
_G(det)->showStaticSpr(_G(talk_hide_static));
_G(talk_start_ani) = -1;
_G(talk_hide_static) = -1;
}
break;
default:
_G(ads_push) = false;
break;
}
}
}
void stopDialogCloseupDialog() {
aadWait(-1);
_G(gameState).DispFlag = _G(ads_tmp_dsp);
_G(flags).ShowAtsInvTxt = true;
_G(flags).MainInput = true;
_G(flags).DialogCloseup = false;
_G(mouseLeftClick) = false;
_G(atds)->stopDialogCloseup();
if (_G(minfo).button)
_G(flags).mainMouseFlag = 1;
}
void cur_2_inventory() {
if (_G(cur)->usingInventoryCursor()) {
invent_2_slot(_G(cur)->getInventoryCursor());
_G(cur)->setInventoryCursor(-1);
_G(menu_item) = CUR_WALK;
cursorChoice(_G(menu_item));
}
_G(cur)->setInventoryCursor(-1);
}
void inventory_2_cur(int16 nr) {
if (!_G(cur)->usingInventoryCursor() && _G(obj)->checkInventory(nr)) {
del_invent_slot(nr);
_G(menu_item) = CUR_USE;
_G(cur)->setInventoryCursor(nr);
getDisplayCoord(&_G(gameState).DispZx, &_G(gameState).DispZy, _G(cur)->getInventoryCursor());
}
}
void new_invent_2_cur(int16 inv_nr) {
cur_2_inventory();
_G(obj)->addInventory(inv_nr, &_G(room_blk));
inventory_2_cur(inv_nr);
}
void invent_2_slot(int16 nr) {
for (int16 i = 0; i < MAX_MOV_OBJ; i++) {
if (_G(gameState).InventSlot[i] == -1) {
_G(gameState).InventSlot[i] = nr;
break;
}
}
_G(obj)->addInventory(nr, &_G(room_blk));
}
int16 del_invent_slot(int16 nr) {
int16 ok = -1;
for (int16 i = 0; i < MAX_MOV_OBJ; i++) {
if (_G(gameState).InventSlot[i] == nr) {
_G(gameState).InventSlot[i] = -1;
if (ok == -1)
ok = i;
}
}
return ok;
}
void remove_inventory(int16 nr) {
if (nr == _G(cur)->getInventoryCursor()) {
delInventory(nr);
} else {
_G(obj)->delInventory(nr, &_G(room_blk));
del_invent_slot(nr);
}
}
} // namespace Chewy

33
engines/chewy/menus.h Normal file
View File

@@ -0,0 +1,33 @@
/* 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/>.
*
*/
#ifndef CHEWY_MENUS_H
#define CHEWY_MENUS_H
namespace Chewy {
#define MOUSE_MENU_MAX_X 200
#define MENU_DISPLAY 1
#define MENU_HIDE 2
} // namespace Chewy
#endif

View File

@@ -0,0 +1,99 @@
/* 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/>.
*
*/
#include "common/savefile.h"
#include "common/system.h"
#include "common/translation.h"
#include "base/plugins.h"
#include "engines/advancedDetector.h"
#include "chewy/chewy.h"
#include "chewy/detection.h"
namespace Chewy {
static const ADExtraGuiOptionsMap optionsList[] = {
{
GAMEOPTION_ORIGINAL_SAVELOAD,
{
_s("Use original save/load screens"),
_s("Use the original save/load screens instead of the ScummVM ones"),
"original_menus",
false,
0,
0
}
},
AD_EXTRA_GUI_OPTIONS_TERMINATOR
};
uint32 ChewyEngine::getFeatures() const {
return _gameDescription->desc.flags;
}
Common::Language ChewyEngine::getLanguage() const {
return _gameDescription->desc.language;
}
} // End of namespace Chewy
class ChewyMetaEngine : public AdvancedMetaEngine<Chewy::ChewyGameDescription> {
public:
const char *getName() const override {
return "chewy";
}
const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
return Chewy::optionsList;
}
bool hasFeature(MetaEngineFeature f) const override;
Common::Error createInstance(OSystem *syst, Engine **engine, const Chewy::ChewyGameDescription *desc) const override;
int getMaximumSaveSlot() const override;
};
bool ChewyMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSupportsLoadingDuringStartup) ||
checkExtendedSaves(f);
}
bool Chewy::ChewyEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsReturnToLauncher) ||
(f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime);
}
Common::Error ChewyMetaEngine::createInstance(OSystem *syst, Engine **engine, const Chewy::ChewyGameDescription *desc) const {
*engine = new Chewy::ChewyEngine(syst,desc);
return Common::kNoError;
}
int ChewyMetaEngine::getMaximumSaveSlot() const {
return 999;
}
#if PLUGIN_ENABLED_DYNAMIC(CHEWY)
REGISTER_PLUGIN_DYNAMIC(CHEWY, PLUGIN_TYPE_ENGINE, ChewyMetaEngine);
#else
REGISTER_PLUGIN_STATIC(CHEWY, PLUGIN_TYPE_ENGINE, ChewyMetaEngine);
#endif

144
engines/chewy/module.mk Normal file
View File

@@ -0,0 +1,144 @@
MODULE := engines/chewy
MODULE_OBJS = \
atds.o \
barriers.o \
chewy.o \
cursor.o \
console.o \
detail.o \
effect.o \
events.o \
font.o \
globals.o \
inits.o \
main.o \
mcga_graphics.o \
memory.o \
menus.o \
metaengine.o \
movclass.o \
object.o \
object_extra.o \
r_event.o \
room.o \
resource.o \
sound.o \
sprite.o \
t_event.o \
text.o \
timer.o \
types.o \
audio/chewy_voc.o \
audio/module_tmf.o \
audio/tmf_stream.o \
dialogs/cinema.o \
dialogs/credits.o \
dialogs/files.o \
dialogs/inventory.o \
dialogs/main_menu.o \
dialogs/options.o \
video/cfo_decoder.o \
video/video_player.o \
rooms/room00.o \
rooms/room01.o \
rooms/room02.o \
rooms/room03.o \
rooms/room04.o \
rooms/room05.o \
rooms/room06.o \
rooms/room07.o \
rooms/room08.o \
rooms/room09.o \
rooms/room10.o \
rooms/room11.o \
rooms/room12.o \
rooms/room13.o \
rooms/room14.o \
rooms/room16.o \
rooms/room17.o \
rooms/room18.o \
rooms/room19.o \
rooms/room21.o \
rooms/room22.o \
rooms/room23.o \
rooms/room24.o \
rooms/room25.o \
rooms/room26.o \
rooms/room27.o \
rooms/room28.o \
rooms/room29.o \
rooms/room31.o \
rooms/room32.o \
rooms/room33.o \
rooms/room34.o \
rooms/room35.o \
rooms/room37.o \
rooms/room39.o \
rooms/room40.o \
rooms/room41.o \
rooms/room42.o \
rooms/room43.o \
rooms/room44.o \
rooms/room45.o \
rooms/room46.o \
rooms/room47.o \
rooms/room48.o \
rooms/room49.o \
rooms/room50.o \
rooms/room51.o \
rooms/room52.o \
rooms/room53.o \
rooms/room54.o \
rooms/room55.o \
rooms/room56.o \
rooms/room57.o \
rooms/room58.o \
rooms/room59.o \
rooms/room62.o \
rooms/room63.o \
rooms/room64.o \
rooms/room65.o \
rooms/room66.o \
rooms/room67.o \
rooms/room68.o \
rooms/room69.o \
rooms/room70.o \
rooms/room71.o \
rooms/room72.o \
rooms/room73.o \
rooms/room74.o \
rooms/room75.o \
rooms/room76.o \
rooms/room77.o \
rooms/room78.o \
rooms/room79.o \
rooms/room80.o \
rooms/room81.o \
rooms/room82.o \
rooms/room83.o \
rooms/room84.o \
rooms/room85.o \
rooms/room86.o \
rooms/room87.o \
rooms/room88.o \
rooms/room89.o \
rooms/room90.o \
rooms/room91.o \
rooms/room92.o \
rooms/room93.o \
rooms/room94.o \
rooms/room95.o \
rooms/room96.o \
rooms/room97.o
# This module can be built as a plugin
ifeq ($(ENABLE_CHEWY), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk
# Detection objects
DETECT_OBJS += $(MODULE)/detection.o

787
engines/chewy/movclass.cpp Normal file
View File

@@ -0,0 +1,787 @@
/* 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/>.
*
*/
#include "chewy/movclass.h"
#include "chewy/defines.h"
#include "chewy/globals.h"
namespace Chewy {
#define LEFT_VECT -1
#define RIGHT_VECT 1
#define MOV_START 0
#define MOV_FOUND 1
#define MOV_UNPASSABLE 2
#define Y_DOWN 1
#define Y_UP 2
#define SOURCE_COL 14
#define DEST_COL 19
#define CHECK_COL 255
#define MIN_COL 8
#define UNBEGEHBAR_COL 3
#define CONNECT_COL 15
#define CUR_COL 13
#define S_OBEN 0
#define S_RECHTS 1
#define S_UNTEN 2
#define S_LINKS 3
#define MOV_X 1
#define MOV_Y 2
MovClass::MovClass() {
_vecTbl[0] = -40;
_vecTbl[1] = 1;
_vecTbl[2] = 40;
_vecTbl[3] = -1;
}
MovClass::~MovClass() {
}
void MovClass::goto_xy(GotoPkt *gp) {
const int16 width = _G(room)->_barriers->getWidth();
_gpkt = gp;
_agv.AutoGo = false;
_agv.Continue = false;
_vecTbl[0] = -width;
_vecTbl[2] = width;
_plotDelay = 20;
calc_xy();
_plotDelay = 0;
int16 start_feld = get_feld_nr(_gpkt->Sx, _gpkt->Sy);
int16 ziel_feld = get_feld_nr(_gpkt->Dx, _gpkt->Dy);
int16 tmp = ziel_feld;
calc_go(start_feld, &ziel_feld);
if (tmp != ziel_feld) {
get_mov_line();
if (_gml.MLineFeld != -1) {
calc_mov_line_xit(_gml.MLineFeld);
if (_mle.FNr != -1) {
_agv.AutoGo = true;
_agv.Start = 0;
_agv.LastFeld = -1;
_agv.AkKnoten = 0;
start_feld = get_feld_nr(_gpkt->Sx, _gpkt->Sy);
ziel_feld = _gml.MLineFeld;
calc_go(start_feld, &ziel_feld);
if (_gml.MLineFeld != ziel_feld) {
_agv.PktAnz = 2;
} else {
_agv.PktAnz = 1;
}
}
}
}
}
int16 MovClass::calc_auto_go(int16 x, int16 y, int16 *auto_x, int16 *auto_y) {
int16 ret = -1;
const int16 width = _G(room)->_barriers->getWidth();
const int16 height = _G(room)->_barriers->getHeight();
if (_agv.AutoGo == true) {
const byte *data = _G(room)->_barriers->getData();
const byte *buffer = data + 6;
buffer += (width * height) * _gpkt->AkMovEbene;
if (!_agv.Start) {
_agv.Start = _agv.PktAnz;
if (_agv.PktAnz == 1) {
_agv.Start = 3;
get_feld_xy(_gml.MLineFeld, &_agv.X_End, &_agv.Y_End);
_agv.AkFeld = _gml.MLineFeld;
} else {
get_feld_xy(_gml.GotoFeld, &_agv.X_End, &_agv.Y_End);
_agv.AkFeld = _gml.GotoFeld;
}
*auto_x = _agv.X_End + 4;
*auto_y = _agv.Y_End + 4;
ret = true;
} else {
if (get_feld_nr(x, y) == _agv.AkFeld) {
if (_agv.Start == 2) {
_agv.Start = 3;
get_feld_xy(_gml.GotoFeld, &_agv.X_End, &_agv.Y_End);
*auto_x = _agv.X_End + 4;
*auto_y = _agv.Y_End + 4;
ret = true;
} else if (_agv.Start == 3) {
if (_agv.LastFeld == -1) {
_agv.LastFeld = _gml.MLineFeld;
_agv.AkFeld = _gml.MLineFeld + _mle.Direction;
if (buffer[_agv.AkFeld] == MOV_LINE_KNOTEN) {
_feld1knoten = true;
} else
_feld1knoten = false;
get_feld_xy(_agv.AkFeld, &_agv.X_End, &_agv.Y_End);
*auto_x = _agv.X_End + 4;
*auto_y = _agv.Y_End + 4;
ret = true;
} else if (get_feld_nr(x, y) == _agv.AkFeld) {
if (_agv.AkFeld == _mle.FNr) {
_agv.AutoGo = false;
*auto_x = _gpkt->Dx;
*auto_y = _gpkt->Dy;
ret = true;
} else {
int16 ok = 0;
if (_feld1knoten) {
_feld1knoten = false;
_agv.LastFeld = _agv.AkFeld;
_agv.AkFeld = _mle.KnPkt[_agv.AkKnoten];
++_agv.AkKnoten;
if (_agv.AkFeld != -1)
ok = 1;
} else {
for (int16 i = 0; i < 4 && !ok; i++) {
if (buffer[_agv.AkFeld + _vecTbl[i]] == MOV_LINE_IDX) {
if (_agv.AkFeld + _vecTbl[i] != _agv.LastFeld) {
_agv.LastFeld = _agv.AkFeld;
_agv.AkFeld += _vecTbl[i];
ok = 1;
}
} else if (buffer[_agv.AkFeld + _vecTbl[i]] == MOV_LINE_KNOTEN) {
if (_agv.AkFeld + _vecTbl[i] != _agv.LastFeld) {
_agv.LastFeld = _agv.AkFeld + _vecTbl[i];
_agv.AkFeld = _mle.KnPkt[_agv.AkKnoten];
++_agv.AkKnoten;
if (_agv.AkFeld == -1)
ok = 0;
else
ok = 1;
}
}
}
}
if (ok) {
get_feld_xy(_agv.AkFeld, &_agv.X_End, &_agv.Y_End);
*auto_x = _agv.X_End + 4;
*auto_y = _agv.Y_End + 4;
} else {
_agv.AutoGo = false;
*auto_x = _gpkt->Dx;
*auto_y = _gpkt->Dy;
}
ret = true;
}
}
}
}
}
delete[] data;
}
return ret;
}
void MovClass::stop_auto_go() {
_agv.AutoGo = false;
_agv.Continue = true;
}
void MovClass::continue_auto_go() {
_agv.AutoGo = _agv.Continue;
}
bool MovClass::auto_go_status() {
return _agv.AutoGo;
}
void MovClass::calc_xy() {
int16 xvector = 0;
int16 yvector = 0;
if (!_G(barriers)->getBarrierId(_gpkt->Dx, _gpkt->Dy)) {
int16 ende = 0;
int16 count = 0;
int16 min_x = -1;
int16 min_y = -1;
const int16 width = _G(room)->_barriers->getWidth();
const int16 height = _G(room)->_barriers->getHeight();
while (!ende) {
int16 min_steps = 30000;
int16 x = _gpkt->Dx - (count + 1) * 8;
int16 y = _gpkt->Dy - (count + 1) * 8;
for (int16 seite = 0; seite < 4; seite++) {
int16 anz = 2 + (count * 2);
switch (seite) {
case S_OBEN:
xvector = 8;
yvector = 0;
break;
case S_RECHTS:
xvector = 0;
yvector = 8;
break;
case S_UNTEN:
xvector = -8;
yvector = 0;
break;
case S_LINKS:
xvector = 0;
yvector = -8;
break;
default:
break;
}
for (int16 i = 0; i < anz; i++) {
if (x >= 0 && x < width * 8 &&
y >= 0 && y < height * 8) {
if (_G(barriers)->getBarrierId(x, y)) {
int16 aksteps = abs(_gpkt->Dx - x);
aksteps += abs(_gpkt->Dy - y);
if (aksteps < min_steps) {
min_steps = aksteps;
min_x = x;
min_y = y;
}
}
}
x += xvector;
y += yvector;
}
}
++count;
if (min_steps != 30000) {
ende = 1;
int16 tmp_feld = get_feld_nr(min_x, min_y);
get_feld_xy(tmp_feld, &_gpkt->Dx, &_gpkt->Dy);
_gpkt->Dx += 4;
_gpkt->Dy += 4;
}
}
}
}
short MovClass::calc_go(int16 src_feld, int16 *dst_feld) {
int16 new_vector = true;
ObjMov om;
MovInfo mi;
mi.Vorschub = _gpkt->Vorschub;
get_feld_xy(src_feld, &om.Xypos[0], &om.Xypos[1]);
get_feld_xy(*dst_feld, &mi.XyzEnd[0], &mi.XyzEnd[1]);
mi.XyzStart[0] = om.Xypos[0];
mi.XyzStart[1] = om.Xypos[1];
get_mov_vector(mi.XyzStart, mi.XyzEnd, mi.Vorschub, &om);
bool endFl = false;
int16 mov_ok = 0;
int16 steps = 0;
int16 abbruch = MOV_START;
while (!endFl && !abbruch) {
if (om.Count > 0) {
--om.Count;
int16 tmpx = om.Xyvo[0];
int16 tmpy = om.Xyvo[1];
int16 tmpz = om.Xyvo[2];
om.Xyna[0][0] += om.Xyna[0][1];
if (om.Xyna[0][1] < 0) {
if (om.Xyna[0][0] < -1000) {
om.Xyna[0][0] += 1000;
--tmpx;
}
} else if (om.Xyna[0][0] > 1000) {
om.Xyna[0][0] -= 1000;
++tmpx;
}
om.Xyna[1][0] += om.Xyna[1][1];
if (om.Xyna[1][1] < 0) {
if (om.Xyna[1][0] < -1000) {
om.Xyna[1][0] += 1000;
--tmpy;
}
} else if (om.Xyna[1][0] > 1000) {
om.Xyna[1][0] -= 1000;
++tmpy;
}
om.Xyna[2][0] += om.Xyna[2][1];
if (om.Xyna[2][1] < 0) {
if (om.Xyna[2][0] < -1000) {
om.Xyna[2][0] += 1000;
}
} else if (om.Xyna[2][0] > 1000) {
om.Xyna[2][0] -= 1000;
}
tmpz = 0;
if (!_G(barriers)->getBarrierId(om.Xypos[0] + tmpx + tmpz,
om.Xypos[1] + tmpy + tmpz)) {
if (!_G(barriers)->getBarrierId(om.Xypos[0] + tmpx + tmpz,
om.Xypos[1] + tmpz)) {
if (!_G(barriers)->getBarrierId(om.Xypos[0] + tmpz,
om.Xypos[1] + tmpy + tmpz)) {
abbruch = MOV_UNPASSABLE;
} else {
if (!tmpy) {
abbruch = MOV_UNPASSABLE;
} else if (abs(om.Xypos[1] - mi.XyzEnd[1]) <= abs(tmpy)) {
abbruch = MOV_FOUND;
} else {
mov_ok = MOV_Y;
}
}
} else {
if (!tmpx) {
abbruch = MOV_UNPASSABLE;
} else if (abs(om.Xypos[0] - mi.XyzEnd[0]) <= abs(tmpx)) {
abbruch = MOV_FOUND;
} else {
mov_ok = MOV_X;
}
}
} else {
++steps;
om.Xypos[0] += tmpx;
om.Xypos[1] += tmpy;
om.Xypos[2] += tmpz;
if (new_vector) {
new_vector = false;
mi.XyzStart[0] = om.Xypos[0];
mi.XyzStart[1] = om.Xypos[1];
get_mov_vector(mi.XyzStart, mi.XyzEnd, mi.Vorschub, &om);
}
if (om.Count == 0) {
abbruch = MOV_FOUND;
}
}
if (mov_ok) {
++steps;
if (mov_ok == MOV_X)
om.Xypos[0] += tmpx;
else
om.Xypos[1] += tmpy;
om.Xypos[2] += tmpz;
mi.XyzStart[0] = om.Xypos[0];
mi.XyzStart[1] = om.Xypos[1];
get_mov_vector(mi.XyzStart, mi.XyzEnd, mi.Vorschub, &om);
if (mov_ok == MOV_X) {
if (om.Xyvo[0] != 0)
new_vector = true;
} else {
if (om.Xyvo[1] != 0)
new_vector = true;
}
if (om.Count == 0) {
abbruch = MOV_FOUND;
}
mov_ok = false;
}
} else
endFl = true;
}
if (abbruch == MOV_UNPASSABLE)
*dst_feld = get_feld_nr(om.Xypos[0], om.Xypos[1]);
return steps;
}
void MovClass::get_mov_line() {
const int16 width = _G(room)->_barriers->getWidth();
const int16 height = _G(room)->_barriers->getHeight();
const int16 level = _G(room)->_barriers->getLevel();
const byte *data = _G(room)->_barriers->getData();
const byte *buffer = data + 6;
int16 ak_steps;
_gml.GotoFeld = -1;
_gml.MLineFeld = -1;
if (level > 1) {
buffer += (width * height) * _gpkt->AkMovEbene;
int16 start_feld = get_feld_nr(_gpkt->Sx, _gpkt->Sy);
int16 ende = 0;
int16 count = 0;
int16 min_steps = 30000;
int16 count_vect = width;
int16 y_richtung = Y_DOWN;
while (!ende) {
int16 tmp_feld = start_feld + count * count_vect;
if (_G(barriers)->getBarrierId(tmp_feld, data + 6)) {
int16 abbruch = 0;
int16 vector = 0;
while ((tmp_feld % width) < (width - 1) && !abbruch)
{
if (_G(barriers)->getBarrierId(tmp_feld + vector, data + 6)) {
tmp_feld += vector;
if (buffer[tmp_feld] == MOV_LINE_IDX) {
ak_steps = abs((tmp_feld % width) - (start_feld % width));
ak_steps += abs((tmp_feld / width) - (start_feld / width));
if (ak_steps < min_steps) {
min_steps = ak_steps;
_gml.GotoFeld = start_feld + count * count_vect;
_gml.MLineFeld = tmp_feld;
}
}
vector = RIGHT_VECT;
} else {
abbruch = MOV_UNPASSABLE;
}
}
tmp_feld = start_feld + count * count_vect;
vector = LEFT_VECT;
abbruch = 0;
while ((tmp_feld % width) > 0 && !abbruch) {
if (_G(barriers)->getBarrierId(tmp_feld + vector, data + 6)) {
tmp_feld += vector;
if (buffer[tmp_feld] == MOV_LINE_IDX) {
ak_steps = abs((tmp_feld % width) - (start_feld % width));
ak_steps += abs((tmp_feld / width) - (start_feld / width));
if (ak_steps < min_steps) {
min_steps = ak_steps;
_gml.GotoFeld = start_feld + count * count_vect;
_gml.MLineFeld = tmp_feld;
}
}
} else {
abbruch = MOV_UNPASSABLE;
}
}
++count;
} else {
if (y_richtung == Y_DOWN) {
y_richtung = Y_UP;
count = 1;
count_vect = -_G(room)->_barriers->getWidth();
} else
ende = 1;
}
}
}
delete[] data;
}
void MovClass::calc_mov_line_xit(int16 start_feld) {
const int16 width = _G(room)->_barriers->getWidth();
const int16 height = _G(room)->_barriers->getHeight();
const int16 level = _G(room)->_barriers->getLevel();
const byte *data = _G(room)->_barriers->getData();
int16 tmp_feld;
int16 i;
int16 dest_steps;
int16 k;
int16 TmpKnPkt[MAX_KNOTEN_PKT];
int16 dir_unerreicht = 0;
int16 KnPkt_unrreicht[MAX_KNOTEN_PKT];
int16 feld_unerreicht = 0;
int16 knoten_felder[MAX_KNOTEN_PKT][6];
for (i = 0; i < MAX_KNOTEN_PKT; i++)
TmpKnPkt[i] = -1;
if (level > 1) {
memset(knoten_felder, -1, MAX_KNOTEN_PKT * 6);
const byte *buffer = data + 6;
buffer += (width * height) * _gpkt->AkMovEbene;
_mle.Steps = 30000;
int16 min_step_unerreicht = 30000;
_mle.FNr = -1;
int16 ziel_feld = get_feld_nr(_gpkt->Dx, _gpkt->Dy);
int16 calc_feld = start_feld;
int16 last_feld = start_feld;
int16 steps = 0;
int16 found = 0;
int16 ak_knoten = -1;
int16 tbl_dir = 1;
int16 tbl_ptr = 0;
int16 knoten_flag = 0;
//found_min = 0;
int16 dir = 30000;
while (!found) {
tmp_feld = ziel_feld;
calc_go(calc_feld, &tmp_feld);
if (tmp_feld == ziel_feld) {
dest_steps = abs((ziel_feld % width) - (calc_feld % width));
dest_steps += abs((ziel_feld / width) - (calc_feld / width));
if (dest_steps < _mle.Steps) {
_mle.Steps = dest_steps;
_mle.FNr = calc_feld;
if (dir == 30000)
_mle.Direction = 0;
else
_mle.Direction = dir;
for (i = 0; i < MAX_KNOTEN_PKT; i++)
_mle.KnPkt[i] = TmpKnPkt[i];
}
} else {
dest_steps = abs((ziel_feld % width) - (tmp_feld % width));
dest_steps += abs((ziel_feld / width) - (tmp_feld / width));
if (dest_steps < min_step_unerreicht) {
min_step_unerreicht = dest_steps;
feld_unerreicht = tmp_feld;
if (dir == 30000)
dir_unerreicht = 0;
else
dir_unerreicht = dir;
for (i = 0; i < MAX_KNOTEN_PKT; i++)
KnPkt_unrreicht[i] = TmpKnPkt[i];
}
}
int16 ok = 0;
for (i = 0; i < 4 && !ok; i++) {
if (buffer[calc_feld + _vecTbl[tbl_ptr + i * tbl_dir]] == MOV_LINE_IDX)
{
if (calc_feld + _vecTbl[tbl_ptr + i * tbl_dir] != last_feld)
{
last_feld = calc_feld;
calc_feld += _vecTbl[tbl_ptr + i * tbl_dir];
++steps;
ok = 1;
if (dir == 30000) {
dir = _vecTbl[tbl_ptr + i * tbl_dir];
}
if (knoten_flag) {
TmpKnPkt[ak_knoten] = calc_feld;
knoten_felder[ak_knoten][tbl_ptr + i * tbl_dir] = calc_feld;
knoten_flag = false;
}
}
} else if (buffer[calc_feld + _vecTbl[tbl_ptr + i * tbl_dir]] == MOV_LINE_KNOTEN) {
if (calc_feld + _vecTbl[tbl_ptr + i * tbl_dir] != last_feld) {
if (dir == 30000) {
dir = _vecTbl[tbl_ptr + i * tbl_dir];
}
++ak_knoten;
for (k = 0; k < 6; k++)
knoten_felder[ak_knoten][k] = -1;
switch (tbl_ptr + i * tbl_dir) {
case MLE_UP:
k = MLE_DOWN;
break;
case MLE_RIGHT:
k = MLE_LEFT;
break;
case MLE_LEFT:
k = MLE_RIGHT;
break;
case MLE_DOWN:
k = MLE_UP;
break;
}
knoten_felder[ak_knoten][k] = calc_feld;
last_feld = calc_feld;
calc_feld += _vecTbl[tbl_ptr + i * tbl_dir];
knoten_felder[ak_knoten][4] = calc_feld;
++steps;
knoten_felder[ak_knoten][5] = steps;
knoten_flag = true;
ok = 1;
}
}
}
if (!ok) {
if (ak_knoten != -1)
{
ok = 0;
for (i = 0; i < 4 && !ok; i++) {
if (knoten_felder[ak_knoten][tbl_ptr + i * tbl_dir] == -1) {
tmp_feld = knoten_felder[ak_knoten][4];
if (buffer[tmp_feld + _vecTbl[tbl_ptr + i * tbl_dir]] == MOV_LINE_IDX)
{
last_feld = knoten_felder[ak_knoten][4];
calc_feld = tmp_feld + _vecTbl[tbl_ptr + i * tbl_dir];
TmpKnPkt[ak_knoten] = calc_feld;
knoten_felder[ak_knoten][tbl_ptr + i * tbl_dir] = calc_feld;
steps = knoten_felder[ak_knoten][5];
ok = 1;
}
}
}
if (!ok) {
--ak_knoten;
}
} else if (tbl_dir == 1) {
tbl_dir = -1;
tbl_ptr = 3;
dir = 30000;
//found_min = 0;
calc_feld = start_feld;
last_feld = start_feld;
} else {
found = 1;
if (_mle.FNr == -1) {
_mle.Steps = min_step_unerreicht;
_mle.FNr = feld_unerreicht;
_mle.Direction = dir_unerreicht;
for (i = 0; i < MAX_KNOTEN_PKT; i++)
_mle.KnPkt[i] = KnPkt_unrreicht[i];
get_feld_xy(feld_unerreicht, &_gpkt->Dx, &_gpkt->Dy);
_gpkt->Dx += 4;
_gpkt->Dy += 4;
}
}
}
}
}
delete[] data;
}
int16 MovClass::get_feld_nr(int16 x, int16 y) {
const int16 width = _G(room)->_barriers->getWidth();
x >>= 3;
y >>= 3;
return x + (y * width);
}
void MovClass::get_feld_xy(int16 fnr, int16 *x, int16 *y) {
const int16 width = _G(room)->_barriers->getWidth();
*x = (fnr % width);
*y = (fnr / width);
*x <<= 3;
*y <<= 3;
}
void MovClass::get_mov_vector(int16 *startXyz, int16 *endXyz, int16 vorschub, ObjMov *om) {
if (vorschub > 0) {
int16 x = startXyz[0];
int16 y = startXyz[1];
int16 z = startXyz[2];
int16 x1 = endXyz[0];
int16 y1 = endXyz[1];
int16 z1 = endXyz[2];
om->Xypos[0] = x;
om->Xypos[1] = y;
om->Xypos[2] = z;
x = x - x1;
y = y - y1;
z = z - z1;
uint8 xvector;
if (x < 0) {
xvector = 1;
--x;
} else {
xvector = 0;
++x;
}
uint8 yvector;
if (y < 0) {
yvector = 1;
--y;
} else {
yvector = 0;
++y;
}
uint8 zvector;
if (z < 0) {
zvector = 1;
--z;
} else {
zvector = 0;
++z;
}
int16 absx = abs(x);
int16 absy = abs(y);
int16 absz = abs(z);
float xstep;
float ystep;
if (absx < absy) {
xstep = (float)absx / ((float)absy / (float)vorschub);
ystep = vorschub;
om->Count = (int16)((float) y / (float)ystep);
} else {
xstep = vorschub;
ystep = (float)absy / ((float)absx / (float)vorschub);
om->Count = (int16)((float) x / (float)xstep);
}
float zstep;
om->Count = abs(om->Count);
if (!om->Count) {
zstep = (float)absz / 1.0;
} else
zstep = (float)absz / ((float)((abs)(om->Count)));
if (!xvector)
xstep = -xstep;
if (!yvector)
ystep = -ystep;
if (!zvector)
zstep = -zstep;
om->Xyvo[0] = (int16)xstep;
om->Xyvo[1] = (int16)ystep;
om->Xyvo[2] = (int16)zstep;
int16 tmp = (int16)((float)xstep * 1000.0);
om->Xyna[0][1] = tmp - (om->Xyvo[0] * 1000);
om->Xyna[0][0] = 0;
tmp = (int16)((float)ystep * 1000.0);
om->Xyna[1][1] = tmp - (om->Xyvo[1] * 1000);
om->Xyna[1][0] = 0;
tmp = (int16)((float)zstep * 1000.0);
om->Xyna[2][1] = tmp - (om->Xyvo[2] * 1000);
om->Xyna[2][0] = 0;
if (!om->Count) {
startXyz[0] = endXyz[0];
startXyz[1] = endXyz[1];
om->Xypos[0] = endXyz[0];
om->Xypos[1] = endXyz[1];
}
} else {
om->Count = 0;
om->Xypos[0] = startXyz[0];
om->Xypos[1] = startXyz[1];
om->Xypos[2] = startXyz[2];
om->Xyvo[0] = 0;
om->Xyvo[1] = 0;
om->Xyvo[2] = 0;
om->Xyna[0][1] = 0;
om->Xyna[0][0] = 0;
om->Xyna[1][1] = 0;
om->Xyna[1][0] = 0;
om->Xyna[2][1] = 0;
om->Xyna[2][0] = 0;
}
}
} // namespace Chewy

138
engines/chewy/movclass.h Normal file
View File

@@ -0,0 +1,138 @@
/* 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/>.
*
*/
#ifndef CHEWY_MOVCLASS_H
#define CHEWY_MOVCLASS_H
#include "common/scummsys.h"
namespace Chewy {
#define MAX_KNOTEN_PKT 15
#define MOV_LINE_IDX 28
#define MOV_LINE_KNOTEN 29
#define MOV_LINE_CROSS 30
#define MLE_UP 0
#define MLE_RIGHT 1
#define MLE_DOWN 2
#define MLE_LEFT 3
struct MovInfo {
int16 XyzStart[3] = { 0 };
int16 XyzEnd[3] = { 0 };
int16 HotX = 0;
int16 HotY = 0;
int16 HotMovX = 0;
int16 HotMovY = 0;
int16 Vorschub = 0;
int16 Delay = 0;
uint8 Id = 0;
uint8 Mode = 0;
};
struct ObjMov {
int16 Xypos[3] = { 0 };
int16 Xyvo[3] = { 0 };
int16 Xyna[3][2] = {{ 0 }};
int16 Count = 0;
int16 Delay = 0;
int16 _delayCount = 0;
int16 Phase = 0;
int16 PhNr = 0;
int16 PhAnz = 0;
int16 Xzoom = 0;
int16 Yzoom = 0;
int16 StNr = 0;
};
struct GotoPkt {
int16 Sx = 0;
int16 Sy = 0;
int16 Dx = 0;
int16 Dy = 0;
int16 AkMovEbene = 0;
int16 Vorschub = 0;
};
struct GotoMovLine {
int16 GotoFeld = 0;
int16 MLineFeld = 0;
};
struct MovLineExit {
int16 Steps = 0;
int16 Direction = 0;
int16 FNr = 0;
int16 KnPkt[MAX_KNOTEN_PKT] = { 0 };
};
struct AutoGoVar {
bool AutoGo = false;
bool Continue = false;
int16 PktAnz = 0;
int16 Start = 0;
int16 X_End = 0;
int16 Y_End = 0;
int16 LastFeld = 0;
int16 AkFeld = 0;
int16 AkKnoten = 0;
};
class MovClass {
public:
MovClass();
~MovClass();
void goto_xy(GotoPkt *gpkt);
int16 calc_auto_go(int16 x, int16 y, int16 *auto_x, int16 *auto_y);
void stop_auto_go();
void continue_auto_go();
bool auto_go_status();
void get_mov_vector(int16 *startXyz, int16 *endXyz, int16 vorschub, ObjMov *om);
private:
void calc_xy();
int16 get_feld_nr(int16 x, int16 y);
void get_feld_xy(int16 fnr, int16 *x, int16 *y);
int16 calc_go(int16 src_feld, int16 *dst_feld);
void get_mov_line();
void calc_mov_line_xit(int16 start_feld);
int16 _feld1knoten = 0;
int16 _plotDelay = 0;
AutoGoVar _agv;
MovLineExit _mle;
GotoMovLine _gml;
GotoPkt *_gpkt = nullptr;
int16 _vecTbl[4];
};
} // namespace Chewy
#endif

57
engines/chewy/ngstypes.h Normal file
View File

@@ -0,0 +1,57 @@
/* 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/>.
*
*/
#ifndef CHEWY_NGSTYPES_H
#define CHEWY_NGSTYPES_H
#include "graphics/screen.h"
namespace Chewy {
struct TafInfo {
int16 count = 0;
byte *palette = nullptr;
int16 *correction = nullptr;
byte **image = nullptr;
};
struct TafSeqInfo {
int16 count = 0;
int16 *correction = nullptr;
byte **image = nullptr;
};
struct MouseInfo {
int16 button = 0;
};
struct MusicInfo {
int16 playing = 0;
int16 play_mode = 0;
int16 pattern_line = 0;
int16 sequence_pos = 0;
int16 cur_pattnr = 0;
char *cur_pattern = nullptr;
};
} // namespace Chewy
#endif

526
engines/chewy/object.cpp Normal file
View File

@@ -0,0 +1,526 @@
/* 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/>.
*
*/
#include "chewy/defines.h"
#include "chewy/globals.h"
#include "chewy/object.h"
namespace Chewy {
static const int16 ACTION_OBJ_TBL[] = {
30000, 5, 8, 13, 38, 41,
30001, 28, 29,
30002, 31, 35, 56, 5088,
30003, 38, 39, 11, 15, 13, 41, 42,
30004, 43, 61,
30005, 67, 5040, 5088,
30006, 77,
30007, 4,
30008, 5004,
32000
};
static const int16 SIB_ZUSTAND_TBL[] = {
30000, 46, 0,
30001, 6,
30002, 7,
30003, 8,
30004, 12, 13,
30005, 2, 3,
30006, 1,
30007, 41, 45, 46, 47, 48,
30008, 7, 60, 23,
30009, 40, 41, 42, 43, 44, 45, 46, 47, 48,
30010, 4, 5,
30011, 8, 9,
30012, 7, 10,
30013, 3, 5, 6,
32000
};
Object::Object(GameState *sp) {
_maxInventoryObj = 0;
_maxStaticInventory = 0;
_maxExit = 0;
_player = sp;
_rmo = sp->room_m_obj;
_rsi = sp->room_s_obj;
_roomExit = sp->room_e_obj;
}
Object::~Object() {
}
int16 Object::load(const char *filename, RoomMovObject *rmo) {
Common::File f;
if (f.open(filename)) {
if (!_iibFileHeader.load(&f)) {
error("Object::load error");
}
if (!scumm_strnicmp(_iibFileHeader.Id, "IIB", 3)) {
if (_iibFileHeader.Size) {
assert(_iibFileHeader.Size % RoomMovObject::SIZE() == 0);
bool valid = true;
for (uint i = 0; i < _iibFileHeader.Size / RoomMovObject::SIZE() && valid; ++i, ++rmo) {
valid = rmo->load(&f);
}
if (!valid)
error("Object::load error");
_maxInventoryObj = (int16)_iibFileHeader.Size / RoomMovObject::SIZE();
} else
_maxInventoryObj = 0;
} else {
error("Object::load error");
}
f.close();
} else {
error("Object::load error");
}
return _maxInventoryObj;
}
int16 Object::load(const char *filename, RoomStaticInventory *rsi) {
Common::File f;
if (f.open(filename)) {
if (!_sibFileHeader.load(&f)) {
error("Object::load error");
}
if (!scumm_strnicmp(_sibFileHeader._id, "SIB", 3)) {
if (_sibFileHeader._nr) {
bool valid = true;
for (int i = 0; i < _sibFileHeader._nr && valid; ++i, ++rsi) {
valid = rsi->load(&f);
}
if (!valid)
error("Object::load error");
_maxStaticInventory = _sibFileHeader._nr;
} else
_maxStaticInventory = 0;
} else {
error("Object::load error");
}
f.close();
} else {
error("Object::load error");
}
return _maxStaticInventory;
}
int16 Object::load(const char *filename, RoomExit *roomExit) {
Common::File f;
if (f.open(filename)) {
if (!_eibFileHeader.load(&f)) {
error("Object::load error");
}
if (!scumm_strnicmp(_eibFileHeader._id, "EIB", 3)) {
if (_sibFileHeader._nr) {
bool valid = true;
for (int i = 0; i < _eibFileHeader._nr && valid; ++i, ++roomExit) {
valid = roomExit->load(&f);
}
if (!valid)
error("Object::load error");
_maxExit = _eibFileHeader._nr;
} else
_maxExit = 0;
} else {
error("Object::load error");
}
f.close();
} else {
error("Object::load error");
}
return _maxExit;
}
void Object::sort() {
mov_obj_room[0] = 0;
spieler_invnr[0] = 0;
for (short i = 0; i < MAX_MOV_OBJ; i++) {
if (_rmo[i].RoomNr != -1) {
if (_rmo[i].RoomNr == 255) {
++spieler_invnr[0];
spieler_invnr[spieler_invnr[0]] = i;
} else if (_rmo[i].RoomNr == _player->_personRoomNr[P_CHEWY]) {
++mov_obj_room[0];
mov_obj_room[mov_obj_room[0]] = i;
}
}
}
}
void Object::free_inv_spr(byte **inv_spr_adr) {
for (int16 i = 0; i < MAX_MOV_OBJ; i++)
if (inv_spr_adr[i] != 0) {
free(inv_spr_adr[i]);
inv_spr_adr[i] = 0;
}
}
int16 Object::is_sib_mouse(int16 mouse_x, int16 mouse_y) {
int16 ret = -1;
for (int16 i = 0; i < _maxStaticInventory && ret == -1; i++) {
if (_rsi[i].RoomNr == _player->_personRoomNr[P_CHEWY] && _rsi[i].HideSib == false) {
if (mouse_x >= _rsi[i].X &&
mouse_x <= (_rsi[i].X + _rsi[i].XOff) &&
mouse_y >= _rsi[i].Y &&
mouse_y <= (_rsi[i].Y + _rsi[i].YOff))
ret = i;
}
}
return ret;
}
int16 Object::is_iib_mouse(int16 mouse_x, int16 mouse_y) {
int16 ret = -1;
for (int16 i = 1; i < mov_obj_room[0] + 1 && ret == -1; i++) {
if (_rmo[mov_obj_room[i]].X != -1 &&
mouse_x >= _rmo[mov_obj_room[i]].X &&
mouse_x <= (_rmo[mov_obj_room[i]].X + _rmo[mov_obj_room[i]].XOff) &&
mouse_y >= _rmo[mov_obj_room[i]].Y &&
mouse_y <= (_rmo[mov_obj_room[i]].Y + _rmo[mov_obj_room[i]].YOff))
ret = mov_obj_room[i];
}
return ret;
}
int16 Object::iib_txt_nr(int16 inv_nr) {
return _rmo[inv_nr].TxtNr;
}
int16 Object::sib_txt_nr(int16 sib_nr) {
return _rsi[sib_nr].TxtNr;
}
int16 Object::action_iib_iib(int16 maus_obj_nr, int16 test_obj_nr) {
int16 ret = NO_ACTION;
int16 tmp1 = maus_obj_nr;
int16 tmp2 = test_obj_nr;
bool actionFl = false;
for (int16 j = 0; j < 2 && !actionFl; j++) {
if (j) {
tmp1 = test_obj_nr;
tmp2 = maus_obj_nr;
}
if (_rmo[tmp1].ActionObj != -1) {
if (_rmo[tmp1].ActionObj < 30000 && _rmo[tmp1].ActionObj == tmp2) {
actionFl = true;
} else if (_rmo[tmp1].ActionObj >= 30000) {
int16 i = 0;
while (ACTION_OBJ_TBL[i] != _rmo[tmp1].ActionObj &&
ACTION_OBJ_TBL[i] != 32000) {
++i;
}
if (ACTION_OBJ_TBL[i] != 32000) {
++i;
int16 ok = 0;
while (ACTION_OBJ_TBL[i] < 30000 && !ok) {
if (ACTION_OBJ_TBL[i] == tmp2 + 5000) {
ok = 1;
actionFl = true;
}
++i;
}
}
}
}
}
if (actionFl && calc_rmo_flip_flop(tmp2))
ret = (tmp2 == test_obj_nr) ? OBJECT_2 : OBJECT_1;
return ret;
}
int16 Object::action_iib_sib(int16 maus_obj_nr, int16 test_obj_nr) {
int16 action_flag = NO_ACTION;
if (_rmo[maus_obj_nr].ActionObj != -1) {
if (_rmo[maus_obj_nr].ActionObj < 30000 &&
_rmo[maus_obj_nr].ActionObj == test_obj_nr) {
action_flag = OBJECT_2;
} else if (_rmo[maus_obj_nr].ActionObj >= 30000) {
int16 i = 0;
while (ACTION_OBJ_TBL[i] != _rmo[maus_obj_nr].ActionObj &&
ACTION_OBJ_TBL[i] != 32000) {
++i;
}
if (ACTION_OBJ_TBL[i] != 32000) {
++i;
int16 ok = 0;
while (ACTION_OBJ_TBL[i] < 30000 && !ok) {
if (ACTION_OBJ_TBL[i] == test_obj_nr) {
ok = 1;
action_flag = OBJECT_2;
}
++i;
}
}
}
}
if (action_flag == OBJECT_2 && !calc_rsi_flip_flop(test_obj_nr))
action_flag = NO_ACTION;
return action_flag;
}
void Object::hide_sib(int16 nr) {
_rsi[nr].HideSib = true;
}
void Object::show_sib(int16 nr) {
_rsi[nr].HideSib = false;
}
void Object::calc_all_static_detail() {
for (int16 i = 0; i < _maxStaticInventory; i++) {
calc_static_detail(i);
}
}
void Object::calc_static_detail(int16 det_nr) {
int16 i;
int16 n;
if (_rsi[det_nr].RoomNr == _player->_personRoomNr[P_CHEWY]) {
int16 nr = _rsi[det_nr].StaticAk;
if (nr != -1) {
if (nr >= 30000) {
i = 0;
while (SIB_ZUSTAND_TBL[i] != nr && SIB_ZUSTAND_TBL[i] != 32000) {
++i;
}
if (SIB_ZUSTAND_TBL[i] != 32000) {
++i;
while (SIB_ZUSTAND_TBL[i] < 30000) {
nr = SIB_ZUSTAND_TBL[i];
if (nr >= 40) {
n = nr - 40;
AniDetailInfo *adi = _G(det)->getAniDetail(n);
if (adi->repeat)
_G(det)->startDetail(n, 0, ANI_FRONT);
else
_G(det)->startDetail(n, 1, ANI_FRONT);
} else
_G(det)->showStaticSpr(nr);
++i;
}
}
} else if (nr >= 40) {
n = nr - 40;
AniDetailInfo *adi = _G(det)->getAniDetail(n);
if (adi->repeat)
_G(det)->startDetail(n, 0, ANI_FRONT);
else
_G(det)->startDetail(n, 1, ANI_FRONT);
} else {
_G(det)->showStaticSpr(nr);
}
}
nr = _rsi[det_nr].StaticOff;
if (nr != -1) {
if (nr >= 30000) {
i = 0;
while (SIB_ZUSTAND_TBL[i] != nr && SIB_ZUSTAND_TBL[i] != 32000) {
++i;
}
if (SIB_ZUSTAND_TBL[i] != 32000) {
++i;
while (SIB_ZUSTAND_TBL[i] < 30000) {
nr = SIB_ZUSTAND_TBL[i];
if (nr >= 40)
_G(det)->stopDetail(nr - 40);
else
_G(det)->hideStaticSpr(nr);
++i;
}
}
} else if (nr >= 40)
_G(det)->stopDetail(nr - 40);
else {
_G(det)->hideStaticSpr(nr);
}
}
}
}
int16 Object::calc_static_use(int16 nr) {
int16 ret;
switch (_rsi[nr].ZustandAk) {
case OBJZU_AUF:
case OBJZU_ZU:
case OBJZU_AN:
case OBJZU_AUS:
if (calc_rsi_flip_flop(nr))
ret = OBJECT_1;
else
ret = NO_ACTION;
break;
case SIB_GET_INV:
ret = SIB_GET_INV;
break;
default:
ret = NO_ACTION;
break;
}
return ret;
}
int16 Object::calc_rsi_flip_flop(int16 nr) {
int16 ret = true;
if (_rsi[nr].ZustandFlipFlop > 0 && _rsi[nr].HideSib == false) {
int16 tmp = _rsi[nr].ZustandAk;
_rsi[nr].ZustandAk = _rsi[nr].ZustandOff;
_rsi[nr].ZustandOff = tmp;
tmp = _rsi[nr].StaticAk;
_rsi[nr].StaticAk = _rsi[nr].StaticOff;
_rsi[nr].StaticOff = tmp;
if (_rsi[nr].AniFlag == 255 && _rsi[nr].AutoMov == 255)
calc_static_detail(nr);
if (_rsi[nr].ZustandFlipFlop != ENDLOS_FLIP_FLOP) {
--_rsi[nr].ZustandFlipFlop;
}
} else {
ret = false;
}
return ret;
}
void Object::set_rsi_flip_flop(int16 nr, int16 anz) {
_rsi[nr].ZustandFlipFlop = anz;
}
int16 Object::calc_rmo_flip_flop(int16 nr) {
int16 ret;
if (_rmo[nr].ZustandFlipFlop > 0) {
ret = true;
int16 tmp = _rmo[nr].ZustandAk;
_rmo[nr].ZustandAk = _rmo[nr].ZustandOff;
_rmo[nr].ZustandOff = tmp;
if (_rmo[nr].ZustandFlipFlop != ENDLOS_FLIP_FLOP) {
--_rmo[nr].ZustandFlipFlop;
}
} else
ret = false;
return ret;
}
int16 Object::del_obj_use(int16 nr) {
int16 ret;
if (_rmo[nr].Del == 1) {
_rmo[nr].RoomNr = -1;
sort();
ret = true;
} else {
ret = false;
if (_rmo[nr].Del != 255) {
--_rmo[nr].Del;
}
}
return ret;
}
void Object::addInventory(int16 nr, RaumBlk *Rb) {
_player->room_m_obj[nr].RoomNr = 255;
sort();
_G(room)->calc_invent(Rb, _player);
}
void Object::delInventory(int16 nr, RaumBlk *Rb) {
_player->room_m_obj[nr].RoomNr = -1;
sort();
}
void Object::changeInventory(int16 old_inv, int16 new_inv, RaumBlk *Rb) {
_player->room_m_obj[old_inv].RoomNr = -1;
_player->room_m_obj[new_inv].RoomNr = 255;
sort();
_G(room)->calc_invent(Rb, _player);
}
void Object::setInventory(int16 nr, int16 x, int16 y, int16 automov, RaumBlk *Rb) {
++mov_obj_room[0];
mov_obj_room[mov_obj_room[0]] = nr;
_player->room_m_obj[nr].RoomNr = _player->_personRoomNr[P_CHEWY];
_player->room_m_obj[nr].X = x;
_player->room_m_obj[nr].Y = y;
_player->room_m_obj[nr].AutoMov = automov;
_G(room)->calc_invent(Rb, _player);
sort();
}
bool Object::checkInventory(int16 nr) {
bool ret = false;
for (int16 i = 0; i < spieler_invnr[0] && !ret; i++) {
if (spieler_invnr[i + 1] == nr)
ret = true;
}
return ret;
}
int16 Object::is_exit(int16 mouse_x, int16 mouse_y) {
int16 ret = -1;
for (int16 i = 0; i < _maxExit && ret == -1; i++) {
if (_roomExit[i].RoomNr == _player->_personRoomNr[P_CHEWY]) {
if (mouse_x >= _roomExit[i].X &&
mouse_x <= (_roomExit[i].X + _roomExit[i].XOff) &&
mouse_y >= _roomExit[i].Y &&
mouse_y <= (_roomExit[i].Y + _roomExit[i].YOff)) {
ret = i;
}
}
}
return ret;
}
} // namespace Chewy

87
engines/chewy/object.h Normal file
View File

@@ -0,0 +1,87 @@
/* 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/>.
*
*/
#ifndef CHEWY_OBJECT_H
#define CHEWY_OBJECT_H
#include "chewy/object_extra.h"
namespace Chewy {
#define ENDLOS_FLIP_FLOP 255
#define LOAD_NEW_OBJ 1
#define NO_ACTION 0
#define OBJECT_1 1
#define OBJECT_2 2
class Object {
public:
Object(GameState *sp);
~Object();
short load(const char *filename, RoomMovObject *rmo);
int16 load(const char *filename, RoomStaticInventory *rsi);
int16 load(const char *filename, RoomExit *roomExit);
void sort();
void free_inv_spr(byte **inv_spr_adr);
int16 is_sib_mouse(int16 mouse_x, int16 mouse_y);
int16 is_iib_mouse(int16 mouse_x, int16 mouse_y);
int16 iib_txt_nr(int16 inv_nr);
int16 sib_txt_nr(int16 sib_nr);
int16 action_iib_iib(int16 maus_obj_nr, int16 test_obj_nr);
int16 action_iib_sib(int16 maus_obj_nr, int16 test_obj_nr);
void hide_sib(int16 nr);
void show_sib(int16 nr);
void calc_all_static_detail();
void calc_static_detail(int16 det_nr);
int16 calc_static_use(int16 nr);
int16 del_obj_use(int16 nr);
int16 calc_rsi_flip_flop(int16 nr);
void set_rsi_flip_flop(int16 nr, int16 anz);
void addInventory(int16 nr, RaumBlk *Rb);
void delInventory(int16 nr, RaumBlk *Rb);
void changeInventory(int16 old_inv, int16 new_inv, RaumBlk *Rb);
void setInventory(int16 nr, int16 x, int16 y, int16 automov, RaumBlk *Rb);
bool checkInventory(int16 nr);
int16 is_exit(int16 mouse_x, int16 mouse_y);
uint8 mov_obj_room[MAX_MOV_OBJ + 1];
uint8 spieler_invnr[MAX_MOV_OBJ + 1];
private:
int16 calc_rmo_flip_flop(int16 nr);
IibFileHeader _iibFileHeader;
SibFileHeader _sibFileHeader;
EibFileHeader _eibFileHeader;
int16 _maxInventoryObj;
int16 _maxStaticInventory;
int16 _maxExit;
GameState *_player;
RoomMovObject *_rmo;
RoomStaticInventory *_rsi;
RoomExit *_roomExit;
};
} // namespace Chewy
#endif

View File

@@ -0,0 +1,140 @@
/* 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/>.
*
*/
#include "chewy/object_extra.h"
namespace Chewy {
bool RoomMovObject::load(Common::SeekableReadStream *src) {
Common::Serializer s(src, nullptr);
synchronize(s);
return true;
}
void RoomMovObject::synchronize(Common::Serializer &s) {
s.syncAsSint16LE(RoomNr);
s.syncAsSint16LE(X);
s.syncAsSint16LE(Y);
s.syncAsByte(XOff);
s.syncAsByte(YOff);
s.syncAsSint16LE(TxtNr);
s.syncAsSint16LE(NeuObj);
s.syncAsSint16LE(ActionObj);
s.syncAsByte(ZustandAk);
s.syncAsByte(ZustandOff);
s.syncAsByte(ZustandFlipFlop);
s.syncAsByte(AutoMov);
s.syncAsByte(AniFlag);
s.syncAsByte(Del);
s.syncAsByte(Attribut);
s.syncAsByte(HeldHide);
s.syncAsSint16LE(ZEbene);
}
bool IibFileHeader::load(Common::SeekableReadStream *src) {
src->read(Id, 4);
src->read(Tafname, 14);
Size = src->readUint32LE();
return true;
}
IibFileHeader::IibFileHeader() {
memset(Id, 0, 4);
memset(Tafname, 0, 14);
Size = 0;
}
bool RoomStaticInventory::load(Common::SeekableReadStream *src) {
Common::Serializer s(src, nullptr);
synchronize(s);
return true;
}
void RoomStaticInventory::synchronize(Common::Serializer &s) {
s.syncAsSint16LE(RoomNr);
s.syncAsSint16LE(X);
s.syncAsSint16LE(Y);
s.syncAsByte(XOff);
s.syncAsByte(YOff);
s.syncAsSint16LE(InvNr);
s.syncAsSint16LE(TxtNr);
s.syncAsByte(HideSib);
s.syncAsByte(Dummy);
s.syncAsByte(ZustandAk);
s.syncAsByte(ZustandOff);
s.syncAsByte(ZustandFlipFlop);
s.syncAsByte(AutoMov);
s.syncAsByte(AniFlag);
s.syncAsByte(HeldHide);
s.syncAsSint16LE(StaticAk);
s.syncAsSint16LE(StaticOff);
}
bool SibFileHeader::load(Common::SeekableReadStream *src) {
src->read(_id, 4);
_nr = src->readUint16LE();
return true;
}
SibFileHeader::SibFileHeader() {
for (int i = 0; i < 4; ++i) {
_id[i] = 0;
}
_nr = 0;
}
bool RoomExit::load(Common::SeekableReadStream *src) {
Common::Serializer s(src, nullptr);
synchronize(s);
return true;
}
void RoomExit::synchronize(Common::Serializer &s) {
s.syncAsSint16LE(RoomNr);
s.syncAsSint16LE(X);
s.syncAsSint16LE(Y);
s.syncAsByte(XOff);
s.syncAsByte(YOff);
s.syncAsSint16LE(Exit);
s.syncAsByte(ExitMov);
s.syncAsByte(AutoMov);
s.syncAsByte(Attribut);
s.syncAsByte(dummy);
}
bool EibFileHeader::load(Common::SeekableReadStream *src) {
src->read(_id, 4);
_nr = src->readSint16LE();
return true;
}
EibFileHeader::EibFileHeader() {
for (int i = 0; i < 4; ++i) {
_id[i] = 0;
}
_nr = 0;
}
} // namespace Chewy

View File

@@ -0,0 +1,139 @@
/* 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/>.
*
*/
#ifndef CHEWY_OBJECT_EXTRA_H
#define CHEWY_OBJECT_EXTRA_H
#include "common/serializer.h"
#include "common/stream.h"
namespace Chewy {
#define OBJZU_AUF 0
#define OBJZU_ZU 1
#define OBJZU_AN 2
#define OBJZU_AUS 3
#define OBJZU_LOCKED 5
#define OBJZU_GEOEFFNET 6
#define OBJZU_NASS 7
#define OBJZU_TROCKEN 8
#define OBJZU_OELIG 9
#define OBJZU_HEISS 10
#define OBJZU_KALT 11
#define OBJZU_LEER 12
#define OBJZU_VOLL 13
#define OBJZU_UNDICHT 14
#define OBJZU_KLEMMT 15
#define SIB_GET_INV 16
struct RoomMovObject {
int16 RoomNr = 0;
int16 X = 0;
int16 Y = 0;
uint8 XOff = 0;
uint8 YOff = 0;
int16 TxtNr = 0;
int16 NeuObj = 0;
int16 ActionObj = 0;
uint8 ZustandAk = 0;
uint8 ZustandOff = 0;
uint8 ZustandFlipFlop = 0;
uint8 AutoMov = 0;
uint8 AniFlag = 0;
uint8 Del = 0;
uint8 Attribut = 0;
uint8 HeldHide = 0;
int16 ZEbene = 0;
void synchronize(Common::Serializer &s);
bool load(Common::SeekableReadStream *src);
static constexpr int SIZE() { return 24; }
};
struct IibFileHeader {
char Id[4];
char Tafname[14];
uint32 Size;
bool load(Common::SeekableReadStream *src);
IibFileHeader();
};
struct RoomStaticInventory {
int16 RoomNr = 0;
int16 X = 0;
int16 Y = 0;
uint8 XOff = 0;
uint8 YOff = 0;
int16 InvNr = 0;
int16 TxtNr = 0;
uint8 HideSib = 0;
uint8 Dummy = 0;
uint8 ZustandAk = 0;
uint8 ZustandOff = 0;
uint8 ZustandFlipFlop = 0;
uint8 AutoMov = 0;
uint8 AniFlag = 0;
uint8 HeldHide = 0;
int16 StaticAk = 0;
int16 StaticOff = 0;
void synchronize(Common::Serializer &s);
bool load(Common::SeekableReadStream *src);
};
struct SibFileHeader {
char _id[4];
int16 _nr;
bool load(Common::SeekableReadStream *src);
SibFileHeader();
};
struct RoomExit {
int16 RoomNr = 0;
int16 X = 0;
int16 Y = 0;
uint8 XOff = 0;
uint8 YOff = 0;
int16 Exit = 0;
uint8 ExitMov = 0;
uint8 AutoMov = 0;
uint8 Attribut = 0;
uint8 dummy = 0;
void synchronize(Common::Serializer &s);
bool load(Common::SeekableReadStream *src);
};
struct EibFileHeader {
char _id[4];
int16 _nr;
bool load(Common::SeekableReadStream *src);
EibFileHeader();
};
} // namespace Chewy
#endif

1298
engines/chewy/r_event.cpp Normal file

File diff suppressed because it is too large Load Diff

444
engines/chewy/resource.cpp Normal file
View File

@@ -0,0 +1,444 @@
/* 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/>.
*
*/
#include "common/debug.h"
#include "common/stream.h"
#include "common/substream.h"
#include "common/textconsole.h"
#include "graphics/surface.h"
#include "chewy/atds.h"
#include "chewy/chewy.h"
#include "chewy/resource.h"
namespace Chewy {
Resource::Resource(const Common::Path &filename) {
const uint32 headerGeneric = MKTAG('N', 'G', 'S', '\0');
const uint32 headerTxtDec = MKTAG('T', 'C', 'F', '\0');
const uint32 headerTxtEnc = MKTAG('T', 'C', 'F', '\1');
const uint32 headerSprite = MKTAG('T', 'A', 'F', '\0');
const uint32 headerBarrier = MKTAG('G', 'E', 'P', '\0');
_stream.open(filename);
Common::String basename = filename.baseName();
basename.toLowercase();
const uint32 header = _stream.readUint32BE();
const bool isText = (header == headerTxtDec || header == headerTxtEnc);
const bool isSprite = (header == headerSprite);
//const bool isSpeech = basename.contains("speech.tvp");
const bool isBarrier = (header == headerBarrier);
if (header != headerGeneric && !isSprite && !isText && !isBarrier)
error("Invalid resource - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
if (isText) {
_resType = kResourceTCF;
_encrypted = (header == headerTxtEnc);
} else if (isSprite) {
initSprite(filename);
return;
} else if (isBarrier) {
_resType = kResourceGEP;
_encrypted = false;
} else {
_resType = (ResourceType)_stream.readUint16LE();
_encrypted = false;
}
if (basename.contains("atds.tap"))
_encrypted = true;
_chunkCount = _stream.readUint16LE();
_chunkList.resize(_chunkCount);
if (header == headerGeneric) {
// NGS files have an index at the end
_stream.seek(-(int)(_chunkCount * sizeof(uint32)), SEEK_END);
for (uint i = 0; i < _chunkCount; i++) {
Chunk &cur = _chunkList[i];
cur.pos = _stream.readUint32LE();
}
}
for (uint i = 0; i < _chunkCount; i++) {
Chunk &cur = _chunkList[i];
if (header == headerGeneric)
_stream.seek(cur.pos - 6);
cur.size = _stream.readUint32LE();
if (isText) {
cur.type = kResourceUnknown;
cur.num = _stream.readUint16LE();
} else if (isBarrier) {
cur.type = kResourceUnknown;
cur.num = i;
cur.size += 6;
} else {
cur.type = (ResourceType)_stream.readUint16LE();
cur.num = 0;
}
cur.pos = _stream.pos();
// TODO: Is this workaround necessary anymore
// with the stream offset fixes
#if 0
// WORKAROUND: Patch invalid speech sample
if (isSpeech && i == 2277 && cur.size == 57028) {
cur.size = 152057;
_stream.skip(cur.size);
_chunkList.push_back(cur);
_chunkList.push_back(cur);
continue;
}
#endif
if (header != headerGeneric)
_stream.skip(cur.size);
}
_spriteCorrectionsCount = 0;
_spriteCorrectionsTable = nullptr;
}
Resource::~Resource() {
_chunkList.clear();
_stream.close();
delete[] _spriteCorrectionsTable;
_spriteCorrectionsTable = nullptr;
}
uint32 Resource::getChunkCount() const {
return _chunkList.size();
}
Chunk *Resource::getChunk(uint num) {
assert(num < _chunkList.size());
return &_chunkList[num];
}
uint32 Resource::findLargestChunk(uint start, uint end) {
uint32 maxSize = 0;
for (uint i = start; i < end; i++) {
if (_chunkList[i].size > maxSize)
maxSize = _chunkList[i].size;
}
return maxSize;
}
uint8 *Resource::getChunkData(uint num) {
assert(num < _chunkList.size());
Chunk *chunk = &_chunkList[num];
uint8 *data = new uint8[chunk->size];
_stream.seek(chunk->pos, SEEK_SET);
_stream.read(data, chunk->size);
if (_encrypted)
decrypt(data, chunk->size);
return data;
}
void Resource::initSprite(const Common::Path &filename) {
_resType = kResourceTAF;
_encrypted = false;
/*screenMode = */_stream.readUint16LE();
_chunkCount = _stream.readUint16LE();
_allSize = _stream.readUint32LE();
_stream.read(_spritePalette, 3 * 256);
uint32 nextSpriteOffset = _stream.readUint32LE();
_spriteCorrectionsCount = _stream.readUint16LE();
// Sometimes there's a filler byte
if ((int32)nextSpriteOffset == _stream.pos() + 1)
_stream.skip(1);
if ((int32)nextSpriteOffset != _stream.pos())
error("Invalid sprite resource - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
for (uint i = 0; i < _chunkCount; i++) {
Chunk cur;
cur.pos = _stream.pos();
cur.type = kResourceTAF;
cur.num = 0;
_stream.skip(2 + 2 + 2);
nextSpriteOffset = _stream.readUint32LE();
uint32 spriteImageOffset = _stream.readUint32LE();
_stream.skip(1);
if ((int32)spriteImageOffset != _stream.pos())
error("Invalid sprite resource - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
cur.size = nextSpriteOffset - cur.pos - 15;
_stream.skip(cur.size);
_chunkList.push_back(cur);
if (_stream.err())
error("Sprite stream error - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
}
_spriteCorrectionsTable = new uint16[_chunkCount * 2];
for (uint i = 0; i < _chunkCount; i++) {
_spriteCorrectionsTable[i * 2] = _stream.readUint16LE();
_spriteCorrectionsTable[i * 2 + 1] = _stream.readUint16LE();
}
}
void Resource::unpackRLE(uint8 *buffer, uint32 compressedSize, uint32 uncompressedSize) {
uint32 outPos = 0;
for (uint i = 0; i < (compressedSize) / 2 && outPos < uncompressedSize; i++) {
uint8 count = _stream.readByte();
uint8 value = _stream.readByte();
for (uint8 j = 0; j < count && outPos < uncompressedSize; j++) {
buffer[outPos++] = value;
}
}
}
void Resource::decrypt(uint8 *data, uint32 size) {
uint8 *c = data;
for (uint i = 0; i < size; i++) {
*c = -(*c);
++c;
}
}
TAFChunk *SpriteResource::getSprite(uint num) {
assert(num < _chunkList.size());
Chunk *chunk = &_chunkList[num];
TAFChunk *taf = new TAFChunk();
_stream.seek(chunk->pos, SEEK_SET);
taf->compressionFlag = _stream.readUint16LE();
taf->width = _stream.readUint16LE();
taf->height = _stream.readUint16LE();
_stream.skip(4 + 4 + 1);
taf->data = new uint8[taf->width * taf->height];
if (!taf->compressionFlag)
_stream.read(taf->data, chunk->size);
else
unpackRLE(taf->data, chunk->size, taf->width * taf->height);
return taf;
}
uint32 SpriteResource::getSpriteData(uint num, uint8 **buf, bool initBuffer) {
TAFChunk *sprite = getSprite(num);
uint32 size = sprite->width * sprite->height;
if (initBuffer)
*buf = (byte *)malloc(size + 4);
// Sprite width and height is piggy-banked inside the sprite data
uint16 *memPtr = (uint16 *)*buf;
memPtr[0] = sprite->width;
memPtr[1] = sprite->height;
memcpy(*buf + 4, sprite->data, size);
delete sprite;
return size + 4;
}
TBFChunk *BackgroundResource::getImage(uint num, bool fixPalette) {
assert(num < _chunkList.size());
Chunk *chunk = &_chunkList[num];
TBFChunk *tbf = new TBFChunk();
_stream.seek(chunk->pos, SEEK_SET);
if (_stream.readUint32BE() != MKTAG('T', 'B', 'F', '\0'))
error("Corrupt TBF resource");
tbf->screenMode = _stream.readUint16LE();
tbf->compressionFlag = _stream.readUint16LE();
tbf->size = _stream.readUint32LE();
tbf->width = _stream.readUint16LE();
tbf->height = _stream.readUint16LE();
for (int j = 0; j < 3 * 256; j++)
tbf->palette[j] = fixPalette ? (_stream.readByte() << 2) & 0xff : _stream.readByte();
tbf->data = new uint8[tbf->size];
if (!tbf->compressionFlag)
_stream.read(tbf->data, chunk->size);
else
unpackRLE(tbf->data, chunk->size, tbf->size);
return tbf;
}
SoundChunk *SoundResource::getSound(uint num) {
assert(num < _chunkList.size());
Chunk *chunk = &_chunkList[num];
SoundChunk *sound = new SoundChunk();
sound->size = chunk->size;
sound->data = new uint8[sound->size];
_stream.seek(chunk->pos, SEEK_SET);
_stream.read(sound->data, sound->size);
return sound;
}
VideoChunk *VideoResource::getVideoHeader(uint num) {
assert(num < _chunkList.size());
Chunk *chunk = &_chunkList[num];
VideoChunk *vid = new VideoChunk();
_stream.seek(chunk->pos, SEEK_SET);
if (_stream.readUint32BE() != MKTAG('C', 'F', 'O', '\0'))
error("Corrupt video resource");
vid->size = _stream.readUint32LE();
vid->frameCount = _stream.readUint16LE();
vid->width = _stream.readUint16LE();
vid->height = _stream.readUint16LE();
vid->frameDelay = _stream.readUint32LE();
vid->firstFrameOffset = _stream.readUint32LE();
return vid;
}
Common::SeekableReadStream *VideoResource::getVideoStream(uint num) {
assert(num < _chunkList.size());
Chunk *chunk = &_chunkList[num];
return new Common::SeekableSubReadStream(&_stream, chunk->pos, chunk->pos + chunk->size);
}
DialogResource::DialogResource(const Common::Path &filename) : Resource(filename) {
_dialogBuffer = new byte[_stream.size()];
_stream.seek(0, SEEK_SET);
_dialogStream = new Common::MemorySeekableReadWriteStream(_dialogBuffer, _stream.size());
_dialogStream->writeStream(&_stream);
}
DialogResource::~DialogResource() {
delete _dialogStream;
delete _dialogBuffer;
}
DialogChunk *DialogResource::getDialog(uint dialog, uint block) {
Chunk *chunk = &_chunkList[dialog];
DialogChunk *item = new DialogChunk();
_dialogStream->seek(chunk->pos + 3 * 6 * block, SEEK_SET);
_dialogStream->read(item->show, 6);
_dialogStream->read(item->next, 6);
_dialogStream->read(item->flags, 6);
return item;
}
bool DialogResource::isItemShown(uint dialog, uint block, uint num) {
DialogChunk *item = getDialog(dialog, block);
bool isShown = item->show[num];
delete item;
return isShown;
}
void DialogResource::setItemShown(uint dialog, uint block, uint num, bool shown) {
Chunk *chunk = &_chunkList[dialog];
_dialogStream->seek(chunk->pos + 3 * 6 * block, SEEK_SET);
_dialogStream->skip(num);
_dialogStream->writeByte(shown ? 1 : 0);
}
bool DialogResource::hasExitBit(uint dialog, uint block, uint num) {
DialogChunk *item = getDialog(dialog, block);
const bool isExit = (item->flags[num] & ADS_EXIT_BIT) != 0;
delete item;
return isExit;
}
bool DialogResource::hasRestartBit(uint dialog, uint block, uint num) {
DialogChunk *item = getDialog(dialog, block);
const bool isRestart = (item->flags[num] & ADS_RESTART_BIT) != 0;
delete item;
return isRestart;
}
bool DialogResource::hasShowBit(uint dialog, uint block, uint num) {
DialogChunk *item = getDialog(dialog, block);
const bool isShown = (item->flags[num] & ADS_SHOW_BIT) != 0;
delete item;
return isShown;
}
uint8 DialogResource::getNextBlock(uint dialog, uint block, uint num) {
DialogChunk *item = getDialog(dialog, block);
const uint8 next = item->next[num];
delete item;
return next;
}
void DialogResource::loadStream(Common::SeekableReadStream *s) {
_dialogStream->seek(0, SEEK_SET);
_dialogStream->writeStream(s, _stream.size());
}
void DialogResource::saveStream(Common::WriteStream* s) {
_dialogStream->seek(0, SEEK_SET);
s->writeStream(_dialogStream, _stream.size());
}
void BarrierResource::init(int16 room, int16 bgWidth, int16 bgHeight) {
assert(room < (int16)_chunkList.size());
Chunk *chunk = &_chunkList[room];
_stream.seek(chunk->pos, SEEK_SET);
_x = _stream.readSint16LE();
_y = _stream.readSint16LE();
_level = _stream.readSint16LE();
_w = bgWidth / _x;
_h = bgHeight / _y;
_room = room;
}
}

249
engines/chewy/resource.h Normal file
View File

@@ -0,0 +1,249 @@
/* 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/>.
*
*/
#ifndef CHEWY_RESOURCE_H
#define CHEWY_RESOURCE_H
#include "common/scummsys.h"
#include "common/file.h"
#include "common/str.h"
#include "common/memstream.h"
#include "common/rect.h"
namespace Chewy {
enum ResourceType {
kResourceUnknown = -1,
kResourcePCX = 0, // unused
kResourceTBF = 1, // background art, contained in TGPs
kResourceTAF = 2,
kResourceTFF = 3,
kResourceVOC = 4, // speech and SFX, contained in TVPs
kResourceTPF = 5, // unused
kResourceTMF = 6, // music, similar to a MOD file, contained in details.tap
kResourceMOD = 7, // unused
kResourceRAW = 8, // unused
kResourceLBM = 9, // unused
kResourceRDI = 10,
kResourceTXT = 11,
kResourceIIB = 12,
kResourceSIB = 13,
kResourceEIB = 14,
kResourceATS = 15, // unused
kResourceSAA = 16, // unused
kResourceFLC = 17, // unused
kResourceAAD = 18, // unused
kResourceADS = 19, // unused
kResourceADH = 20, // used in txt/diah.adh
kResourceTGP = 21, // container for background art, used in back/comic.tgp, back/episode1.tgp and back/gbook.tgp
kResourceTVP = 22, // container for speech, used in sound/speech.tvp
kResourceTTP = 23, // unused
kResourceTAP = 24, // container for sound effects, music and cutscenes, used in sound/details.tap and cut/cut.tap
kResourceCFO = 25, // unused
kResourceTCF = 26, // error messages, used in err/err_e.tcf (English) and err/err_d.tcf (German)
kResourceGEP = 27 // barriers / walkable areas
};
// Generic chunk header
struct Chunk {
uint32 size;
uint16 num; // same as the type below, used in chunks where the type is substituted with count
ResourceType type;
uint32 pos; // position of the actual data
};
// TBF (background) chunk header
struct TBFChunk {
// TBF chunk header
// ID (TBF, followed by a zero)
uint16 screenMode;
uint16 compressionFlag;
uint32 size;
uint16 width;
uint16 height;
uint8 palette[3 * 256];
uint8 *data;
};
// TAF (sprite) image data chunk header - 15 bytes
struct TAFChunk {
uint16 compressionFlag;
uint16 width;
uint16 height;
// 4 bytes next sprite offset
// 4 bytes sprite image offset
// 1 byte padding
uint8 *data;
};
// Sound chunk header
struct SoundChunk {
uint32 size;
uint8 *data;
};
// Video chunk header
struct VideoChunk {
// ID (CFA, followed by a zero)
uint32 size;
uint16 frameCount;
uint16 width;
uint16 height;
uint32 frameDelay; // in ms
uint32 firstFrameOffset;
};
// Dialog chunk header (AdsBlock)
// Original values are in diah.adh, and are synced
// to saved games
struct DialogChunk {
bool show[6];
uint8 next[6];
uint8 flags[6];
};
enum VideoFrameType {
kVideoFrameNormal = 0xF1FA,
kVideoFrameCustom = 0xFAF1
};
typedef Common::Array<Chunk> ChunkList;
typedef Common::Array<TBFChunk> TBFChunkList;
class Resource {
public:
Resource(const Common::Path &filename);
virtual ~Resource();
ResourceType getType() const {
return _resType;
}
uint32 getSize() const {
return _stream.size();
}
uint32 findLargestChunk(uint start, uint end);
uint32 getChunkCount() const;
Chunk *getChunk(uint num);
virtual uint8 *getChunkData(uint num);
protected:
void initSprite(const Common::Path &filename);
void unpackRLE(uint8 *buffer, uint32 compressedSize, uint32 uncompressedSize);
void decrypt(uint8 *data, uint32 size);
Common::File _stream;
uint16 _chunkCount;
ResourceType _resType;
bool _encrypted;
// Sprite specific
uint8 _spritePalette[3 * 256];
uint32 _allSize;
uint16 _spriteCorrectionsCount;
uint16 *_spriteCorrectionsTable;
ChunkList _chunkList;
};
class SpriteResource : public Resource {
public:
SpriteResource(const Common::Path &filename) : Resource(filename) {}
virtual ~SpriteResource() {}
TAFChunk *getSprite(uint num);
uint32 getSpriteData(uint num, uint8 **buf, bool initBuffer);
uint8 *getSpritePalette() { return _spritePalette; }
uint32 getAllSize() { return _allSize; }
uint16 getSpriteCorrectionsCount() { return _spriteCorrectionsCount; }
uint16 *getSpriteCorrectionsTable() { return _spriteCorrectionsTable; }
};
class BackgroundResource : public Resource {
public:
BackgroundResource(const Common::Path &filename) : Resource(filename) {}
virtual ~BackgroundResource() {}
TBFChunk *getImage(uint num, bool fixPalette);
};
class SoundResource : public Resource {
public:
SoundResource(const Common::Path &filename) : Resource(filename) {}
virtual ~SoundResource() {}
SoundChunk *getSound(uint num);
};
class VideoResource : public Resource {
public:
VideoResource(const Common::Path &filename) : Resource(filename) {}
virtual ~VideoResource() {}
VideoChunk *getVideoHeader(uint num);
Common::SeekableReadStream *getVideoStream(uint num);
};
class DialogResource : public Resource {
public:
DialogResource(const Common::Path &filename);
virtual ~DialogResource();
DialogChunk *getDialog(uint dialog, uint block);
bool isItemShown(uint dialog, uint block, uint num);
void setItemShown(uint dialog, uint block, uint num, bool shown);
bool hasExitBit(uint dialog, uint block, uint num);
bool hasRestartBit(uint dialog, uint block, uint num);
bool hasShowBit(uint dialog, uint block, uint num);
uint8 getNextBlock(uint dialog, uint block, uint num);
void loadStream(Common::SeekableReadStream *s);
void saveStream(Common::WriteStream *s);
uint32 getStreamSize() const {
return _stream.size();
}
private:
Common::MemorySeekableReadWriteStream *_dialogStream;
byte *_dialogBuffer;
};
class BarrierResource : public Resource {
public:
BarrierResource(const Common::Path &filename) : Resource(filename) {}
virtual ~BarrierResource() {}
void init(int16 room, int16 bgWidth, int16 bgHeight);
int16 getX() const { return _x; }
int16 getY() const { return _y; }
int16 getLevel() const { return _level; }
int16 getWidth() const { return _w; }
int16 getHeight() const { return _h; }
uint8 *getData() { return getChunkData(_room); }
private:
int16 _x = 0, _y = 0, _level = 0, _w = 0, _h = 0, _room = 0;
};
} // namespace Chewy
#endif

529
engines/chewy/room.cpp Normal file
View File

@@ -0,0 +1,529 @@
/* 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/>.
*
*/
#include "chewy/defines.h"
#include "chewy/globals.h"
#include "chewy/memory.h"
#include "chewy/resource.h"
#include "chewy/room.h"
#include "cursor.h"
#include "chewy/sound.h"
namespace Chewy {
const int16 SURIMY_TAF19_PHASES[4][2] = {
{ 0, 0 },
{ 39, 46 },
{ 0, 0 },
{ 0, 0 }
};
static const uint8 CHEWY_PHASES[8][8] = {
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 8, 9, 10, 11, 12, 13, 14, 15 },
{ 16, 17, 18, 19, 20, 21, 22, 23 },
{ 24, 25, 26, 27, 28, 29, 30, 31 },
{ 32, 33, 34, 33, 32 },
{ 35, 36, 37, 38, 39, 40, 41, 42 },
{ 43, 44, 45, 46, 47, 48, 49, 50 },
{ 51, 52, 53, 52, 51 }
};
static const uint8 CHEWY_PHASE_NR[] = { 8, 8, 8, 8, 5, 8, 8, 5 };
static const uint8 CHEWY_BO_PHASES[8][8] = {
{ 0, 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10, 11 },
{ 12, 13, 14, 15, 16, 17 },
{ 12, 13, 14, 15, 16, 17 },
{ 18, 19, 20, 19, 18 },
{ 21, 22, 23, 24, 25, 26 },
{ 21, 22, 23, 24, 25, 26 },
{ 27, 28, 29, 28, 27 }
};
static const uint8 CHEWY_BO_PHASE_NR[] = { 6, 6, 6, 6, 5, 6, 6, 5 };
static const uint8 CHEWY_MI_PHASES[8][8] = {
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 8, 9, 10, 11, 12, 13, 14, 15 },
{ 24, 25, 26, 27, 28, 29, 30, 31 },
{ 24, 25, 26, 27, 28, 29, 30, 31 },
{ 32, 33, 34, 33, 32 },
{ 16, 17, 18, 19, 20, 21, 22, 23 },
{ 16, 17, 18, 19, 20, 21, 22, 23 },
{ 35, 36, 37, 36, 35 }
};
static const uint8 CHEWY_MI_PHASE_NR[] = { 8, 8, 8, 8, 5, 8, 8, 5 };
static const uint8 CHEWY_RO_PHASES[8][8] = {
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 8, 9, 10, 11, 12, 13, 14, 15 },
{ 24, 25, 26, 27, 28, 29, 30, 31 },
{ 24, 25, 26, 27, 28, 29, 30, 31 },
{ 32, 33, 34, 35, 36, 35, 34, 33 },
{ 16, 17, 18, 19, 20, 21, 22, 23 },
{ 16, 17, 18, 19, 20, 21, 22, 23 },
{ 37, 38, 39, 40, 41, 40, 39, 38 }
};
static const uint8 CHEWY_RO_PHASE_NR[] = { 8, 8, 8, 8, 8, 8, 8, 8 };
static const uint8 CHEWY_JM_PHASES[8][8] = {
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 8, 9, 10, 11, 12, 13, 14, 15 },
{ 16, 17, 18, 19, 20, 21, 22, 23 },
{ 16, 17, 18, 19, 20, 21, 22, 23 },
{ 24, 25, 26, 27, 27, 26, 25, 24 },
{ 8, 9, 10, 11, 12, 13, 14, 15 },
{ 8, 9, 10, 11, 12, 13, 14, 15 },
{ 28, 29, 30, 31, 31, 30, 29, 28 }
};
static const uint8 CHEWY_JM_PHASE_NR[] = {8, 8, 8, 8, 8, 8, 8, 8};
void JungleRoom::topEntry() {
hideCur();
setPersonPos(236, 110, P_CHEWY, P_RIGHT);
setPersonPos(263, 85, P_NICHELLE, P_RIGHT);
setPersonPos(285, 78, P_HOWARD, P_RIGHT);
goAutoXy(266, 113, P_HOWARD, ANI_WAIT);
showCur();
}
void JungleRoom::leftEntry() {
setPersonPos(31, 118, P_CHEWY, P_RIGHT);
setPersonPos(71, 104, P_NICHELLE, P_RIGHT);
setPersonPos(6, 111, P_HOWARD, P_RIGHT);
}
void JungleRoom::rightEntry() {
setPersonPos(587, 114, P_CHEWY, P_LEFT);
setPersonPos(613, 103, P_NICHELLE, P_LEFT);
setPersonPos(561, 112, P_HOWARD, P_LEFT);
}
void JungleRoom::setup_func() {
calc_person_look();
const int posX = _G(moveState)[P_CHEWY].Xypos[0];
int howDestX, nicDestX;
if (posX < 40) {
howDestX = 52;
nicDestX = 100;
} else if (posX < 230) {
howDestX = 83;
nicDestX = 163;
} else if (posX < 445) {
howDestX = 261;
nicDestX = 329;
} else {
howDestX = 493;
nicDestX = 543;
}
goAutoXy(howDestX, 111, P_HOWARD, ANI_GO);
goAutoXy(nicDestX, 110, P_NICHELLE, ANI_GO);
}
Room::Room() {
_roomTimer._timerMaxNr = 0;
_roomTimer._timerStart = 0;
init_ablage();
_roomInfo = nullptr;
_barriers = new BarrierResource(EPISODE1_GEP);
}
Room::~Room() {
delete _barriers;
free_ablage();
}
void Room::loadRoom(RaumBlk *Rb, int16 room_nr, GameState *player) {
clear_prog_ani();
_G(det)->load_rdi(Rb->DetFile, room_nr);
RoomDetailInfo *Rdi_ = _G(det)->getRoomDetailInfo();
_roomInfo = &Rdi_->Ri;
if (_roomInfo->_tafLoad != 255) {
_G(det)->load_rdi_taf(_roomInfo->_tafName, _roomInfo->_tafLoad);
Rb->Fti = _G(det)->get_taf_info();
Rb->_detImage = Rb->Fti->image;
Rb->DetKorrekt = Rb->Fti->correction;
}
_G(obj)->calc_all_static_detail();
load_tgp(_roomInfo->_imageNr, Rb, EPISODE1_TGP, true, EPISODE1);
set_pal(_ablagePal[Rb->AkAblage], Rb->LowPalMem);
calc_invent(Rb, player);
del_timer_old_room();
add_timer_new_room();
if (Rb->AadLoad)
_G(atds)->load_atds(_roomInfo->_roomNr, AAD_DATA);
}
void Room::set_timer_start(int16 timer_start) {
_roomTimer._timerStart = timer_start;
}
void Room::add_timer_new_room() {
_roomTimer._timerMaxNr = 0;
for (int i = 0; i < MAXDETAILS && _roomTimer._timerMaxNr < MAX_ROOM_TIMER; i++) {
AniDetailInfo *adi = _G(det)->getAniDetail(i);
if (adi->timer_start != 0) {
set_timer(i, adi->timer_start);
} else if (adi->start_flag || adi->repeat) {
_G(det)->startDetail(i, 0, ANI_FRONT);
}
}
}
void Room::del_timer_old_room() {
for (int i = 0; i < _roomTimer._timerMaxNr; i++) {
_G(uhr)->setStatus(_roomTimer._timerNr[i], TIMER_STOP);
}
_roomTimer._timerMaxNr = 0;
}
int16 Room::set_timer(int16 ani_nr, int16 timer_end) {
int16 timer_nr_ = _roomTimer._timerStart + _roomTimer._timerMaxNr;
int16 ret = _G(uhr)->setNewTimer(timer_nr_, timer_end, SEC_MODE);
if (ret != -1) {
_roomTimer._objNr[_roomTimer._timerMaxNr] = ani_nr;
_roomTimer._timerNr[_roomTimer._timerMaxNr] = timer_nr_;
++_roomTimer._timerMaxNr;
}
return timer_nr_;
}
void Room::set_timer_status(int16 ani_nr, int16 status) {
for (int i = 0; i < _roomTimer._timerMaxNr; i++) {
if (_roomTimer._objNr[i] == ani_nr) {
_G(uhr)->setStatus(_roomTimer._timerNr[i], status);
}
}
}
void Room::set_zoom(int16 zoom) {
_roomInfo->_zoomFactor = (uint8)zoom;
}
void Room::set_pal(const byte *src_pal, byte *dest_pal) {
memcpy(dest_pal, src_pal, 768l);
dest_pal[767] = 63;
dest_pal[766] = 63;
dest_pal[765] = 63;
dest_pal[0] = 0;
dest_pal[1] = 0;
dest_pal[2] = 0;
}
void Room::set_ak_pal(RaumBlk *Rb) {
set_pal(_ablagePal[Rb->AkAblage], Rb->LowPalMem);
}
void Room::calc_invent(RaumBlk *Rb, GameState *player) {
byte *tmp_inv_spr[MAX_MOV_OBJ];
_G(obj)->sort();
memcpy(tmp_inv_spr, Rb->InvSprAdr, MAX_MOV_OBJ * sizeof(char *));
memset(Rb->InvSprAdr, 0, MAX_MOV_OBJ * sizeof(char *));
SpriteResource *spriteRes = new SpriteResource(Rb->InvFile);
for (int16 i = 1; i < _G(obj)->mov_obj_room[0] + 1; i++) {
if (!tmp_inv_spr[_G(obj)->mov_obj_room[i]]) {
spriteRes->getSpriteData(_G(obj)->mov_obj_room[i], &Rb->InvSprAdr[_G(obj)->mov_obj_room[i]], true);
} else {
Rb->InvSprAdr[_G(obj)->mov_obj_room[i]] = tmp_inv_spr[_G(obj)->mov_obj_room[i]];
tmp_inv_spr[_G(obj)->mov_obj_room[i]] = nullptr;
}
}
for (int16 i = 1; i < _G(obj)->spieler_invnr[0] + 1; i++) {
if (!tmp_inv_spr[_G(obj)->spieler_invnr[i]]) {
spriteRes->getSpriteData(_G(obj)->spieler_invnr[i], &Rb->InvSprAdr[_G(obj)->spieler_invnr[i]], true);
} else {
Rb->InvSprAdr[_G(obj)->spieler_invnr[i]] = tmp_inv_spr[_G(obj)->spieler_invnr[i]];
tmp_inv_spr[_G(obj)->spieler_invnr[i]] = 0;
}
}
for (int16 i = 0; i < MAX_MOV_OBJ; i++) {
if (tmp_inv_spr[i] != 0)
free(tmp_inv_spr[i]);
}
if (_G(cur)->usingInventoryCursor()) {
const int cursor = _G(cur)->getInventoryCursor();
if (Rb->InvSprAdr[cursor] == nullptr) {
spriteRes->getSpriteData(cursor, &Rb->InvSprAdr[cursor], true);
}
}
delete spriteRes;
}
int16 Room::load_tgp(int16 nr, RaumBlk *Rb, int16 tgp_idx, bool loadBarriers, const char *fileName) {
BackgroundResource *res = new BackgroundResource(fileName);
TBFChunk *img = res->getImage(nr, false);
Rb->AkAblage = get_ablage(nr + (1000 * tgp_idx), img->size + 4);
if (Rb->AkAblage == -1) {
} else if (Rb->AkAblage >= 1000) {
Rb->AkAblage -= 1000;
} else {
// Image width and height is piggy-banked inside the image data
uint16 *memPtr = (uint16 *)_ablage[Rb->AkAblage];
memPtr[0] = img->width;
memPtr[1] = img->height;
memcpy(_ablage[Rb->AkAblage] + 4, img->data, img->size);
memcpy(_ablagePal[Rb->AkAblage], img->palette, 3 * 256);
set_ablage_info(Rb->AkAblage, nr + (1000 * tgp_idx), img->size);
if (loadBarriers)
_barriers->init(nr, img->width, img->height);
}
delete img;
delete res;
return true;
}
void Room::init_ablage() {
_lastAblageSave = 0;
_ablage[0] = (byte *)MALLOC(MAX_ABLAGE * (ABLAGE_BLOCK_SIZE + 4l));
_ablagePal[0] = (byte *)MALLOC(MAX_ABLAGE * 768l);
_akAblage = 0;
for (int16 i = 0; i < MAX_ABLAGE; i++) {
_ablage[i] = _ablage[0] + (ABLAGE_BLOCK_SIZE + 4l) * i;
_ablageInfo[i][0] = -1;
_ablageInfo[i][1] = -1;
_ablagePal[i] = _ablagePal[0] + 768l * i;
}
}
void Room::free_ablage() {
free(_ablagePal[0]);
free(_ablage[0]);
_akAblage = -1;
}
byte *Room::get_ablage(int16 nr) {
byte *ret = nullptr;
if (nr < MAX_ABLAGE && _akAblage != -1) {
ret = _ablage[nr];
}
return ret;
}
byte **Room::get_ablage() {
byte **ret = nullptr;
if (_akAblage != -1) {
ret = &_ablage[0];
}
return ret;
}
int16 Room::get_ablage(int16 pic_nr, uint32 pic_size) {
int16 ret = -1;
uint32 ablage_bedarf = pic_size / ABLAGE_BLOCK_SIZE;
if (pic_size % ABLAGE_BLOCK_SIZE > 4)
++ablage_bedarf;
int16 ende = 0;
for (int16 i = 0; i < MAX_ABLAGE && !ende; i++) {
if (_ablageInfo[i][0] == pic_nr &&
_ablageInfo[i][1] != 255) {
ende = 1;
ret = 1000 + i;
}
}
if (!ende) {
for (int16 i = 0; i < MAX_ABLAGE && !ende; i++) {
ret = get_ablage_g1((int16)ablage_bedarf, i);
ende = 1;
}
}
if (ret != -1) {
if (ret < 1000) {
ende = 0;
while (!ende) {
if (_ablageInfo[_lastAblageSave][1] == 255) {
--_lastAblageSave;
if (_lastAblageSave < 0) {
_lastAblageSave = 0;
_ablageInfo[0][1] = MAX_ABLAGE;
}
} else
ende = 1;
}
int16 i = _ablageInfo[_lastAblageSave][1];
for (int16 j = _lastAblageSave; j < _lastAblageSave + i; j++) {
_ablageInfo[j][0] = -1;
_ablageInfo[j][1] = -1;
}
}
}
return ret;
}
int16 Room::get_ablage_g1(int16 ablage_bedarf, int16 ak_pos) {
short ret = 0;
bool endLoop = false;
int16 count = 0;
_lastAblageSave = ak_pos;
while (!endLoop) {
if (_lastAblageSave >= MAX_ABLAGE)
_lastAblageSave = 0;
if (ablage_bedarf == 1) {
endLoop = true;
ret = _lastAblageSave;
} else if (ablage_bedarf <= MAX_ABLAGE - _lastAblageSave) {
endLoop = true;
ret = _lastAblageSave;
} else
++_lastAblageSave;
++count;
if (count > MAX_ABLAGE) {
ret = -1;
endLoop = true;
}
}
return ret;
}
void Room::set_ablage_info(int16 ablagenr, int16 bildnr, uint32 pic_size) {
uint32 ablage_bedarf = (pic_size / ABLAGE_BLOCK_SIZE);
if (pic_size % ABLAGE_BLOCK_SIZE > 4)
++ablage_bedarf;
int16 j = (int16)ablage_bedarf;
for (int16 i = ablagenr; i < j + ablagenr; i++) {
_ablageInfo[i][0] = bildnr;
_ablageInfo[i][1] = (int16)ablage_bedarf;
ablage_bedarf = 255;
++_lastAblageSave;
}
}
void load_chewy_taf(int16 taf_nr) {
if (_G(AkChewyTaf) != taf_nr) {
if (_G(chewy)) {
free((char *)_G(chewy));
_G(chewy) = nullptr;
}
_G(spieler_mi)[P_CHEWY].HotY = CH_HOT_Y;
const char *filename;
switch (taf_nr) {
case CHEWY_NORMAL:
filename = CHEWY_TAF;
_G(chewy_ph_nr) = CHEWY_PHASE_NR;
_G(chewy_ph) = (const uint8 *)CHEWY_PHASES;
break;
case CHEWY_BORK:
filename = CHEWY_BO_TAF;
_G(chewy_ph_nr) = CHEWY_BO_PHASE_NR;
_G(chewy_ph) = (const uint8 *)CHEWY_BO_PHASES;
break;
case CHEWY_MINI:
filename = CHEWY_MI_TAF;
_G(chewy_ph_nr) = CHEWY_MI_PHASE_NR;
_G(chewy_ph) = (const uint8 *)CHEWY_MI_PHASES;
break;
case CHEWY_PUMPKIN:
filename = CHEWY_PUMP_TAF;
_G(chewy_ph_nr) = CHEWY_MI_PHASE_NR;
_G(chewy_ph) = (const uint8 *)CHEWY_MI_PHASES;
break;
case CHEWY_ROCKER:
filename = CHEWY_ROCK_TAF;
_G(chewy_ph_nr) = CHEWY_RO_PHASE_NR;
_G(chewy_ph) = (const uint8 *)CHEWY_RO_PHASES;
break;
case CHEWY_JMANS:
filename = CHEWY_JMAN_TAF;
_G(chewy_ph_nr) = CHEWY_JM_PHASE_NR;
_G(chewy_ph) = (const uint8 *)CHEWY_JM_PHASES;
_G(spieler_mi)[P_CHEWY].HotY = 68;
break;
case CHEWY_ANI7:
filename = CHEWY_HELM_TAF;
_G(chewy_ph_nr) = CHEWY_MI_PHASE_NR;
_G(chewy_ph) = (const uint8 *)CHEWY_MI_PHASES;
break;
default:
filename = nullptr;
break;
}
if (filename != nullptr) {
_G(gameState).ChewyAni = taf_nr;
_G(AkChewyTaf) = taf_nr;
_G(chewy) = _G(mem)->taf_adr(filename);
}
}
}
void switchRoom(int16 nr) {
_G(fx_blend) = BLEND1;
exit_room(-1);
_G(gameState)._personRoomNr[P_CHEWY] = nr;
_G(room)->loadRoom(&_G(room_blk), _G(gameState)._personRoomNr[P_CHEWY], &_G(gameState));
enter_room(-1);
setupScreen(DO_SETUP);
}
void calc_person_look() {
for (int16 i = 1; i < MAX_PERSON; i++) {
if (_G(spieler_mi)[i].Id != NO_MOV_OBJ) {
if (_G(moveState)[i].Xypos[0] > _G(moveState)[P_CHEWY].Xypos[0])
_G(person_end_phase)[i] = P_LEFT;
else
_G(person_end_phase)[i] = P_RIGHT;
}
}
}
} // namespace Chewy

118
engines/chewy/room.h Normal file
View File

@@ -0,0 +1,118 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOM_H
#define CHEWY_ROOM_H
#include "chewy/detail.h"
#include "chewy/mcga_graphics.h"
#include "chewy/object_extra.h"
namespace Chewy {
#define ANI_HIDE 0
#define ANI_SHOW 1
#define SURIMY_OBJ 0
extern const int16 SURIMY_TAF19_PHASES[4][2];
#define MAX_ABLAGE 4
#define ABLAGE_BLOCK_SIZE 64000l
class JungleRoom {
protected:
static void topEntry();
static void leftEntry();
static void rightEntry();
static void setup_func();
};
struct RaumBlk {
byte *LowPalMem;
const char *InvFile;
const char *DetFile;
byte **InvSprAdr;
RoomMovObject *Rmo;
RoomStaticInventory *Rsi;
int16 AkAblage;
byte **_detImage;
int16 *DetKorrekt;
TafInfo *Fti;
int16 AadLoad;
};
struct RaumTimer {
int16 _timerStart;
int16 _timerMaxNr;
uint8 _objNr[MAX_ROOM_TIMER];
uint8 _timerNr[MAX_ROOM_TIMER];
};
class Room {
public:
Room();
~Room();
void loadRoom(RaumBlk *Rb, int16 room_nr, GameState *player);
int16 load_tgp(int16 nr, RaumBlk *Rb, int16 tgp_idx, bool loadBarriers, const char *fileName);
byte *get_ablage(int16 nr);
byte **get_ablage();
void set_timer_start(int16 timer_start);
void add_timer_new_room();
void del_timer_old_room();
int16 set_timer(int16 ani_nr, int16 timer_end);
void set_timer_status(int16 ani_nr, int16 status);
void set_zoom(int16 zoom);
void set_pal(const byte *src_pal, byte *dest_pal);
void set_ak_pal(RaumBlk *Rb);
void calc_invent(RaumBlk *Rb, GameState *player);
RaumTimer _roomTimer;
RoomInfo *_roomInfo;
BarrierResource *_barriers;
private:
void init_ablage();
void free_ablage();
int16 get_ablage(int16 pic_nr, uint32 pic_size);
int16 get_ablage_g1(int16 ablage_bedarf, int16 ak_pos);
void set_ablage_info(int16 ablagenr, int16 bildnr, uint32 pic_size);
int16 _akAblage;
int16 _lastAblageSave;
byte *_ablage[MAX_ABLAGE];
byte *_ablagePal[MAX_ABLAGE];
int16 _ablageInfo[MAX_ABLAGE][2];
};
void load_chewy_taf(int16 taf_nr);
extern void switchRoom(int16 nr);
extern void calc_person_look();
} // namespace Chewy
#endif

View File

@@ -0,0 +1,775 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/font.h"
#include "chewy/globals.h"
#include "chewy/main.h"
#include "chewy/room.h"
#include "chewy/rooms/room00.h"
#include "chewy/sound.h"
namespace Chewy {
namespace Rooms {
#define FLAP_SPRITE 5
#define CH_FLASH 8
#define FLAP_DETAIL 10
#define HOSE_DETAIL 11
#define CH_THROWS_SLIME 12
#define CH_TO_FEEDER 13
#define CH_THROWS_PILLOW 14
#define FEEDER_HOSE 15
#define STERNE_STEHEN 16
#define HOSE1 11
#define HOSE2 38
#define HOSE3 59
#define HEAD1 39
#define HEAD2 46
#define HEAD3 48
void Room0::entry() {
if (isCurInventory(0) || _G(gameState).R0PillowThrow || _G(obj)->checkInventory(0))
_G(det)->hideStaticSpr(6);
if (!_G(flags).LoadGame) {
setPersonPos(150, 100, P_CHEWY, P_RIGHT);
hideCur();
_G(timer_nr)[0] = _G(room)->set_timer(255, 3);
while (!_G(ani_timer)[_G(timer_nr)[0]]._timeFlag && !SHOULD_QUIT) {
setupScreen(DO_SETUP);
}
start_spz(CH_TALK5, 255, ANI_FRONT, P_CHEWY);
startAadWait(2);
showCur();
}
}
bool Room0::timer(int16 timerNr, int16 aniNr) {
bool retval = false;
if (aniNr == 1) {
if (_G(timer_action_ctr) > 0) {
_G(uhr)->resetTimer(timerNr, 0);
--_G(timer_action_ctr);
} else if (!is_chewy_busy() && _G(flags).AutoAniPlay == 0) {
if (!_G(gameState).R0FueterLab)
_G(timer_action_ctr) = 2;
_G(flags).AutoAniPlay = true;
if (!_G(gameState).R0SlimeUsed) {
startAadWait(42);
autoMove(5, P_CHEWY);
setPersonSpr(P_LEFT, P_CHEWY);
if (_G(gameState).R0FueterLab < 3) {
start_spz(CH_TALK3, 255, false, P_CHEWY);
if (_G(gameState).R0FueterLab)
startAadWait(618);
else
startAadWait(43);
++_G(gameState).R0FueterLab;
}
eyeAnim();
} else if (!_G(gameState).R0PillowThrow) {
startAadWait(42);
start_spz(CH_TALK3, 255, false, P_CHEWY);
if (_G(gameState).R0FueterLab < 3) {
startAadWait(43);
++_G(gameState).R0FueterLab;
}
autoMove(3, P_CHEWY);
setPersonPos(191, 120, P_CHEWY, P_LEFT);
}
if (!_G(gameState).R0PillowThrow)
feederAni();
_G(uhr)->resetTimer(timerNr, 0);
_G(flags).AutoAniPlay = false;
}
} else if (timerNr != 3) {
retval = true;
}
return retval;
}
bool Room0::getPillow() {
bool retval = false;
if (!_G(cur)->usingInventoryCursor()) {
hideCur();
_G(flags).AutoAniPlay = true;
autoMove(1, P_CHEWY);
start_spz_wait(CH_LGET_O, 1, false, P_CHEWY);
invent_2_slot(0);
_G(menu_item) = CUR_WALK;
cursorChoice(CUR_WALK);
_G(atds)->setControlBit(174, ATS_ACTIVE_BIT);
_G(det)->hideStaticSpr(6);
_G(flags).AutoAniPlay = false;
showCur();
retval = true;
}
return retval;
}
bool Room0::pullSlime() {
bool retval = false;
if (!_G(cur)->usingInventoryCursor()) {
hideCur();
_G(flags).AutoAniPlay = true;
autoMove(2, P_CHEWY);
_G(gameState)._personHide[P_CHEWY] = true;
startSetAILWait(3, 1, ANI_FRONT);
startSetAILWait(17, 2, ANI_FRONT);
setPersonPos(222, 106, P_CHEWY, P_LEFT);
_G(gameState)._personHide[P_CHEWY] = false;
invent_2_slot(1);
_G(menu_item) = CUR_WALK;
cursorChoice(CUR_WALK);
_G(atds)->setControlBit(175, ATS_ACTIVE_BIT);
_G(flags).AutoAniPlay = false;
showCur();
retval = true;
}
return retval;
}
void Room0::eyeAnim() {
if (!_G(gameState).R0SlimeUsed) {
// Start the eye animation
eyeStart(EYE_START);
if (!_G(gameState).R0SlimeUsed)
eyeWait();
if (_G(gameState).R0SlimeUsed) {
start_aad(124);
checkSlimeEye();
eyeSlimeBack();
autoMove(FUETTER_POS, P_CHEWY);
setPersonPos(199 - CH_HOT_MOV_X, 145 - CH_HOT_MOV_Y, P_CHEWY, P_LEFT);
} else {
eyeShoot();
setPersonPos(199 - CH_HOT_MOV_X, 145 - CH_HOT_MOV_Y, P_CHEWY, P_LEFT);
eyeStart(EYE_END);
}
}
}
void Room0::eyeStart(EyeMode mode) {
AniDetailInfo *adi = _G(det)->getAniDetail(HOSE_DETAIL);
if (mode == EYE_START)
adi->ani_count = adi->start_ani;
else
adi->ani_count = 38;
if (mode == EYE_START) {
trapDoorOpen();
}
bool ende = false;
_G(flags).AniUserAction = true;
if (mode == EYE_START) {
_G(det)->playSound(FLAP_DETAIL, 0);
_G(det)->stopSound(1);
_G(det)->playSound(HOSE_DETAIL, 0);
_G(det)->stopSound(2);
} else {
_G(det)->stopSound(0);
_G(det)->playSound(FLAP_DETAIL, 1);
_G(det)->stopSound(0);
_G(det)->playSound(HOSE_DETAIL, 2);
}
while (!ende) {
clear_prog_ani();
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, FLAP_DETAIL, FLAP_SPRITE, ANI_HIDE);
_G(spr_info)[0]._zLevel = 190;
if ((adi->ani_count > 11) && (adi->ani_count < 19)) {
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, HOSE1, ANI_HIDE);
_G(spr_info)[1]._zLevel = 191;
}
if (adi->ani_count == 38) {
_G(spr_info)[2] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, HEAD1, ANI_HIDE);
_G(spr_info)[2]._zLevel = 192;
}
_G(spr_info)[3] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, adi->ani_count, ANI_HIDE);
_G(spr_info)[3]._zLevel = 193;
get_user_key(NO_SETUP);
setupScreen(NO_SETUP);
SHOULD_QUIT_RETURN;
_G(cur)->updateCursor();
calcEyeClick(3);
_G(out)->copyToScreen();
if (adi->delay_count > 0)
--adi->delay_count;
else {
adi->delay_count = adi->delay + _G(gameState).DelaySpeed;
if (mode == EYE_START) {
++adi->ani_count;
if (adi->ani_count > 38)
ende = true;
} else {
--adi->ani_count;
if (adi->ani_count == adi->start_ani - 1)
ende = true;
}
}
}
clear_prog_ani();
_G(flags).AniUserAction = false;
if (mode == EYE_END) {
trapDoorClose();
}
}
void Room0::eyeWait() {
AniDetailInfo *adi = _G(det)->getAniDetail(HOSE_DETAIL);
adi->ani_count = 39;
adi->delay_count = 15;
_G(flags).AniUserAction = true;
while (adi->ani_count < 46) {
clear_prog_ani();
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, FLAP_DETAIL, FLAP_SPRITE, ANI_HIDE);
_G(spr_info)[0]._zLevel = 190;
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, HOSE2, ANI_HIDE);
_G(spr_info)[1]._zLevel = 191;
_G(spr_info)[2] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, adi->ani_count, ANI_HIDE);
_G(spr_info)[2]._zLevel = 192;
get_user_key(NO_SETUP);
setupScreen(NO_SETUP);
_G(cur)->updateCursor();
calcEyeClick(2);
_G(out)->copyToScreen();
if (adi->delay_count > 0) {
--adi->delay_count;
} else {
adi->delay_count = adi->delay + _G(gameState).DelaySpeed;
++adi->ani_count;
}
EVENTS_UPDATE;
SHOULD_QUIT_RETURN;
}
_G(flags).AniUserAction = false;
clear_prog_ani();
}
void Room0::calcEyeClick(int16 aniNr) {
if (mouse_on_prog_ani() == aniNr) {
if (_G(minfo).button != 1 && g_events->_kbInfo._keyCode != Common::KEYCODE_RETURN) {
const uint8 roomNum = _G(room)->_roomInfo->_roomNr;
Common::StringArray desc = _G(atds)->getTextArray(roomNum, 172, ATS_DATA);
if (desc.size() > 0) {
_G(fontMgr)->setFont(_G(font8));
int16 x = g_events->_mousePos.x;
int16 y = g_events->_mousePos.y;
calcTxtXy(&x, &y, desc);
for (int16 i = 0; i < (int16)desc.size(); i++)
printShadowed(x, y + i * 10, 255, 300, 0, _G(scr_width), desc[i].c_str());
}
} else if (_G(minfo).button == 1 || g_events->_kbInfo._keyCode == Common::KEYCODE_RETURN) {
if (isCurInventory(SLIME_INV)) {
delInventory(_G(cur)->getInventoryCursor());
_G(gameState).R0SlimeUsed = true;
} else if (isCurInventory(PILLOW_INV)) {
startAtsWait(172, TXT_MARK_WALK, 14, ATS_DATA);
}
}
}
}
void Room0::eyeShoot() {
AniDetailInfo *adi = _G(det)->getAniDetail(HOSE_DETAIL);
adi->ani_count = 47;
bool endLoopFl = false;
_G(det)->startDetail(CH_FLASH, 1, ANI_FRONT);
while (!endLoopFl) {
clear_prog_ani();
_G(gameState)._personHide[P_CHEWY] = true;
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, FLAP_DETAIL, FLAP_SPRITE, ANI_HIDE);
_G(spr_info)[0]._zLevel = 190;
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, HOSE2, ANI_HIDE);
_G(spr_info)[1]._zLevel = 191;
if (adi->ani_count < 53) {
_G(spr_info)[2] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, adi->ani_count, ANI_HIDE);
_G(spr_info)[2]._zLevel = 192;
} else {
_G(spr_info)[2] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, 47, ANI_HIDE);
_G(spr_info)[2]._zLevel = 192;
if (!_G(det)->get_ani_status(CH_FLASH))
endLoopFl = true;
}
setupScreen(DO_SETUP);
SHOULD_QUIT_RETURN;
if (adi->delay_count > 0)
--adi->delay_count;
else {
adi->delay_count = adi->delay + _G(gameState).DelaySpeed;
++adi->ani_count;
}
}
_G(det)->startDetail(STERNE_STEHEN, 255, ANI_FRONT);
clear_prog_ani();
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, FLAP_DETAIL, FLAP_SPRITE, ANI_HIDE);
_G(spr_info)[0]._zLevel = 190;
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, HOSE2, ANI_HIDE);
_G(spr_info)[1]._zLevel = 191;
_G(spr_info)[2] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, HEAD2, ANI_HIDE);
_G(spr_info)[2]._zLevel = 192;
waitShowScreen(30);
clear_prog_ani();
setPersonPos(199 - CH_HOT_MOV_X, 145 - CH_HOT_MOV_Y, P_CHEWY, P_LEFT);
_G(gameState)._personHide[P_CHEWY] = false;
}
void Room0::eyeSlimeBack() {
AniDetailInfo *adi = _G(det)->getAniDetail(HOSE_DETAIL);
adi->ani_count = 53;
bool endLoopFl = false;
_G(flags).AniUserAction = true;
while (!endLoopFl) {
clear_prog_ani();
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, FLAP_DETAIL, FLAP_SPRITE, ANI_HIDE);
_G(spr_info)[0]._zLevel = 190;
if ((adi->ani_count > 52) && (adi->ani_count < 59)) {
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, HOSE2, ANI_HIDE);
_G(spr_info)[1]._zLevel = 191;
}
if (adi->ani_count == 61) {
_G(spr_info)[2] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, HOSE3, ANI_HIDE);
_G(spr_info)[2]._zLevel = 192;
}
_G(spr_info)[3] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, adi->ani_count, ANI_HIDE);
_G(spr_info)[3]._zLevel = 193;
set_ani_screen();
SHOULD_QUIT_RETURN;
if (adi->delay_count > 0)
--adi->delay_count;
else {
adi->delay_count = adi->delay + _G(gameState).DelaySpeed;
++adi->ani_count;
if (adi->ani_count == 77)
endLoopFl = true;
}
}
_G(flags).AniUserAction = false;
clear_prog_ani();
}
void Room0::checkSlimeEye() {
AniDetailInfo *adi = _G(det)->getAniDetail(CH_THROWS_SLIME);
adi->ani_count = adi->start_ani;
if (adi->load_flag) {
_G(det)->load_taf_seq(adi->start_ani, (adi->end_ani - adi->start_ani) + 1, nullptr);
}
while (adi->ani_count < adi->end_ani && !SHOULD_QUIT) {
clear_prog_ani();
_G(gameState)._personHide[P_CHEWY] = true;
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, FLAP_DETAIL, FLAP_SPRITE, ANI_HIDE);
_G(spr_info)[0]._zLevel = 190;
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, HOSE2, ANI_HIDE);
_G(spr_info)[1]._zLevel = 191;
_G(spr_info)[2] = _G(det)->plot_detail_sprite(0, 0, HOSE_DETAIL, HEAD2, ANI_HIDE);
_G(spr_info)[2]._zLevel = 192;
_G(spr_info)[3] = _G(det)->plot_detail_sprite(0, 0, CH_THROWS_SLIME, adi->ani_count, ANI_HIDE);
_G(spr_info)[3]._zLevel = 193;
setupScreen(DO_SETUP);
if (adi->delay_count > 0)
--adi->delay_count;
else {
adi->delay_count = adi->delay + _G(gameState).DelaySpeed;
++adi->ani_count;
}
}
if (adi->load_flag) {
_G(det)->del_taf_tbl(adi->start_ani, (adi->end_ani - adi->start_ani) + 1, nullptr);
}
clear_prog_ani();
_G(gameState)._personHide[P_CHEWY] = false;
}
void Room0::feederStart(int16 mode) {
AniDetailInfo *adi = _G(det)->getAniDetail(FEEDER_HOSE);
if (!mode)
adi->ani_count = adi->start_ani;
else
adi->ani_count = 135;
if (!mode) {
trapDoorOpen();
_G(det)->playSound(FLAP_DETAIL, 0);
_G(det)->stopSound(1);
_G(det)->playSound(FEEDER_HOSE, 0);
_G(det)->stopSound(2);
} else {
_G(det)->stopSound(0);
_G(det)->playSound(FLAP_DETAIL, 1);
_G(det)->stopSound(0);
_G(det)->playSound(FEEDER_HOSE, 2);
}
bool endLoopFl = false;
if (_G(gameState).R0SlimeUsed)
_G(flags).AniUserAction = true;
while (!endLoopFl) {
clear_prog_ani();
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, FLAP_DETAIL, FLAP_SPRITE, ANI_HIDE);
_G(spr_info)[0]._zLevel = 190;
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, FEEDER_HOSE, adi->ani_count, ANI_HIDE);
_G(spr_info)[1]._zLevel = 191;
if (_G(flags).AniUserAction)
get_user_key(NO_SETUP);
EVENTS_UPDATE;
SHOULD_QUIT_RETURN;
setupScreen(NO_SETUP);
_G(cur)->updateCursor();
if (!mode)
calcPillowClick(1);
_G(out)->copyToScreen();
if (adi->delay_count > 0)
--adi->delay_count;
else {
adi->delay_count = adi->delay + _G(gameState).DelaySpeed;
if (!mode) {
++adi->ani_count;
if (adi->ani_count > 135)
endLoopFl = true;
} else {
--adi->ani_count;
if (adi->ani_count == adi->start_ani - 1)
endLoopFl = true;
}
}
}
clear_prog_ani();
_G(flags).AniUserAction = false;
if (mode) {
_G(det)->startDetail(FLAP_DETAIL, 1, ANI_BACK);
while (_G(det)->get_ani_status(FLAP_DETAIL))
set_ani_screen();
}
}
void Room0::feederExtend() {
for (int16 i = 0; i < 30 && !_G(gameState).R0PillowThrow; i++) {
clear_prog_ani();
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, FLAP_DETAIL, FLAP_SPRITE, ANI_HIDE);
_G(spr_info)[0]._zLevel = 190;
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, FEEDER_HOSE, 136, ANI_HIDE);
_G(spr_info)[1]._zLevel = 191;
get_user_key(NO_SETUP);
setupScreen(NO_SETUP);
_G(cur)->updateCursor();
calcPillowClick(1);
_G(out)->copyToScreen();
}
clear_prog_ani();
}
void Room0::calcPillowClick(int16 aniNr) {
if (mouse_on_prog_ani() == aniNr) {
if (_G(minfo).button != 1 && g_events->_kbInfo._keyCode != Common::KEYCODE_RETURN) {
const uint8 roomNum = _G(room)->_roomInfo->_roomNr;
Common::StringArray desc = _G(atds)->getTextArray(roomNum, 173, ATS_DATA);
if (desc.size() > 0) {
_G(fontMgr)->setFont(_G(font8));
int16 x = g_events->_mousePos.x;
int16 y = g_events->_mousePos.y;
calcTxtXy(&x, &y, desc);
for (int16 i = 0; i < (int16)desc.size(); i++)
printShadowed(x, y + i * 10, 255, 300, 0, _G(scr_width), desc[i].c_str());
}
} else if (_G(minfo).button == 1 || g_events->_kbInfo._keyCode == Common::KEYCODE_RETURN) {
if (isCurInventory(PILLOW_INV) && _G(gameState).R0SlimeUsed) {
delInventory(_G(cur)->getInventoryCursor());
_G(gameState).R0PillowThrow = true;
} else if (isCurInventory(SLIME_INV)) {
startAtsWait(173, TXT_MARK_WALK, 14, ATS_DATA);
}
}
}
}
void Room0::checkFeed() {
AniDetailInfo *adi = _G(det)->getAniDetail(FEEDER_HOSE);
adi->ani_count = 136;
int16 i = 152;
bool endLoopFl = false;
if (_G(gameState).R0SlimeUsed)
_G(flags).AniUserAction = true;
while (!endLoopFl) {
clear_prog_ani();
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, FLAP_DETAIL, FLAP_SPRITE, ANI_HIDE);
_G(spr_info)[0]._zLevel = 190;
if (adi->ani_count == 136) {
_G(gameState)._personHide[P_CHEWY] = true;
if (!_G(gameState).R0SlimeUsed)
_G(det)->stopDetail(16);
}
if (adi->ani_count > 138) {
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, FEEDER_HOSE, 138, ANI_HIDE);
_G(spr_info)[1]._zLevel = 191;
}
if (adi->ani_count > 141) {
_G(spr_info)[2] = _G(det)->plot_detail_sprite(0, 0, FEEDER_HOSE, i, ANI_HIDE);
_G(spr_info)[2]._zLevel = 192;
}
if (adi->ani_count == 138) {
_G(spr_info)[3] = _G(det)->plot_detail_sprite(0, 0, FEEDER_HOSE, 139, ANI_HIDE);
_G(spr_info)[3]._zLevel = 193;
}
_G(spr_info)[4] = _G(det)->plot_detail_sprite(0, 0, FEEDER_HOSE, adi->ani_count, ANI_HIDE);
_G(spr_info)[4]._zLevel = 194;
set_ani_screen();
SHOULD_QUIT_RETURN;
if (adi->delay_count > 0)
--adi->delay_count;
else {
adi->delay_count = adi->delay + _G(gameState).DelaySpeed;
if (adi->ani_count > 141)
++i;
++adi->ani_count;
if (adi->ani_count == 152)
endLoopFl = true;
}
}
adi->ani_count = 138;
_G(det)->startDetail(CH_TO_FEEDER, 2, ANI_FRONT);
endLoopFl = false;
while (!endLoopFl) {
clear_prog_ani();
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, FLAP_DETAIL, FLAP_SPRITE, ANI_HIDE);
_G(spr_info)[0]._zLevel = 190;
if (adi->ani_count > 138) {
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, FEEDER_HOSE, 138, ANI_HIDE);
_G(spr_info)[1]._zLevel = 191;
}
if (adi->ani_count == 138) {
_G(spr_info)[2] = _G(det)->plot_detail_sprite(0, 0, FEEDER_HOSE, 139, ANI_HIDE);
_G(spr_info)[2]._zLevel = 192;
}
_G(spr_info)[3] = _G(det)->plot_detail_sprite(0, 0, FEEDER_HOSE, adi->ani_count, ANI_HIDE);
_G(spr_info)[3]._zLevel = 193;
set_ani_screen();
SHOULD_QUIT_RETURN;
if (!_G(det)->get_ani_status(CH_TO_FEEDER))
endLoopFl = true;
if (adi->delay_count > 0)
--adi->delay_count;
else {
adi->delay_count = adi->delay + _G(gameState).DelaySpeed;
if (adi->ani_count > 135)
--adi->ani_count;
}
}
_G(gameState)._personHide[P_CHEWY] = false;
_G(flags).AniUserAction = false;
clear_prog_ani();
}
void Room0::checkPillow() {
AniDetailInfo *adi = _G(det)->getAniDetail(FEEDER_HOSE);
adi->ani_count = 161;
bool endLoopFl = false;
_G(gameState)._personHide[P_CHEWY] = true;
_G(det)->startDetail(CH_THROWS_PILLOW, 1, ANI_FRONT);
bool mode = false;
while (!endLoopFl) {
clear_prog_ani();
if (!_G(det)->get_ani_status(CH_THROWS_PILLOW)) {
mode = true;
_G(gameState)._personHide[P_CHEWY] = false;
setPersonPos(228 - CH_HOT_MOV_X, 143 - CH_HOT_MOV_Y, P_CHEWY, P_LEFT);
}
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, FLAP_DETAIL, FLAP_SPRITE, ANI_HIDE);
_G(spr_info)[0]._zLevel = 190;
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, FEEDER_HOSE, 138, ANI_HIDE);
_G(spr_info)[1]._zLevel = 191;
if (mode) {
_G(spr_info)[2] = _G(det)->plot_detail_sprite(0, 0, FEEDER_HOSE, adi->ani_count, ANI_HIDE);
_G(spr_info)[2]._zLevel = 192;
}
setupScreen(DO_SETUP);
SHOULD_QUIT_RETURN;
if (mode) {
if (adi->delay_count > 0)
--adi->delay_count;
else {
adi->delay_count = adi->delay + _G(gameState).DelaySpeed;
--adi->ani_count;
if (adi->ani_count == 151)
endLoopFl = true;
}
}
}
clear_prog_ani();
}
void Room0::trapDoorOpen() {
_G(det)->startDetail(FLAP_DETAIL, 1, ANI_FRONT);
while (_G(det)->get_ani_status(FLAP_DETAIL)) {
set_ani_screen();
SHOULD_QUIT_RETURN;
}
_G(flags).AniUserAction = true;
for (int16 i = 0; i < 25; i++) {
clear_prog_ani();
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, FLAP_DETAIL, FLAP_SPRITE, ANI_HIDE);
_G(spr_info)[0]._zLevel = 190;
set_ani_screen();
SHOULD_QUIT_RETURN;
}
_G(flags).AniUserAction = false;
clear_prog_ani();
}
void Room0::trapDoorClose() {
_G(det)->startDetail(FLAP_DETAIL, 1, ANI_BACK);
while (_G(det)->get_ani_status(FLAP_DETAIL)) {
set_ani_screen();
EVENTS_UPDATE;
SHOULD_QUIT_RETURN;
}
}
void Room0::feederAni() {
int16 action = false;
feederStart(0);
if (_G(gameState).R0SlimeUsed) {
feederExtend();
if (_G(gameState).R0PillowThrow) {
checkPillow();
feederStart(1);
autoMove(VERSTECK_POS, P_CHEWY);
setupScreen(DO_SETUP);
_G(out)->cls();
flic_cut(FCUT_000);
register_cutscene(1);
_G(gameState)._personRoomNr[P_CHEWY] = 1;
_G(room)->loadRoom(&_G(room_blk), _G(gameState)._personRoomNr[P_CHEWY], &_G(gameState));
setPersonPos(_G(Rdi)->autoMove[4]._x - CH_HOT_MOV_X,
_G(Rdi)->autoMove[4]._y - CH_HOT_MOV_Y, P_CHEWY, P_RIGHT);
_G(moveState)[P_CHEWY]._delayCount = 0;
setShadowPalette(4, false);
_G(fx_blend) = BLEND1;
setupScreen(DO_SETUP);
} else {
action = true;
}
} else {
action = true;
}
if (action) {
checkFeed();
start_spz(CH_EKEL, 3, ANI_FRONT, P_CHEWY);
start_aad(55);
feederStart(1);
}
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,79 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM0_H
#define CHEWY_ROOMS_ROOM0_H
namespace Chewy {
namespace Rooms {
/**
* Prison Cell - Starting room
*/
class Room0 {
private:
/**
* Do the basic eye animation.
*/
enum EyeMode { EYE_START = 0, EYE_END = 1 };
static void eyeStart(EyeMode mode);
/**
* Pause after the eye arrives
*/
static void eyeWait();
/**
* Do the eye shooting animation
*/
static void eyeShoot();
static void eyeSlimeBack();
static void checkSlimeEye();
static void feederStart(int16 mode);
static void checkFeed();
static void checkPillow();
static void feederExtend();
static void trapDoorOpen();
static void trapDoorClose();
static void calcEyeClick(int16 aniNr);
static void calcPillowClick(int16 aniNr);
public:
static void entry();
static bool timer(int16 timerNr, int16 aniNr);
static void eyeAnim();
static void feederAni();
static bool getPillow();
static bool pullSlime();
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,64 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/room.h"
#include "chewy/rooms/room01.h"
namespace Chewy {
namespace Rooms {
void Room1::gottenCard() {
_G(det)->hideStaticSpr(2);
startSetAILWait(4, 1, ANI_FRONT);
_G(gameState)._personHide[P_CHEWY] = false;
_G(atds)->delControlBit(7, ATS_COUNT_BIT);
}
void Room1::gedAction(int index) {
#define CABLEBOX 1
if (index == 0 && !_G(gameState).R2ElectrocutedBork) {
bool pickedUpCable = false;
if (_G(cur)->getInventoryCursor() == CABLE_INV) {
pickedUpCable = true;
delInventory(_G(cur)->getInventoryCursor());
} else if (_G(obj)->checkInventory(CABLE_INV)) {
pickedUpCable = true;
_G(obj)->del_obj_use(CABLE_INV);
remove_inventory(CABLE_INV);
}
if (pickedUpCable) {
startAadWait(54);
_G(atds)->set_ats_str(8, TXT_MARK_LOOK, 0, ATS_DATA);
_G(gameState).room_s_obj[CABLEBOX].ZustandFlipFlop = 2;
_G(obj)->calc_rsi_flip_flop(CABLEBOX);
_G(obj)->calc_all_static_detail();
}
}
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,37 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM1_H
#define CHEWY_ROOMS_ROOM1_H
namespace Chewy {
namespace Rooms {
class Room1 {
public:
static void gottenCard();
static void gedAction(int index);
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,94 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/room.h"
#include "chewy/rooms/room02.h"
namespace Chewy {
namespace Rooms {
#define ANI_5 5
#define GRID_FLASHING 7
static const AniBlock ABLOCK4[2] = {
{ GRID_FLASHING, 3, ANI_FRONT, ANI_WAIT, 0 },
{ GRID_FLASHING, 12, ANI_FRONT, ANI_GO, 0 }
};
void Room2::entry() {
if (!_G(gameState).R2ElectrocutedBork)
_G(det)->startDetail(5, 255, ANI_FRONT);
}
void Room2::jump_out_r1(int16 nr) {
_G(gameState)._personHide[P_CHEWY] = true;
startSetAILWait(nr, 1, ANI_FRONT);
setupScreen(DO_SETUP);
_G(det)->stopDetail(6);
setPersonPos(32, 127, P_CHEWY, P_LEFT);
_G(gameState)._personHide[P_CHEWY] = false;
clear_prog_ani();
switchRoom(1);
setShadowPalette(2, true);
}
void Room2::electrifyWalkway1() {
_G(det)->startDetail(ANI_5, 255, ANI_FRONT);
start_spz(CH_TALK6, 255, false, ANI_FRONT);
startAadWait(49);
_G(det)->stopDetail(ANI_5);
_G(det)->startDetail(GRID_FLASHING, 12, ANI_FRONT);
_G(gameState).R2ElectrocutedBork = true;
delInventory(_G(cur)->getInventoryCursor());
_G(atds)->delControlBit(11, ATS_COUNT_BIT);
_G(atds)->delControlBit(11, ATS_ACTION_BIT);
_G(atds)->delControlBit(19, ATS_COUNT_BIT);
_G(atds)->delControlBit(25, ATS_ACTIVE_BIT);
_G(atds)->setControlBit(8, ATS_COUNT_BIT);
_G(atds)->set_all_ats_str(11, 1, ATS_DATA);
}
void Room2::electrifyWalkway2() {
start_spz(CH_TALK12, 255, false, P_CHEWY);
startAadWait(47);
}
void Room2::gedAction(int index) {
if (index == 0) {
_G(det)->stopDetail(5);
if (!_G(gameState).R2ElectrocutedBork)
_G(det)->startDetail(6, 2, ANI_FRONT);
else
startAniBlock(2, ABLOCK4);
jump_out_r1(9);
}
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,40 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM2_H
#define CHEWY_ROOMS_ROOM2_H
namespace Chewy {
namespace Rooms {
class Room2 {
public:
static void entry();
static void jump_out_r1(int16 nr);
static void electrifyWalkway1();
static void electrifyWalkway2();
static void gedAction(int index);
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,422 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/room.h"
#include "chewy/rooms/room02.h"
#include "chewy/rooms/room03.h"
#include "chewy/rooms/room04.h"
#include "chewy/sound.h"
namespace Chewy {
namespace Rooms {
#define HEADSHOT 0
#define SONDE_ANI 2
#define SONDE_SHOOT 3
#define SONDE_RET 4
#define SONDE_SMOKE 5
#define SONDE_CLEAR 6
#define SONDE_GRAB 7
#define SONDE_GRAB1 8
#define SONDE_SPR_R 118
#define SONDE_SPR_L 120
#define GRID_FLASHING 7
#define SONDE_OBJ 0
#define SONDE_OBJ1 1
static const MovLine SONDE_MPKT[3] = {
{ { 13, 45, 75 }, 1, 2 },
{ { 237, 52, 160 }, 1, 2 },
{ { 4, 83, 180 }, 0, 2 }
};
static const int16 SONDE_PHASEN[4][2] = {
{ 120, 120 },
{ 118, 118 },
{ 141, 141 },
{ 119, 119 }
};
static const AniBlock ABLOCK0[5] = {
{ 6, 1, ANI_FRONT, ANI_WAIT, 0 },
{ 7, 3, ANI_FRONT, ANI_WAIT, 0 },
};
static const AniBlock ABLOCK1[2] = {
{ 10, 1, ANI_FRONT, ANI_WAIT, 0 },
{ 13, 1, ANI_FRONT, ANI_WAIT, 0 },
};
static const AniBlock ABLOCK2[2] = {
{ 12, 1, ANI_FRONT, ANI_WAIT, 0 },
{ GRID_FLASHING, 1, ANI_FRONT, ANI_GO, 0 }
};
static const AniBlock ABLOCK3[2] = {
{ 4, 2, ANI_FRONT, ANI_GO, 0 },
{ 11, 255, ANI_FRONT, ANI_GO, 0 }
};
static const AniBlock ablock5[3] = {
{ 0, 1, ANI_FRONT, ANI_WAIT, 0 },
{ 8, 9, ANI_FRONT, ANI_GO, 0 },
{ 1, 1, ANI_FRONT, ANI_WAIT, 0 },
};
void Room3::entry() {
probeInit();
}
void Room3::terminal() {
showCur();
_G(auto_obj) = 0;
switch (Room4::comp_probe()) {
case 0:
probeTransfer();
_G(spr_info)[0]._image = _G(room_blk)._detImage[120];
_G(spr_info)[0]._x = 250;
_G(spr_info)[0]._y = 2;
_G(spr_info)[0]._zLevel = 0;
if (!_G(gameState).R2ElectrocutedBork) {
_G(det)->stopDetail(5);
startAniBlock(2, ABLOCK3);
if (_G(gameState).R2FussSchleim) {
_G(gameState).R2FussSchleim = false;
_G(gameState).room_s_obj[SIB_SLIME].ZustandFlipFlop = 1;
}
_G(gameState)._personHide[P_CHEWY] = true;
startSetAILWait(8, 1, ANI_FRONT);
setupScreen(DO_SETUP);
_G(det)->stopDetail(6);
clear_prog_ani();
switchRoom(1);
startAniBlock(2, ABLOCK0);
setPersonPos(92, 131, P_CHEWY, P_LEFT);
_G(gameState)._personHide[P_CHEWY] = false;
} else if (!_G(gameState).R2FussSchleim) {
startAniBlock(2, ABLOCK2);
Room2::jump_out_r1(9);
startAadWait(45);
} else {
_G(gameState)._personHide[P_CHEWY] = true;
startAniBlock(2, ABLOCK1);
_G(gameState)._personRoomNr[P_CHEWY] = 5;
clear_prog_ani();
_G(auto_obj) = 0;
_G(room)->loadRoom(&_G(room_blk), _G(gameState)._personRoomNr[P_CHEWY], &_G(gameState));
_G(fx_blend) = BLEND1;
startAniBlock(3, ablock5);
setPersonPos(91, 107, P_CHEWY, P_LEFT);
_G(gameState)._personHide[P_CHEWY] = false;
}
clear_prog_ani();
break;
case 1:
_G(auto_obj) = 1;
_G(mouseLeftClick) = false;
_G(minfo).button = 0;
stopPerson(P_CHEWY);
start_spz(15, 255, false, P_CHEWY);
startAadWait(51);
setupScreen(DO_SETUP);
break;
case 2:
probeCreak();
break;
default:
break;
}
}
void Room3::probeInit() {
_G(auto_obj) = 1;
_G(mov_phasen)[SONDE_OBJ].AtsText = 24;
_G(mov_phasen)[SONDE_OBJ].Lines = 3;
_G(mov_phasen)[SONDE_OBJ].Repeat = 255;
_G(mov_phasen)[SONDE_OBJ].ZoomFak = 20;
_G(auto_mov_obj)[SONDE_OBJ].Id = AUTO_OBJ0;
_G(auto_mov_vector)[SONDE_OBJ].Delay = _G(gameState).DelaySpeed;
_G(auto_mov_obj)[SONDE_OBJ].Mode = true;
init_auto_obj(SONDE_OBJ, &SONDE_PHASEN[0][0], 3, (const MovLine *)SONDE_MPKT);
}
void Room3::probeCreak() {
MovLine sonde_mpkt1[3] = {
{ { 237, 52, 160 }, 0, 2 },
{ { 13, 45, 75 }, 0, 4 },
{ { 4, 100, 180 }, 1, 2 }
};
MovLine sonde_mpkt2[2] = {
{ { 4, 100, 180 }, 1, 3 },
{ { 13, 45, 75 }, 1, 3 }
};
hideCur();
RoomDetailInfo *rdi = _G(det)->getRoomDetailInfo();
_G(det)->load_taf_seq(162, 17, nullptr);
int16 tmp = _G(zoom_horizont);
_G(zoom_horizont) = 100;
_G(auto_obj) = 1;
_G(mov_phasen)[SONDE_OBJ].Lines = 3;
_G(mov_phasen)[SONDE_OBJ].Repeat = 1;
_G(mov_phasen)[SONDE_OBJ].ZoomFak = 20;
_G(auto_mov_obj)[SONDE_OBJ].Id = AUTO_OBJ0;
_G(auto_mov_vector)[SONDE_OBJ].Delay = _G(gameState).DelaySpeed;
_G(auto_mov_obj)[SONDE_OBJ].Mode = true;
init_auto_obj(SONDE_OBJ, &SONDE_PHASEN[0][0], 3, (MovLine*)sonde_mpkt1);
_G(flags).AniUserAction = false;
while (_G(mov_phasen)[SONDE_OBJ].Repeat != -1) {
set_ani_screen();
SHOULD_QUIT_RETURN;
}
_G(det)->startDetail(SONDE_SHOOT, 1, ANI_FRONT);
int16 ende = 0;
while (!ende) {
clear_prog_ani();
if (rdi->Ainfo[SONDE_SHOOT].ani_count == 170) {
_G(gameState)._personHide[P_CHEWY] = true;
_G(det)->startDetail(HEADSHOT, 1, ANI_FRONT);
}
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, SONDE_ANI, SONDE_SPR_R, ANI_HIDE);
_G(spr_info)[0]._zLevel = 0;
if (rdi->Ainfo[HEADSHOT].ani_count >= 13 && rdi->Ainfo[HEADSHOT].ani_count <= 21) {
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, HEADSHOT, 21, ANI_HIDE);
_G(spr_info)[1]._zLevel = 190;
} else if (rdi->Ainfo[HEADSHOT].ani_count > 21 && _G(det)->get_ani_status(SONDE_RET) == 0) {
_G(spr_info)[2] = _G(det)->plot_detail_sprite(0, 0, SONDE_RET, 173, ANI_HIDE);
_G(spr_info)[2]._zLevel = 190;
}
if (rdi->Ainfo[SONDE_SHOOT].ani_count == 178)
_G(det)->startDetail(SONDE_RET, 3, ANI_BACK);
if (rdi->Ainfo[HEADSHOT].ani_count == 28)
ende = 1;
set_ani_screen();
SHOULD_QUIT_RETURN;
}
clear_prog_ani();
_G(det)->startDetail(SONDE_SMOKE, 3, ANI_FRONT);
ende = 0;
while (_G(det)->get_ani_status(SONDE_SMOKE)) {
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, SONDE_ANI, SONDE_SPR_R, ANI_HIDE);
_G(spr_info)[0]._zLevel = 0;
_G(spr_info)[1] = _G(det)->plot_detail_sprite(0, 0, SONDE_RET, 173, ANI_HIDE);
_G(spr_info)[1]._zLevel = 190;
++ende;
if (ende == 3)
_G(gameState)._personHide[P_CHEWY] = false;
set_ani_screen();
SHOULD_QUIT_RETURN;
}
start_spz(15, 255, false, P_CHEWY);
startAadWait(53);
clear_prog_ani();
_G(det)->startDetail(SONDE_CLEAR, 1, ANI_BACK);
while (_G(det)->get_ani_status(SONDE_CLEAR)) {
SHOULD_QUIT_RETURN;
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, SONDE_ANI, SONDE_SPR_R, ANI_HIDE);
_G(spr_info)[0]._zLevel = 0;
set_ani_screen();
}
clear_prog_ani();
_G(mov_phasen)[SONDE_OBJ].Lines = 2;
_G(mov_phasen)[SONDE_OBJ].Repeat = 1;
_G(mov_phasen)[SONDE_OBJ].ZoomFak = 28;
init_auto_obj(SONDE_OBJ, &SONDE_PHASEN[0][0], 2, (MovLine*)sonde_mpkt2);
while (_G(mov_phasen)[SONDE_OBJ].Repeat != -1) {
set_ani_screen();
SHOULD_QUIT_RETURN;
}
_G(det)->del_taf_tbl(162, 17, nullptr);
_G(zoom_horizont) = tmp;
probeInit();
showCur();
}
void Room3::probeTransfer() {
static const MovLine SONDE_MPKT1[2] = {
{ { 237, 52, 160 }, 0, 2 },
{ { 144, 100, 180 }, 0, 2 }
};
static const MovLine SONDE_MPKT_[4][2] = {
{ { { 144, 100, 180 }, 0, 2 },
{ { 110, 100, 180 }, 0, 2 } },
{ { { 110, 101, 180 }, 0, 3 },
{ { -55, 50, 180 }, 0, 3 } },
{ { { 310, 20, 180 }, 0, 3 },
{ { -55, 20, 180 }, 0, 3 } },
{ { { 310, 2, 180 }, 0, 3 },
{ { 250, 2, 180 }, 0, 3 } }
};
_G(flags).AniUserAction = false;
hideCur();
_G(det)->getRoomDetailInfo();
int16 tmp = _G(zoom_horizont);
_G(zoom_horizont) = 100;
int16 anistart = false;
_G(auto_obj) = 1;
_G(mov_phasen)[SONDE_OBJ].Lines = 2;
_G(mov_phasen)[SONDE_OBJ].Repeat = 1;
_G(mov_phasen)[SONDE_OBJ].ZoomFak = 20;
_G(auto_mov_obj)[SONDE_OBJ].Id = AUTO_OBJ0;
_G(auto_mov_vector)[SONDE_OBJ].Delay = _G(gameState).DelaySpeed;
_G(auto_mov_obj)[SONDE_OBJ].Mode = true;
init_auto_obj(SONDE_OBJ, &SONDE_PHASEN[0][0], 2, (const MovLine *)SONDE_MPKT1);
_G(atds)->set_all_ats_str(24, ATS_ACTIVE_BIT, ATS_DATA);
while (_G(mov_phasen)[SONDE_OBJ].Repeat != -1) {
set_ani_screen();
SHOULD_QUIT_RETURN;
}
_G(det)->startDetail(SONDE_GRAB, 1, ANI_FRONT);
while (_G(det)->get_ani_status(SONDE_GRAB)) {
clear_prog_ani();
_G(spr_info)[0] = _G(det)->plot_detail_sprite(0, 0, SONDE_GRAB, SONDE_SPR_L, ANI_HIDE);
_G(spr_info)[0]._zLevel = 146;
set_ani_screen();
SHOULD_QUIT_RETURN;
}
clear_prog_ani();
_G(auto_obj) = 2;
int16 spr_nr = 140;
for (int16 i = 0; i < 4 && !SHOULD_QUIT; i++) {
_G(mov_phasen)[SONDE_OBJ].Lines = 2;
_G(mov_phasen)[SONDE_OBJ].Repeat = 1;
_G(mov_phasen)[SONDE_OBJ].ZoomFak = 0;
_G(auto_mov_obj)[SONDE_OBJ].Id = AUTO_OBJ0;
_G(auto_mov_obj)[SONDE_OBJ].Mode = true;
_G(auto_mov_vector)[SONDE_OBJ].Delay = _G(gameState).DelaySpeed;
init_auto_obj(SONDE_OBJ, &SONDE_PHASEN[0][0], 2, SONDE_MPKT_[i]);
_G(mov_phasen)[SONDE_OBJ1].Lines = 2;
_G(mov_phasen)[SONDE_OBJ1].Repeat = 1;
_G(mov_phasen)[SONDE_OBJ1].ZoomFak = 0;
_G(auto_mov_obj)[SONDE_OBJ1].Id = AUTO_OBJ1;
_G(auto_mov_obj)[SONDE_OBJ1].Mode = true;
_G(auto_mov_vector)[SONDE_OBJ1].Delay = _G(gameState).DelaySpeed;
init_auto_obj(SONDE_OBJ1, &SONDE_PHASEN[0][0], 2, SONDE_MPKT_[i]);
_G(mov_phasen)[SONDE_OBJ1].Phase[0][0] = spr_nr;
_G(mov_phasen)[SONDE_OBJ1].Phase[0][1] = spr_nr;
while (_G(mov_phasen)[SONDE_OBJ].Repeat != -1) {
SHOULD_QUIT_RETURN;
if (i == 2 || i == 1) {
if (mouse_auto_obj(SONDE_OBJ, 50, 100)) {
if (_G(minfo).button == 1 || g_events->_kbInfo._keyCode == Common::KEYCODE_RETURN) {
if (isCurInventory(SPINAT_INV)) {
_G(atds)->set_split_win(0, 120, 100);
if (_G(gameState)._personRoomNr[P_CHEWY] == 3)
start_aad(50);
else
start_aad(44);
delInventory(_G(cur)->getInventoryCursor());
_G(gameState).R2FussSchleim = true;
_G(mov_phasen)[SONDE_OBJ1].Phase[0][0] = 142;
_G(mov_phasen)[SONDE_OBJ1].Phase[0][1] = 149;
_G(auto_mov_vector)[SONDE_OBJ1].PhAnz = 8;
anistart = true;
}
}
}
}
set_ani_screen();
if (anistart) {
if (_G(auto_mov_vector)[SONDE_OBJ1].PhNr == 7) {
anistart = false;
spr_nr = 149;
_G(mov_phasen)[SONDE_OBJ1].Phase[0][0] = spr_nr;
_G(mov_phasen)[SONDE_OBJ1].Phase[0][1] = spr_nr;
_G(auto_mov_vector)[SONDE_OBJ1].PhAnz = 1;
_G(auto_mov_vector)[SONDE_OBJ1].PhNr = 0;
}
}
}
switch (i) {
case 0:
showCur();
start_aad(52);
_G(flags).AniUserAction = true;
spr_nr = 141;
_G(gameState)._personHide[P_CHEWY] = true;
_G(det)->load_taf_seq(142, 8, nullptr);
break;
case 1:
g_engine->_sound->waitForSpeechToFinish();
_G(atds)->set_all_ats_str(24, 0, ATS_DATA);
_G(mov_phasen)[0].AtsText = 544;
switchRoom(1);
break;
case 2:
g_engine->_sound->waitForSpeechToFinish();
_G(det)->del_taf_tbl(142, 7, nullptr);
_G(flags).AniUserAction = false;
_G(mov_phasen)[0].AtsText = 24;
switchRoom(2);
break;
default:
break;
}
}
_G(flags).AniUserAction = false;
_G(zoom_horizont) = tmp;
_G(auto_obj) = 0;
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,41 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM3_H
#define CHEWY_ROOMS_ROOM3_H
namespace Chewy {
namespace Rooms {
class Room3 {
private:
static void probeCreak();
static void probeTransfer();
static void probeInit();
public:
static void entry();
static void terminal();
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,161 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/room.h"
#include "chewy/rooms/room04.h"
#include "chewy/sound.h"
namespace Chewy {
namespace Rooms {
#define HAND_NORMAL 68
#define HAND_CLICK 69
#define RED_FRAME 70
#define YELLOW_FRAME 71
int16 Room4::comp_probe() {
static const int16 CUR_POS[3][2] = {
{ 83, 106 },
{ 136, 103 },
{ 188, 101 }
};
// This can't be static because it makes them global objects
const Common::Rect CONSOLE_HOTSPOTS[] = {
{ 80, 140, 120, 175 },
{ 140, 140, 170, 175 },
{ 195, 140, 235, 175 }
};
cur_2_inventory();
_G(gameState)._personHide[P_CHEWY] = true;
switchRoom(4);
bool endLoop = false;
// TODO: The original limited the cursor height to 16 pixels
//WRITE_LE_INT16(_G(room_blk)._detImage[HAND_NORMAL] + 2, 16);
//WRITE_LE_INT16(_G(room_blk)._detImage[HAND_CLICK] + 2, 16);
_G(cur)->setCustomRoomCursor(_G(room_blk)._detImage[HAND_NORMAL]);
byte curCursor = HAND_NORMAL;
int16 curX = 1;
int16 sprNr = RED_FRAME;
_G(cur)->move(160, 160);
// Clear any pending keys
g_events->_kbInfo._keyCode = '\0';
g_events->_kbInfo._scanCode = Common::KEYCODE_INVALID;
_G(minfo).button = 0;
_G(mouseLeftClick) = false;
start_aad(46);
while (!endLoop) {
// WORKAROUND: The original constrained the mouse area.
// We don't do that in ScummVM so the below prevents
// potential crashes caused by the hand sprites being
// unloaded if the cursor is moved up too high
if (g_events->_mousePos.y < 135)
g_events->_mousePos.y = 135;
mouseAction();
if (_G(mouseLeftClick)) {
switch (_G(out)->findHotspot(CONSOLE_HOTSPOTS)) {
case 0:
if (curX > 0)
--curX;
else
curX = 2;
_G(det)->playSound(0, 1);
break;
case 1:
endLoop = true;
sprNr = YELLOW_FRAME;
_G(det)->playSound(0, 0);
break;
case 2:
if (curX < 2)
++curX;
else
curX = 0;
_G(det)->playSound(0, 2);
break;
default:
break;
}
}
_G(spr_info)[0]._image = _G(room_blk)._detImage[sprNr];
_G(spr_info)[0]._zLevel = 0;
_G(spr_info)[0]._x = CUR_POS[curX][0];
_G(spr_info)[0]._y = CUR_POS[curX][1];
if (_G(minfo).button == 1 || g_events->_kbInfo._keyCode == Common::KEYCODE_RETURN) {
if (curCursor != HAND_CLICK) {
_G(cur)->setCustomRoomCursor(_G(room_blk)._detImage[HAND_CLICK]);
_G(cur)->setAnimation(HAND_CLICK, HAND_CLICK, -1);
curCursor = HAND_CLICK;
}
} else {
if (curCursor != HAND_NORMAL) {
_G(cur)->setCustomRoomCursor(_G(room_blk)._detImage[HAND_NORMAL]);
_G(cur)->setAnimation(HAND_NORMAL, HAND_NORMAL, -1);
curCursor = HAND_NORMAL;
}
}
cursorChoice(CUR_USER);
if (g_events->_mousePos.y < 124)
g_events->_mousePos.y = 123;
setupScreen(DO_SETUP);
SHOULD_QUIT_RETURN0;
}
g_events->delay(500);
clear_prog_ani();
_G(gameState)._personHide[P_CHEWY] = false;
_G(menu_item) = CUR_WALK;
cursorChoice(_G(menu_item));
_G(moveState)[P_CHEWY]._delayCount = 0;
_G(mouseLeftClick) = false;
_G(minfo).button = 0;
_G(gameState)._personRoomNr[P_CHEWY] = 3;
_G(room)->loadRoom(&_G(room_blk), 3, &_G(gameState));
setPersonPos(110, 139, P_CHEWY, P_LEFT);
_G(fx_blend) = BLEND1;
_G(atds)->stopAad();
return curX;
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,36 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM4_H
#define CHEWY_ROOMS_ROOM4_H
namespace Chewy {
namespace Rooms {
class Room4 {
public:
static int16 comp_probe();
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,58 @@
/* 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/>.
*
*/
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/ani_dat.h"
#include "chewy/room.h"
#include "chewy/rooms/room05.h"
namespace Chewy {
namespace Rooms {
void Room5::entry() {
if (_G(gameState).R5Terminal)
_G(det)->startDetail(6, 255, ANI_FRONT);
}
void Room5::pushButton() {
if (_G(gameState).R5Terminal) {
int16 strNr;
if (_G(gameState).R5Door == false) {
startSetAILWait(9, 1, ANI_FRONT);
_G(gameState).room_e_obj[6].Attribut = EXIT_TOP;
strNr = 1;
} else {
startSetAILWait(9, 1, ANI_BACK);
_G(gameState).room_e_obj[6].Attribut = 255;
strNr = 0;
}
_G(atds)->set_all_ats_str(29, strNr, ATS_DATA);
_G(gameState).R5Door ^= 1;
_G(obj)->calc_rsi_flip_flop(SIB_DOOR_R5);
} else {
startAadWait(1);
}
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,37 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM5_H
#define CHEWY_ROOMS_ROOM5_H
namespace Chewy {
namespace Rooms {
class Room5 {
public:
static void entry();
static void pushButton();
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,130 @@
/* 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/>.
*
*/
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/ani_dat.h"
#include "chewy/rooms/room06.h"
namespace Chewy {
namespace Rooms {
static const int16 ROBO_PHASEN[4][2] = {
{ 86, 86 },
{ 86, 86 },
{ 86, 86 },
{ 86, 86 }
};
static const MovLine ROBO_MPKT[3] = {
{ { 168, 71, 180 }, 1, 1 },
{ { 180, 71, 100 }, 1, 2 },
{ { 60, 210, 110 }, 1, 16 }
};
static const AniBlock ABLOCK6[3] = {
{ 3, 1, ANI_FRONT, ANI_GO, 0 },
{ 13, 1, ANI_FRONT, ANI_WAIT, 0 },
{ 14, 4, ANI_FRONT, ANI_GO, 0 },
};
static const AniBlock ABLOCK7[2] = {
{ 1, 2, ANI_FRONT, ANI_WAIT, 0 },
{ 2, 1, ANI_FRONT, ANI_GO, 0 },
};
void Room6::entry() {
_G(zoom_horizont) = 80;
_G(flags).ZoomMov = true;
_G(zoom_mov_fak) = 2;
if (_G(gameState).R6BolaSchild && _G(gameState).R6RaumBetreten < 2) {
_G(det)->startDetail(7, 255, ANI_FRONT);
_G(atds)->delControlBit(44, ATS_ACTIVE_BIT);
if (!_G(flags).LoadGame)
++_G(gameState).R6RaumBetreten;
if (_G(gameState).R6RaumBetreten == 2) {
hideCur();
_G(det)->stopDetail(7);
init_robo();
wait_auto_obj(0);
_G(gameState).R6BolaOk = true;
_G(obj)->show_sib(SIB_BOLA_BUTTON_R6);
_G(obj)->hide_sib(SIB_BOLA_R6);
_G(atds)->setControlBit(44, ATS_ACTIVE_BIT);
showCur();
}
}
}
void Room6::init_robo() {
#define ROBO_OBJ 0
_G(auto_obj) = 1;
_G(mov_phasen)[ROBO_OBJ].AtsText = 44;
_G(mov_phasen)[ROBO_OBJ].Lines = 3;
_G(mov_phasen)[ROBO_OBJ].Repeat = 1;
_G(mov_phasen)[ROBO_OBJ].ZoomFak = 0;
_G(auto_mov_obj)[ROBO_OBJ].Id = AUTO_OBJ0;
_G(auto_mov_vector)[ROBO_OBJ].Delay = _G(gameState).DelaySpeed;
_G(auto_mov_obj)[ROBO_OBJ].Mode = true;
init_auto_obj(ROBO_OBJ, &ROBO_PHASEN[0][0], 3, (const MovLine *)ROBO_MPKT);
}
void Room6::bola_button() {
if (!_G(gameState).R6BolaBecher) {
_G(det)->hideStaticSpr(0);
startSetAILWait(0, 1, ANI_FRONT);
if (_G(gameState).R6BolaOk) {
_G(gameState).R6BolaBecher = true;
_G(det)->showStaticSpr(0);
startAniBlock(2, ABLOCK7);
_G(obj)->calc_rsi_flip_flop(SIB_BOLA_FLECK_R6);
waitDetail(2);
_G(obj)->calc_rsi_flip_flop(SIB_BOLA_SCHACHT);
_G(atds)->delControlBit(42, ATS_ACTIVE_BIT);
_G(atds)->set_ats_str(41, TXT_MARK_LOOK, 1, ATS_DATA);
_G(obj)->calc_rsi_flip_flop(SIB_BOLA_BUTTON_R6);
_G(obj)->hide_sib(SIB_BOLA_BUTTON_R6);
} else {
_G(gameState)._personHide[P_CHEWY] = true;
startAniBlock(3, ABLOCK6);
while (_G(det)->get_ani_status(3) && !SHOULD_QUIT) {
if (!_G(det)->get_ani_status(14)) {
setPersonPos(220, 89, P_CHEWY, P_LEFT);
_G(gameState)._personHide[P_CHEWY] = false;
}
setupScreen(DO_SETUP);
}
_G(det)->showStaticSpr(0);
++_G(gameState).R6BolaJoke;
int16 diaNr = (_G(gameState).R6BolaJoke < 3) ? 3 : 4;
start_spz(CH_TALK5, 244, false, 0);
startAadWait(diaNr);
}
_G(obj)->calc_rsi_flip_flop(SIB_BOLA_BUTTON_R6);
}
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,40 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM6_H
#define CHEWY_ROOMS_ROOM6_H
namespace Chewy {
namespace Rooms {
class Room6 {
private:
static void init_robo();
public:
static void entry();
static void bola_button();
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,187 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/ani_dat.h"
#include "chewy/rooms/room07.h"
namespace Chewy {
namespace Rooms {
static const AniBlock ABLOCK10[4] = {
{ 15, 2, ANI_FRONT, ANI_WAIT, 0 },
{ 16, 1, ANI_FRONT, ANI_WAIT, 0 },
{ 17, 2, ANI_FRONT, ANI_WAIT, 0 },
{ 18, 1, ANI_FRONT, ANI_WAIT, 0 },
};
static const AniBlock ABLOCK25[3] = {
{ 1, 1, ANI_FRONT, ANI_WAIT, 0 },
{ 5, 255, ANI_FRONT, ANI_GO, 0 },
{ 4, 1, ANI_FRONT, ANI_WAIT, 0 },
};
void Room7::entry() {
_G(gameState).ScrollxStep = 2;
}
void Room7::hook(int16 sibNr) {
int16 diaNr;
delInventory(8);
_G(cur)->setInventoryCursor(-1);
_G(menu_item) = CUR_WALK;
cursorChoice(_G(menu_item));
if (_G(gameState).R7RHaken) {
_G(gameState).R7RopeOk = true;
if (sibNr == SIB_LHAKEN_R7) {
_G(obj)->calc_rsi_flip_flop(SIB_LHAKEN_R7);
_G(obj)->calc_rsi_flip_flop(SIB_RHAKEN_R7);
}
_G(atds)->delControlBit(56, ATS_ACTIVE_BIT);
_G(atds)->set_ats_str(55, TXT_MARK_LOOK, 1, ATS_DATA);
diaNr = 9;
} else {
_G(gameState).R7RopeLeft = true;
diaNr = 48;
}
_G(obj)->calc_all_static_detail();
_G(atds)->set_ats_str(54, TXT_MARK_LOOK, 1, ATS_DATA);
startAadWait(diaNr);
}
void Room7::bell() {
hideCur();
if ((!_G(gameState).R7BellCount) ||
(_G(gameState).R7BellCount >= 2 && _G(gameState).R7RopeLeft && !_G(gameState).R7RopeOk)) {
_G(gameState)._personHide[P_CHEWY] = true;
start_aad(5, 0);
startAniBlock(3, ABLOCK25);
_G(det)->showStaticSpr(7);
startSetAILWait(12, 1, ANI_FRONT);
startSetAILWait(11, 1, ANI_FRONT);
_G(det)->hideStaticSpr(7);
_G(det)->stopDetail(5);
setPersonPos(95, 94, P_CHEWY, P_RIGHT);
_G(gameState)._personHide[P_CHEWY] = false;
} else if (_G(gameState).R7BellCount == 1) {
_G(gameState)._personHide[P_CHEWY] = true;
start_aad(6, 0);
startAniBlock(3, ABLOCK25);
_G(det)->showStaticSpr(7);
startSetAILWait(10, 1, ANI_FRONT);
_G(det)->startDetail(13, 1, ANI_FRONT);
setPersonPos(95, 94, P_CHEWY, P_RIGHT);
_G(det)->stopDetail(5);
_G(gameState)._personHide[P_CHEWY] = false;
_G(flags).NoScroll = true;
autoMove(6, P_CHEWY);
_G(gameState)._personHide[P_CHEWY] = true;
_G(det)->startDetail(0, 255, ANI_FRONT);
startSetAILWait(13, 1, ANI_FRONT);
flic_cut(FCUT_001);
_G(det)->stopDetail(0);
_G(gameState).scrollx = 0;
_G(gameState).scrolly = 0;
setPersonPos(114, 138, P_CHEWY, -1);
startDetailFrame(19, 1, ANI_FRONT, 6);
startDetailFrame(9, 1, ANI_FRONT, 4);
_G(det)->showStaticSpr(9);
waitDetail(9);
_G(det)->hideStaticSpr(9);
_G(obj)->show_sib(SIB_SCHLOTT_R7);
_G(obj)->calc_rsi_flip_flop(SIB_SCHLOTT_R7);
_G(gameState)._personHide[P_CHEWY] = false;
_G(flags).NoScroll = false;
_G(det)->hideStaticSpr(7);
} else if (!_G(gameState).R7RopeOk) {
_G(gameState)._personHide[P_CHEWY] = true;
start_aad(7, 0);
startAniBlock(3, ABLOCK25);
_G(det)->showStaticSpr(7);
_G(det)->load_taf_seq(192, 74, nullptr);
_G(det)->startDetail(14, 1, ANI_FRONT);
setPersonPos(95, 94, P_CHEWY, P_RIGHT);
_G(det)->stopDetail(5);
_G(gameState)._personHide[P_CHEWY] = false;
_G(flags).NoScroll = true;
autoMove(6, P_CHEWY);
_G(gameState)._personHide[P_CHEWY] = true;
_G(det)->startDetail(0, 255, ANI_FRONT);
waitDetail(14);
startAniBlock(4, ABLOCK10);
_G(det)->hideStaticSpr(7);
_G(det)->stopDetail(0);
setPersonPos(181, 130, P_CHEWY, P_RIGHT);
_G(gameState)._personHide[P_CHEWY] = false;
_G(flags).NoScroll = false;
_G(det)->del_taf_tbl(192, 74, nullptr);
} else if (_G(gameState).R7RopeOk && !_G(gameState).R7BorkFlug) {
_G(gameState).R7BorkFlug = true;
_G(gameState)._personHide[P_CHEWY] = true;
start_aad(8, 0);
startSetAILWait(1, 1, ANI_FRONT);
_G(obj)->set_rsi_flip_flop(SIB_TBUTTON2_R7, 255);
_G(obj)->hide_sib(SIB_KLINGEL_R7);
_G(flags).NoPalAfterFlc = false;
register_cutscene(2);
flic_cut(FCUT_002);
setPersonPos(201, 117, P_CHEWY, P_LEFT);
_G(gameState).scrollx = 0;
_G(gameState).scrolly = 0;
_G(gameState)._personHide[P_CHEWY] = false;
}
++_G(gameState).R7BellCount;
showCur();
}
void Room7::gedAction(int index) {
if (index == 0 && _G(gameState).R7BorkFlug && _G(gameState).R7ChewyFlug) {
_G(gameState)._personHide[P_CHEWY] = true;
setPersonPos(180, 124, P_CHEWY, P_LEFT);
startSetAILWait(20, 1, ANI_FRONT);
_G(det)->showStaticSpr(10);
waitShowScreen(10 * _G(gameState).DelaySpeed);
_G(det)->hideStaticSpr(10);
_G(gameState)._personHide[P_CHEWY] = false;
_G(gameState).R7ChewyFlug = false;
}
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,39 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM7_H
#define CHEWY_ROOMS_ROOM7_H
namespace Chewy {
namespace Rooms {
class Room7 {
public:
static void entry();
static void hook(int16 sibNr);
static void bell();
static void gedAction(int index);
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,190 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/ani_dat.h"
#include "chewy/room.h"
#include "chewy/rooms/room08.h"
#include "chewy/dialogs/inventory.h"
namespace Chewy {
namespace Rooms {
static const AniBlock ABLOCK12[2] = {
{ 8, 1, ANI_FRONT, ANI_WAIT, 0 },
{ 9, 2, ANI_FRONT, ANI_GO, 0 },
};
static const AniBlock ABLOCK13[2] = {
{10, 1, ANI_FRONT, ANI_WAIT, 0},
{11, 255, ANI_FRONT, ANI_GO, 0},
};
void Room8::entry() {
_G(gameState).R7ChewyFlug = true;
if (!_G(gameState).R8Folter)
start_folter();
else
stop_folter();
_G(atds)->set_all_ats_str(60, 0, ATS_DATA);
}
void Room8::start_folter() {
_G(atds)->set_all_ats_str(67, 1, ATS_DATA);
_G(det)->stopDetail(19);
_G(det)->startDetail(13, 255, ANI_FRONT);
}
void Room8::stop_folter() {
_G(atds)->set_all_ats_str(67, 0, ATS_DATA);
_G(det)->startDetail(19, 255, ANI_FRONT);
_G(det)->stopDetail(13);
_G(gameState).R8Folter = true;
_G(obj)->hide_sib(SIB_FOLTER_R8);
}
void Room8::hole_kohle() {
if (_G(gameState).R8Kohle) {
startAadWait(604);
} else {
hideCur();
_G(gameState).R8Kohle = true;
autoMove(4, P_CHEWY);
_G(gameState)._personHide[P_CHEWY] = true;
startSetAILWait(12, 1, ANI_FRONT);
cur_2_inventory();
invent_2_slot(KOHLE_HEISS_INV);
_G(gameState)._personHide[P_CHEWY] = false;
showCur();
}
}
void Room8::start_verbrennen() {
hideCur();
if (!_G(cur)->usingInventoryCursor()) {
autoMove(3, P_CHEWY);
start_aad(102, 0);
_G(gameState)._personHide[P_CHEWY] = true;
startAniBlock(2, ABLOCK12);
while (_G(det)->get_ani_status(9)) {
setupScreen(DO_SETUP);
SHOULD_QUIT_RETURN;
if (_G(minfo).button == 1 || g_events->_kbInfo._keyCode == Common::KEYCODE_RETURN) {
if (g_events->_mousePos.x > 146 && g_events->_mousePos.x < 208 &&
g_events->_mousePos.y > 107 && g_events->_mousePos.y < 155)
break;
}
}
_G(det)->stopDetail(9);
setPersonPos(129, 246, P_CHEWY, P_RIGHT);
startAniBlock(2, ABLOCK13);
_G(atds)->set_ats_str(60, TXT_MARK_LOOK, 1, ATS_DATA);
_G(gameState)._personHide[P_CHEWY] = false;
}
showCur();
}
bool Room8::gips_wurf() {
bool actionFl = false;
if (isCurInventory(GIPS_EIMER_INV)) {
hideCur();
actionFl = true;
_G(det)->load_taf_seq(116, 30, nullptr);
autoMove(2, P_CHEWY);
_G(mouseLeftClick) = false;
_G(gameState)._personHide[P_CHEWY] = true;
delInventory(GIPS_EIMER_INV);
startSetAILWait(4, 1, ANI_FRONT);
_G(gameState)._personHide[P_CHEWY] = false;
startDetailFrame(5, 1, ANI_FRONT, 16);
startSetAILWait(6, 1, ANI_FRONT);
_G(obj)->show_sib(33);
_G(det)->showStaticSpr(14);
waitDetail(5);
_G(gameState).R8GipsWurf = true;
_G(gameState).room_m_obj[MASKE_INV].ZEbene = 0;
_G(obj)->setInventory(MASKE_INV, 181, 251, 8, &_G(room_blk));
_G(det)->del_taf_tbl(116, 30, nullptr);
autoMove(8, P_CHEWY);
_G(flags).AtsAction = false;
_G(menu_item) = CUR_USE;
Dialogs::Inventory::look_screen(INVENTORY_NORMAL, 178);
_G(flags).AtsAction = true;
_G(gameState)._personHide[P_CHEWY] = true;
startSetAILWait(20, 1, ANI_FRONT);
_G(gameState)._personHide[P_CHEWY] = false;
invent_2_slot(MASKE_INV);
cursorChoice(_G(menu_item));
showCur();
}
return actionFl;
}
void Room8::open_gdoor() {
_G(gameState)._personHide[P_CHEWY] = true;
_G(det)->showStaticSpr(17);
setupScreen(DO_SETUP);
startSetAILWait(7, 1, ANI_FRONT);
_G(det)->showStaticSpr(15);
_G(det)->hideStaticSpr(17);
_G(gameState)._personHide[P_CHEWY] = false;
setPersonPos(204, 274, P_CHEWY, P_LEFT);
_G(atds)->delControlBit(69, ATS_ACTIVE_BIT);
_G(obj)->hide_sib(31);
_G(gameState).R8GTuer = true;
_G(gameState).room_e_obj[15].Attribut = EXIT_BOTTOM;
}
void Room8::talk_nimoy() {
autoMove(9, P_CHEWY);
_G(flags).NoScroll = true;
auto_scroll(0, 120);
if (_G(gameState).R8Folter) {
int16 diaNr = _G(gameState).R8GipsWurf ? 2 : 1;
if (!_G(gameState).R8GTuer)
loadDialogCloseup(diaNr);
else
startAadWait(61);
} else {
startAadWait(603);
loadDialogCloseup(6);
}
_G(flags).NoScroll = false;
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,43 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM8_H
#define CHEWY_ROOMS_ROOM8_H
namespace Chewy {
namespace Rooms {
class Room8 {
public:
static void entry();
static bool gips_wurf();
static void hole_kohle();
static void start_verbrennen();
static void talk_nimoy();
static void start_folter();
static void stop_folter();
static void open_gdoor();
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,122 @@
/* 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/>.
*
*/
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/room.h"
#include "chewy/rooms/room09.h"
namespace Chewy {
namespace Rooms {
static const int16 SURIMY_PHASEN[4][2] = {
{ 91, 98 },
{ 91, 98 },
{ 91, 98 },
{ 91, 98 }
};
static const MovLine SURIMY_MPKT[2] = {
{ { 80, 170, 199 }, 2, 6 },
{ { 210, 162, 199 }, 2, 6 }
};
static const MovLine SURIMY_MPKT1[2] = {
{ { 224, 158, 199 }, 2, 6 },
{ { 330, 162, 199 }, 2, 6 }
};
void Room9::entry() {
_G(gameState).R7ChewyFlug = false;
if (!_G(gameState).R9Grid)
setPersonPos(138, 91, P_CHEWY, P_LEFT);
else
_G(det)->showStaticSpr(5);
if (_G(gameState).R9Surimy) {
_G(det)->hideStaticSpr(4);
_G(room)->set_timer_status(7, TIMER_STOP);
}
}
void Room9::gtuer() {
_G(gameState).R9Grid = true;
_G(det)->showStaticSpr(5);
startSetAILWait(6, 1, ANI_FRONT);
setPersonPos(74, 93, P_CHEWY, P_LEFT);
_G(atds)->delControlBit(74, ATS_ACTIVE_BIT);
_G(atds)->delControlBit(75, ATS_ACTIVE_BIT);
_G(atds)->delControlBit(76, ATS_ACTIVE_BIT);
_G(obj)->show_sib(34);
_G(atds)->set_all_ats_str(73, 1, ATS_DATA);
}
void Room9::surimy() {
hideCur();
_G(gameState).R9Surimy = true;
const int16 tmp = _G(moveState)[P_CHEWY].Count;
stopPerson(P_CHEWY);
_G(atds)->setControlBit(75, ATS_ACTIVE_BIT);
_G(det)->hideStaticSpr(4);
_G(room)->set_timer_status(7, TIMER_STOP);
surimy_ani();
start_spz(CH_TALK11, 255, false, P_CHEWY);
startAadWait(56);
_G(gameState).room_e_obj[17].Attribut = EXIT_RIGHT;
_G(moveState)[P_CHEWY].Count = tmp;
get_phase(&_G(moveState)[P_CHEWY], &_G(spieler_mi)[P_CHEWY]);
_G(mov)->continue_auto_go();
showCur();
}
void Room9::surimy_ani() {
_G(det)->load_taf_seq(91, 8, nullptr);
_G(auto_obj) = 1;
_G(mov_phasen)[SURIMY_OBJ].AtsText = 0;
_G(mov_phasen)[SURIMY_OBJ].Lines = 2;
_G(mov_phasen)[SURIMY_OBJ].Repeat = 1;
_G(mov_phasen)[SURIMY_OBJ].ZoomFak = 0;
_G(auto_mov_obj)[SURIMY_OBJ].Id = AUTO_OBJ0;
_G(auto_mov_vector)[SURIMY_OBJ].Delay = _G(gameState).DelaySpeed;
_G(auto_mov_obj)[SURIMY_OBJ].Mode = true;
init_auto_obj(SURIMY_OBJ, &SURIMY_PHASEN[0][0], 2, (const MovLine *)SURIMY_MPKT);
wait_auto_obj(SURIMY_OBJ);
startDetailFrame(0, 1, ANI_FRONT, 15);
_G(det)->startDetail(2, 1, ANI_FRONT);
waitDetail(0);
startSetAILWait(1, 1, ANI_FRONT);
start_spz(CH_EKEL, 2, ANI_FRONT, P_CHEWY);
_G(det)->hideStaticSpr(4);
_G(mov_phasen)[SURIMY_OBJ].Repeat = 1;
init_auto_obj(SURIMY_OBJ, &SURIMY_PHASEN[0][0], _G(mov_phasen)[SURIMY_OBJ].Lines, (const MovLine *)SURIMY_MPKT1);
wait_auto_obj(SURIMY_OBJ);
_G(det)->del_taf_tbl(91, 8, nullptr);
}
void Room9::gedAction(int index) {
if (index == 0 && !_G(gameState).R9Surimy)
surimy();
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,42 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM9_H
#define CHEWY_ROOMS_ROOM9_H
namespace Chewy {
namespace Rooms {
class Room9 {
private:
static void surimy_ani();
public:
static void entry();
static void gedAction(int index);
static void gtuer();
static void surimy();
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,68 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/room.h"
#include "chewy/rooms/room10.h"
namespace Chewy {
namespace Rooms {
void Room10::entry() {
if (!_G(gameState).R10Surimy) {
_G(out)->setPointer(_G(workptr));
_G(out)->map_spr2screen(_G(ablage)[_G(room_blk).AkAblage], _G(gameState).scrollx, _G(gameState).scrolly);
_G(out)->setPointer(nullptr);
_G(fx)->blende1(_G(workptr), _G(pal), 0, 0);
_G(gameState).R10Surimy = true;
_G(fx_blend) = BLEND_NONE;
flic_cut(FCUT_003);
setPersonPos(0, 130, P_CHEWY, P_RIGHT);
autoMove(2, P_CHEWY);
hideCur();
start_spz(CH_TALK6, 255, false, P_CHEWY);
startAadWait(101);
showCur();
} else if (_G(gameState).R10SurimyOk) {
_G(room)->set_timer_status(3, TIMER_STOP);
}
}
void Room10::get_surimy() {
hideCur();
autoMove(4, P_CHEWY);
start_aad(104, 0);
flic_cut(FCUT_005);
_G(gameState).R10SurimyOk = true;
_G(room)->set_timer_status(3, TIMER_STOP);
_G(atds)->set_ats_str(77, TXT_MARK_LOOK, 1, ATS_DATA);
invent_2_slot(18);
delInventory(_G(cur)->getInventoryCursor());
showCur();
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,37 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM10_H
#define CHEWY_ROOMS_ROOM10_H
namespace Chewy {
namespace Rooms {
class Room10 {
public:
static void entry();
static void get_surimy();
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,207 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/ani_dat.h"
#include "chewy/room.h"
#include "chewy/rooms/room11.h"
namespace Chewy {
namespace Rooms {
AniBlock ABLOCK17[2] = {
{ 8, 1, ANI_FRONT, ANI_WAIT, 0 },
{ 9, 255, ANI_FRONT, ANI_GO, 0 },
};
AniBlock ABLOCK18[2] = {
{ 7, 1, ANI_FRONT, ANI_WAIT, 0 },
{ 7, 1, ANI_BACK, ANI_WAIT, 0 },
};
void Room11::entry() {
_G(zoom_horizont) = 80;
_G(flags).ZoomMov = true;
_G(zoom_mov_fak) = 2;
if (_G(gameState).R12ChewyBork) {
if (!_G(gameState).R11DoorRightB) {
_G(obj)->calc_rsi_flip_flop(SIB_TBUTTON2_R11);
_G(gameState).R11DoorRightB = exit_flip_flop(5, 22, -1, 98, -1, -1,
EXIT_TOP, -1, (int16)_G(gameState).R11DoorRightB);
_G(obj)->calc_all_static_detail();
}
_G(obj)->hide_sib(SIB_TBUTTON1_R11);
_G(obj)->hide_sib(SIB_SCHLITZ_R11);
_G(obj)->hide_sib(SIB_TBUTTON2_R11);
_G(obj)->hide_sib(SIB_TBUTTON3_R11);
_G(gameState).room_e_obj[20].Attribut = 255;
_G(gameState).room_e_obj[21].Attribut = 255;
_G(atds)->delControlBit(121, ATS_ACTIVE_BIT);
if (!_G(flags).LoadGame) {
startAniBlock(2, ABLOCK17);
autoMove(8, P_CHEWY);
startAadWait(31);
_G(det)->stopDetail(9);
}
_G(det)->showStaticSpr(8);
if (!_G(flags).LoadGame)
autoMove(6, P_CHEWY);
_G(timer_nr)[0] = _G(room)->set_timer(255, 10);
}
}
bool Room11::timer(int16 t_nr, int16 ani_nr) {
if (t_nr == _G(timer_nr)[0])
bork_zwinkert();
return false;
}
void Room11::gedAction(int index) {
switch (index) {
case 0:
chewy_bo_use();
break;
default:
break;
}
}
void Room11::bork_zwinkert() {
if (!_G(flags).AutoAniPlay) {
_G(flags).AutoAniPlay = true;
_G(det)->hideStaticSpr(8);
startAniBlock(2, ABLOCK18);
_G(uhr)->resetTimer(_G(timer_nr)[0], 0);
_G(det)->showStaticSpr(8);
_G(flags).AutoAniPlay = false;
}
}
void Room11::talk_debug() {
if (_G(gameState).R12ChewyBork) {
_G(flags).AutoAniPlay = true;
autoMove(8, P_CHEWY);
startDialogCloseupWait(5);
_G(menu_item) = CUR_WALK;
cursorChoice(CUR_WALK);
_G(flags).AutoAniPlay = false;
}
}
void Room11::chewy_bo_use() {
if (_G(gameState).R12ChewyBork) {
hideCur();
_G(flags).AutoAniPlay = true;
stopPerson(P_CHEWY);
_G(det)->hideStaticSpr(8);
startAniBlock(2, ABLOCK17);
startAadWait(32);
_G(det)->stopDetail(9);
_G(det)->showStaticSpr(8);
autoMove(6, P_CHEWY);
_G(flags).AutoAniPlay = false;
showCur();
}
}
int16 Room11::scanner() {
int16 actionFl = false;
if (!_G(gameState).R12ChewyBork) {
autoMove(7, P_CHEWY);
if (!_G(gameState).R11CardOk) {
actionFl = true;
startAadWait(13);
} else if (isCurInventory(BORK_INV)) {
hideCur();
setupScreen(DO_SETUP);
actionFl = true;
start_aad(105, 0);
flic_cut(FCUT_010);
register_cutscene(4);
_G(gameState).R11TerminalOk = true;
cur_2_inventory();
_G(menu_item) = CUR_TALK;
cursorChoice(_G(menu_item));
startAadWait(12);
showCur();
loadDialogCloseup(3);
} else if (!_G(cur)->usingInventoryCursor()) {
if (!_G(gameState).R11TerminalOk) {
actionFl = true;
flic_cut(FCUT_009);
startAadWait(20);
} else {
actionFl = true;
startAadWait(12);
_G(menu_item) = CUR_TALK;
cursorChoice(_G(menu_item));
loadDialogCloseup(3);
}
}
}
return actionFl;
}
void Room11::get_card() {
if (_G(gameState).R11CardOk) {
cur_2_inventory();
_G(gameState).R11CardOk = false;
_G(obj)->addInventory(_G(gameState).R11IdCardNr, &_G(room_blk));
_G(cur)->setInventoryCursor(_G(gameState).R11IdCardNr);
_G(det)->stopDetail(0);
_G(atds)->set_ats_str(83, TXT_MARK_LOOK, 0, ATS_DATA);
_G(atds)->set_ats_str(84, TXT_MARK_LOOK, 0, ATS_DATA);
}
}
void Room11::put_card() {
if (isCurInventory(RED_CARD_INV) || isCurInventory(YEL_CARD_INV)) {
_G(gameState).R11IdCardNr = _G(cur)->getInventoryCursor();
delInventory(_G(gameState).R11IdCardNr);
_G(det)->startDetail(0, 255, ANI_FRONT);
_G(atds)->set_ats_str(83, TXT_MARK_LOOK, 1, ATS_DATA);
_G(atds)->set_ats_str(84, TXT_MARK_LOOK, 1, ATS_DATA);
_G(gameState).R11CardOk = true;
if (!_G(gameState).R11TerminalOk)
startAadWait(16);
}
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,47 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM11_H
#define CHEWY_ROOMS_ROOM11_H
namespace Chewy {
namespace Rooms {
class Room11 {
private:
static void bork_zwinkert();
static void chewy_bo_use();
public:
static void entry();
static bool timer(int16 t_nr, int16 ani_nr);
static void gedAction(int index);
static void get_card();
static void put_card();
static int16 scanner();
static void talk_debug();
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,286 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/ani_dat.h"
#include "chewy/room.h"
#include "chewy/rooms/room12.h"
namespace Chewy {
namespace Rooms {
#define R12_BORK_OBJ 0
static const int16 R12_BORK_PHASEN[4][2] = {
{ 74, 79 },
{ 80, 85 },
{ 62, 67 },
{ 68, 73 }
};
static const MovLine R12_BORK_MPKT[5] = {
{ { 207, 220, 199 }, 2, 6 },
{ { 207, 145, 199 }, 2, 6 },
{ { 30, 145, 199 }, 0, 6 },
{ { 207, 145, 199 }, 1, 6 },
{ { 207, 220, 199 }, 3, 6 }
};
static const MovLine R12_BORK_MPKT1[2] = {
{ { 207, 220, 199 }, 0, 6 },
{ { 170, 145, 199 }, 0, 6 }
};
static const MovLine R12_BORK_MPKT2[3] = {
{ { 170, 145, 199 }, 1, 8 },
{ { 180, 145, 120 }, 1, 8 },
{ { 300, 80, 120 }, 1, 8 }
};
static const AniBlock ABLOCK16[2] = {
{ 0, 1, ANI_FRONT, ANI_WAIT, 0 },
{ 1, 1, ANI_FRONT, ANI_WAIT, 0 },
};
void Room12::entry() {
_G(zoom_horizont) = 150;
_G(timer_nr)[1] = _G(room)->set_timer(254, 20);
if (!_G(gameState).R12Betreten) {
_G(gameState).R12Betreten = true;
hideCur();
for (int16 i = 7; i < 10; i++)
_G(det)->showStaticSpr(i);
_G(flags).NoScroll = true;
auto_scroll(60, 0);
flic_cut(FCUT_015);
_G(flags).NoScroll = false;
for (int16 i = 7; i < 10; i++)
_G(det)->hideStaticSpr(i);
_G(obj)->show_sib(SIB_TALISMAN_R12);
_G(obj)->calc_rsi_flip_flop(SIB_TALISMAN_R12);
_G(obj)->calc_all_static_detail();
autoMove(5, P_CHEWY);
start_spz(CH_TALK12, 255, false, 0);
startAadWait(109);
showCur();
} else if (_G(gameState).R12Talisman && !_G(gameState).R12BorkInRohr)
_G(timer_nr)[0] = _G(room)->set_timer(255, 20);
else if (_G(gameState).R12BorkInRohr && !_G(gameState).R12RaumOk)
_G(det)->showStaticSpr(12);
}
bool Room12::timer(int16 t_nr, int16 ani_nr) {
if (t_nr == _G(timer_nr)[0]) {
if (!is_chewy_busy())
init_bork();
} else if (t_nr == _G(timer_nr)[1] && _G(gameState).R12TransOn) {
_G(gameState).R12TransOn = false;
startAadWait(30);
}
return false;
}
void Room12::init_bork() {
if (!auto_obj_status(R12_BORK_OBJ) && !_G(gameState).R12BorkTalk) {
if (!_G(auto_obj))
_G(det)->load_taf_seq(62, 24, nullptr);
if (!_G(flags).AutoAniPlay && !_G(flags).ChAutoMov) {
_G(auto_obj) = 1;
_G(mov_phasen)[R12_BORK_OBJ].AtsText = 120;
_G(mov_phasen)[R12_BORK_OBJ].Lines = 5;
_G(mov_phasen)[R12_BORK_OBJ].Repeat = 1;
_G(mov_phasen)[R12_BORK_OBJ].ZoomFak = (int16)_G(room)->_roomInfo->_zoomFactor + 20;
_G(auto_mov_obj)[R12_BORK_OBJ].Id = AUTO_OBJ0;
_G(auto_mov_vector)[R12_BORK_OBJ].Delay = _G(gameState).DelaySpeed;
_G(auto_mov_obj)[R12_BORK_OBJ].Mode = true;
init_auto_obj(R12_BORK_OBJ, &R12_BORK_PHASEN[0][0], 5, (const MovLine *)R12_BORK_MPKT);
if (!_G(gameState).R12TalismanOk) {
hideCur();
_G(auto_mov_vector)[R12_BORK_OBJ]._delayCount = 1000;
autoMove(5, P_CHEWY);
_G(auto_mov_vector)[R12_BORK_OBJ]._delayCount = 0;
if (_G(gameState).R12BorkCount < 3) {
++_G(gameState).R12BorkCount;
_G(uhr)->resetTimer(_G(timer_nr)[0], 0);
waitShowScreen(10);
start_spz(CH_TALK3, 255, ANI_FRONT, P_CHEWY);
startAadWait(14);
}
wait_auto_obj(R12_BORK_OBJ);
showCur();
} else {
bork_ok();
}
}
_G(uhr)->resetTimer(_G(timer_nr)[0], 0);
}
}
void Room12::talk_bork() {
if (!_G(gameState).R12TalismanOk) {
startAadWait(28);
}
}
void Room12::bork_ok() {
hideCur();
_G(flags).MouseLeft = true;
_G(auto_mov_vector)[R12_BORK_OBJ]._delayCount = 1000;
autoMove(5, P_CHEWY);
_G(auto_mov_vector)[R12_BORK_OBJ]._delayCount = 0;
_G(gameState).R12BorkTalk = true;
_G(mov_phasen)[R12_BORK_OBJ].Repeat = 1;
_G(mov_phasen)[R12_BORK_OBJ].Lines = 2;
init_auto_obj(R12_BORK_OBJ, &R12_BORK_PHASEN[0][0], 2, (const MovLine *)R12_BORK_MPKT1);
wait_auto_obj(R12_BORK_OBJ);
_G(gameState).R12BorkInRohr = true;
_G(det)->setDetailPos(3, 170, 145);
_G(det)->startDetail(3, 255, ANI_FRONT);
startAadWait(57);
_G(det)->stopDetail(3);
_G(mov_phasen)[R12_BORK_OBJ].Repeat = 1;
_G(mov_phasen)[R12_BORK_OBJ].Lines = 3;
init_auto_obj(R12_BORK_OBJ, &R12_BORK_PHASEN[0][0], 3, (const MovLine *)R12_BORK_MPKT2);
wait_auto_obj(R12_BORK_OBJ);
_G(det)->hideStaticSpr(10);
startSetAILWait(4, 1, ANI_FRONT);
_G(talk_hide_static) = -1;
_G(det)->showStaticSpr(12);
_G(atds)->set_ats_str(118, TXT_MARK_LOOK, 2, ATS_DATA);
_G(obj)->calc_rsi_flip_flop(SIB_ROEHRE_R12);
_G(flags).MouseLeft = false;
showCur();
}
int16 Room12::use_terminal() {
int16 action_flag = false;
if (!_G(cur)->usingInventoryCursor()) {
action_flag = true;
if (!_G(gameState).R12ChewyBork) {
autoMove(6, P_CHEWY);
startAadWait(110);
if (_G(gameState).R12BorkInRohr && !_G(gameState).R12RaumOk) {
start_spz(CH_TALK5, 255, false, P_CHEWY);
startAadWait(112);
_G(flags).NoScroll = true;
auto_scroll(46, 0);
flic_cut(FCUT_016);
register_cutscene(5);
load_chewy_taf(CHEWY_BORK);
_G(flags).NoScroll = false;
_G(atds)->set_all_ats_str(118, 0, ATS_DATA);
_G(det)->hideStaticSpr(12);
_G(menu_item) = CUR_WALK;
cursorChoice(_G(menu_item));
setPersonPos(108, 90, P_CHEWY, -1);
_G(gameState).R12ChewyBork = true;
_G(gameState).R12RaumOk = true;
autoMove(4, P_CHEWY);
start_spz(68, 255, false, P_CHEWY);
startAadWait(113);
} else if (_G(gameState).R12TalismanOk && !_G(gameState).R12RaumOk) {
use_linke_rohr();
} else {
_G(gameState).R12TransOn = true;
_G(uhr)->resetTimer(_G(timer_nr)[1], 0);
}
} else {
start_aad(114, 0);
}
}
return action_flag;
}
void Room12::use_linke_rohr() {
_G(gameState).R12TalismanOk = false;
_G(gameState).R12ChainLeft = true;
_G(uhr)->disableTimer();
_G(obj)->calc_rsi_flip_flop(SIB_L_ROEHRE_R12);
_G(obj)->calc_rsi_flip_flop(SIB_ROEHRE_R12);
_G(obj)->calc_all_static_detail();
_G(atds)->set_ats_str(118, TXT_MARK_LOOK, 0, ATS_DATA);
_G(atds)->set_ats_str(117, TXT_MARK_LOOK, 1, ATS_DATA);
start_aad(111, 0);
}
int16 Room12::chewy_trans() {
int16 action_flag = false;
if (!_G(cur)->usingInventoryCursor() && _G(gameState).R12TransOn) {
action_flag = true;
_G(flags).AutoAniPlay = true;
autoMove(9, P_CHEWY);
_G(gameState)._personHide[P_CHEWY] = true;
startAniBlock(2, ABLOCK16);
setPersonPos(108, 82, P_CHEWY, P_RIGHT);
_G(gameState)._personHide[P_CHEWY] = false;
_G(gameState).R12TransOn = false;
_G(flags).AutoAniPlay = false;
}
return action_flag;
}
int16 Room12::useTransformerTube() {
bool result = false;
if (!_G(cur)->usingInventoryCursor()) {
result = true;
if (_G(gameState).R12ChainLeft) {
_G(gameState).R12ChainLeft = false;
_G(uhr)->enableTimer();
_G(atds)->set_ats_str(117, TXT_MARK_LOOK, 0, ATS_DATA);
} else {
autoMove(7, P_CHEWY);
startAadWait(29);
}
}
return result;
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,47 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM12_H
#define CHEWY_ROOMS_ROOM12_H
namespace Chewy {
namespace Rooms {
class Room12 {
private:
static void bork_ok();
static void init_bork();
public:
static void entry();
static bool timer(int16 t_nr, int16 ani_nr);
static void use_linke_rohr();
static int16 chewy_trans();
static int16 useTransformerTube();
static int16 use_terminal();
static void talk_bork();
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,249 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/ani_dat.h"
#include "chewy/room.h"
#include "chewy/rooms/room13.h"
namespace Chewy {
namespace Rooms {
#define R13_BORK_OBJ 0
static const int16 R13_BORK_PHASEN[4][2] = {
{ 92, 97 },
{ 86, 91 },
{ 86, 91 },
{ 68, 73 }
};
static const MovLine R13_BORK_MPKT[3] = {
{ { 168, 140, 162 }, 0, 6 },
{ { 50, 140, 162 }, 0, 6 },
{ { 50, 107, 130 }, 2, 6 }
};
void Room13::entry() {
if (!_G(gameState).R12ChewyBork && !_G(gameState).R13BorkOk) {
_G(out)->cls();
flic_cut(FCUT_012);
setPersonPos(106, 65, P_CHEWY, P_RIGHT);
switchRoom(11);
start_spz(CH_TALK12, 255, false, P_CHEWY);
startAadWait(27);
} else {
if (_G(gameState).R13MonitorStatus)
_G(det)->showStaticSpr(11 - _G(gameState).R13MonitorStatus);
if (!_G(gameState).R13BorkOk) {
_G(det)->showStaticSpr(12);
_G(obj)->hide_sib(SIB_BANDBUTTON_R13);
_G(gameState).R13Bandlauf = true;
_G(atds)->set_ats_str(94, TXT_MARK_LOOK, _G(gameState).R13Bandlauf, ATS_DATA); // conveyor belt
_G(atds)->set_ats_str(97, TXT_MARK_LOOK, _G(gameState).R13Bandlauf, ATS_DATA); // lever
_G(atds)->set_ats_str(93, TXT_MARK_LOOK, _G(gameState).R13Bandlauf, ATS_DATA); // monitor
} else {
_G(atds)->setControlBit(122, ATS_ACTIVE_BIT);
_G(atds)->delControlBit(92, ATS_ACTIVE_BIT);
_G(obj)->show_sib(SIB_BANDBUTTON_R13);
}
if (_G(gameState).R13Bandlauf) {
for (int i = 0; i < 5; ++i)
_G(det)->startDetail(i, 255, false);
}
if (!_G(flags).LoadGame && _G(gameState).R13Band) {
_G(gameState).room_e_obj[25].Attribut = EXIT_TOP;
_G(atds)->setControlBit(100, ATS_ACTIVE_BIT);
_G(gameState).R13Band = false;
}
if (_G(gameState).R21GarbageGrid)
_G(det)->hideStaticSpr(6);
}
}
void Room13::xit() {
_G(gameState).room_e_obj[25].Attribut = EXIT_TOP;
_G(atds)->setControlBit(100, ATS_ACTIVE_BIT);
_G(gameState).R13Band = false;
}
void Room13::gedAction(int index) {
if (index == 2 && _G(gameState).R12ChewyBork) {
stopPerson(P_CHEWY);
talk_bork();
}
}
void Room13::talk_bork() {
if (!_G(gameState).R13BorkOk) {
_G(gameState).R13BorkOk = true;
_G(gameState).R12ChewyBork = false;
_G(det)->showStaticSpr(13);
_G(det)->setDetailPos(10, _G(moveState)[P_CHEWY].Xypos[0], _G(moveState)[P_CHEWY].Xypos[1]);
_G(det)->setStaticPos(12, _G(moveState)[P_CHEWY].Xypos[0], _G(moveState)[P_CHEWY].Xypos[1], false, true);
_G(gameState)._personHide[P_CHEWY] = true;
startAadWait(33);
_G(det)->stopDetail(9);
_G(det)->load_taf_seq(86, 12, nullptr);
_G(gameState)._personHide[P_CHEWY] = false;
_G(det)->hideStaticSpr(12);
_G(auto_obj) = 1;
_G(mov_phasen)[R13_BORK_OBJ].AtsText = 122;
_G(mov_phasen)[R13_BORK_OBJ].Lines = 3;
_G(mov_phasen)[R13_BORK_OBJ].Repeat = 1;
_G(mov_phasen)[R13_BORK_OBJ].ZoomFak = 0;
_G(auto_mov_obj)[R13_BORK_OBJ].Id = AUTO_OBJ0;
_G(auto_mov_vector)[R13_BORK_OBJ].Delay = _G(gameState).DelaySpeed;
_G(auto_mov_obj)[R13_BORK_OBJ].Mode = true;
init_auto_obj(R13_BORK_OBJ, &R13_BORK_PHASEN[0][0], 3, (const MovLine *)R13_BORK_MPKT);
autoMove(9, P_CHEWY);
wait_auto_obj(R13_BORK_OBJ);
autoMove(11, P_CHEWY);
_G(flags).NoScroll = true;
auto_scroll(41, 0);
start_spz(68, 255, false, P_CHEWY);
startAadWait(248);
flic_cut(FCUT_013);
load_chewy_taf(CHEWY_NORMAL);
_G(auto_obj) = 0;
_G(flags).NoScroll = false;
_G(atds)->setControlBit(122, ATS_ACTIVE_BIT);
_G(atds)->delControlBit(92, ATS_ACTIVE_BIT);
_G(obj)->show_sib(SIB_BANDBUTTON_R13);
setPersonPos(153, 138, P_CHEWY, P_LEFT);
startAadWait(34);
startAadWait(249);
_G(obj)->show_sib(SIB_TBUTTON1_R11);
_G(obj)->show_sib(SIB_SCHLITZ_R11);
_G(obj)->show_sib(SIB_TBUTTON2_R11);
_G(obj)->show_sib(SIB_TBUTTON3_R11);
if (_G(gameState).R6DoorRightB)
_G(gameState).room_e_obj[20].Attribut = EXIT_LEFT;
_G(gameState).room_e_obj[21].Attribut = EXIT_TOP;
}
}
void Room13::jmp_band() {
if (!_G(gameState).R13Band && !_G(gameState).R12ChewyBork) {
if (!_G(gameState).R13Bandlauf) {
_G(obj)->hide_sib(SIB_BANDBUTTON_R13);
_G(gameState).room_e_obj[25].Attribut = 255;
_G(atds)->delControlBit(100, ATS_ACTIVE_BIT);
_G(gameState).R13Band = true;
autoMove(3, P_CHEWY);
_G(gameState)._personHide[P_CHEWY] = true;
startSetAILWait(8, 1, ANI_FRONT);
_G(gameState)._personHide[P_CHEWY] = false;
setPersonPos(292, 98, P_CHEWY, P_RIGHT);
} else {
_G(gameState).R13Surf = true;
_G(mouseLeftClick) = false;
autoMove(12, P_CHEWY);
startAadWait(117);
_G(flags).NoScroll = true;
auto_scroll(76, 0);
flic_cut(FCUT_014);
_G(flags).NoScroll = false;
setPersonPos(195, 226, P_CHEWY, P_LEFT);
_G(gameState).R13Bandlauf = false;
_G(atds)->set_ats_str(94, TXT_MARK_LOOK, _G(gameState).R13Bandlauf, ATS_DATA); // conveyor belt
_G(atds)->set_ats_str(97, TXT_MARK_LOOK, _G(gameState).R13Bandlauf, ATS_DATA); // lever
_G(atds)->set_ats_str(93, TXT_MARK_LOOK, _G(gameState).R13Bandlauf, ATS_DATA); // monitor
_G(obj)->calc_rsi_flip_flop(SIB_BANDBUTTON_R13);
_G(obj)->hide_sib(SIB_BANDBUTTON_R13);
switchRoom(14);
flic_cut(FCUT_017);
register_cutscene(6);
_G(gameState).scrollx = 92;
_G(gameState).scrolly = 120;
_G(gameState)._personHide[P_CHEWY] = true;
waitShowScreen(20);
_G(gameState)._personHide[P_CHEWY] = false;
}
}
}
void Room13::jmp_floor() {
if (_G(gameState).R13Band) {
if (!_G(gameState).R13Surf)
_G(obj)->show_sib(SIB_BANDBUTTON_R13);
_G(gameState).room_e_obj[25].Attribut = EXIT_TOP;
_G(atds)->setControlBit(100, ATS_ACTIVE_BIT);
_G(gameState).R13Band = false;
autoMove(5, P_CHEWY);
_G(gameState)._personHide[P_CHEWY] = true;
startSetAILWait(7, 1, ANI_FRONT);
_G(gameState)._personHide[P_CHEWY] = false;
setPersonPos(176, 138, P_CHEWY, P_LEFT);
}
}
int16 Room13::monitor_button() {
int16 action_flag = false;
if (!_G(cur)->usingInventoryCursor()) {
if (_G(gameState).R13Band) {
action_flag = true;
startAadWait(620);
} else if (!_G(gameState).R12ChewyBork) {
action_flag = true;
autoMove(8, P_CHEWY);
_G(gameState)._personHide[P_CHEWY] = true;
startSetAILWait(6, 1, ANI_FRONT);
_G(gameState)._personHide[P_CHEWY] = false;
if (_G(gameState).R13MonitorStatus)
_G(det)->hideStaticSpr(11 - _G(gameState).R13MonitorStatus);
++_G(gameState).R13MonitorStatus;
if (_G(gameState).R13MonitorStatus > 4)
_G(gameState).R13MonitorStatus = 0;
else
_G(det)->showStaticSpr(11 - _G(gameState).R13MonitorStatus);
_G(atds)->set_ats_str(96, TXT_MARK_LOOK, _G(gameState).R13MonitorStatus, ATS_DATA);
}
}
return action_flag;
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,43 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM13_H
#define CHEWY_ROOMS_ROOM13_H
namespace Chewy {
namespace Rooms {
class Room13 {
public:
static void entry();
static void xit();
static void gedAction(int index);
static int16 monitor_button();
static void jmp_band();
static void jmp_floor();
static void talk_bork();
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,198 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/room.h"
#include "chewy/rooms/room14.h"
#include "chewy/rooms/room23.h"
namespace Chewy {
namespace Rooms {
void Room14::entry() {
_G(gameState).R23GliderExit = 14;
_G(zoom_horizont) = 310;
_G(gameState).ScrollxStep = 2;
if (!_G(gameState).R14Feuer)
_G(obj)->hide_sib(46);
if (!_G(flags).LoadGame) {
if (_G(gameState).R14GleiterAuf) {
setPersonPos(381, 264, P_CHEWY, P_LEFT);
_G(det)->showStaticSpr(6);
_G(gameState).scrollx = 160;
_G(gameState).scrolly = 120;
} else {
_G(gameState).scrollx = 92;
_G(gameState).scrolly = 17;
}
}
}
bool Room14::timer(int16 t_nr, int16 ani_nr) {
if (ani_nr)
eremit_feuer(t_nr, ani_nr);
return false;
}
void Room14::eremit_feuer(int16 t_nr, int16 ani_nr) {
if (!_G(flags).AutoAniPlay && !_G(gameState).R14Feuer) {
_G(flags).AutoAniPlay = true;
_G(det)->hideStaticSpr(9);
startSetAILWait(_G(room)->_roomTimer._objNr[ani_nr], 1, ANI_FRONT);
_G(uhr)->resetTimer(t_nr, 0);
_G(det)->showStaticSpr(9);
_G(det)->startDetail(7, 1, ANI_FRONT);
_G(flags).AutoAniPlay = false;
}
}
int16 Room14::use_schrott() {
int16 action_flag = false;
if (!_G(cur)->usingInventoryCursor()) {
autoMove(3, P_CHEWY);
_G(gameState)._personHide[P_CHEWY] = true;
startSetAILWait(12, 1, ANI_FRONT);
_G(gameState)._personHide[P_CHEWY] = false;
if (!_G(gameState).R14Waffe) {
action_flag = true;
_G(gameState).R14Waffe = true;
startAadWait(21);
invent_2_slot(BWAFFE_INV);
}
}
return action_flag;
}
int16 Room14::use_gleiter() {
int16 action_flag = false;
if (!_G(cur)->usingInventoryCursor()) {
action_flag = true;
autoMove(4, P_CHEWY);
if (!_G(gameState).R14GleiterAuf) {
_G(gameState).R14GleiterAuf = true;
_G(gameState)._personHide[P_CHEWY] = true;
startSetAILWait(10, 1, ANI_FRONT);
_G(gameState)._personHide[P_CHEWY] = false;
_G(det)->showStaticSpr(6);
_G(atds)->set_ats_str(107, TXT_MARK_LOOK, 1, ATS_DATA);
} else {
_G(gameState).R23GliderExit = 14;
Room23::cockpit();
}
}
return action_flag;
}
void Room14::talk_eremit() {
if (!_G(gameState).R14Feuer) {
autoMove(6, P_CHEWY);
_G(flags).AutoAniPlay = true;
if (_G(gameState).R14Translator) {
loadDialogCloseup(0);
_G(obj)->show_sib(46);
} else {
hideCur();
startAadWait(24);
showCur();
_G(flags).AutoAniPlay = false;
}
}
}
int16 Room14::use_schleim() {
int16 action_flag = false;
if (!_G(cur)->usingInventoryCursor()) {
autoMove(2, P_CHEWY);
_G(gameState)._personHide[P_CHEWY] = true;
startSetAILWait(11, 1, ANI_FRONT);
_G(gameState)._personHide[P_CHEWY] = false;
if (!_G(gameState).R14Sicherung) {
action_flag = true;
_G(gameState).R14Sicherung = true;
startAadWait(22);
invent_2_slot(SICHERUNG_INV);
}
}
return action_flag;
}
void Room14::feuer() {
int16 waffe = false;
int16 tmp = _G(cur)->getInventoryCursor();
_G(gameState).R14Feuer = true;
_G(flags).AutoAniPlay = true;
hideCur();
if (isCurInventory(BWAFFE_INV)) {
autoMove(5, P_CHEWY);
waffe = true;
_G(gameState)._personHide[P_CHEWY] = true;
startDetailFrame(8, 1, ANI_FRONT, 11);
startSetAILWait(9, 1, ANI_FRONT);
waitDetail(8);
_G(gameState)._personHide[P_CHEWY] = false;
} else {
autoMove(7, P_CHEWY);
_G(det)->hideStaticSpr(9);
startDetailFrame(2, 1, ANI_FRONT, 9);
_G(gameState)._personHide[P_CHEWY] = true;
startSetAILWait(13, 1, ANI_FRONT);
_G(gameState)._personHide[P_CHEWY] = false;
waitDetail(2);
startSetAILWait(5, 1, ANI_FRONT);
_G(det)->showStaticSpr(9);
}
delInventory(tmp);
_G(det)->startDetail(6, 255, ANI_FRONT);
waitShowScreen(40);
if (waffe)
autoMove(7, P_CHEWY);
startAadWait(26);
_G(det)->hideStaticSpr(9);
startSetAILWait(3, 1, ANI_FRONT);
_G(det)->showStaticSpr(9);
invent_2_slot(FLUXO_INV);
_G(atds)->set_ats_str(105, TXT_MARK_LOOK, 1, ATS_DATA);
_G(gameState).R14FluxoFlex = true;
_G(flags).AutoAniPlay = false;
showCur();
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,46 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM14_H
#define CHEWY_ROOMS_ROOM14_H
namespace Chewy {
namespace Rooms {
class Room14 {
private:
static void eremit_feuer(int16 t_nr, int16 ani_nr);
public:
static void entry();
static bool timer(int16 t_nr, int16 ani_nr);
static void feuer();
static int16 use_schrott();
static int16 use_gleiter();
static int16 use_schleim();
static void talk_eremit();
};
} // namespace Rooms
} // namespace Chewy
#endif

View File

@@ -0,0 +1,61 @@
/* 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/>.
*
*/
#include "chewy/cursor.h"
#include "chewy/defines.h"
#include "chewy/events.h"
#include "chewy/globals.h"
#include "chewy/room.h"
#include "chewy/rooms/room16.h"
#include "chewy/rooms/room23.h"
namespace Chewy {
namespace Rooms {
void Room16::entry() {
_G(zoom_horizont) = 140;
if (!_G(gameState).R16F5Exit) {
_G(det)->showStaticSpr(4);
_G(gameState).room_e_obj[32].Attribut = 255;
_G(atds)->delControlBit(124, ATS_ACTIVE_BIT);
} else {
_G(det)->hideStaticSpr(4);
_G(gameState).room_e_obj[32].Attribut = EXIT_LEFT;
_G(atds)->setControlBit(124, ATS_ACTIVE_BIT);
}
}
int16 Room16::use_gleiter() {
int16 action_flag = false;
if (!_G(cur)->usingInventoryCursor()) {
action_flag = true;
autoMove(6, P_CHEWY);
_G(gameState).R23GliderExit = 16;
Room23::cockpit();
}
return action_flag;
}
} // namespace Rooms
} // namespace Chewy

View File

@@ -0,0 +1,37 @@
/* 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/>.
*
*/
#ifndef CHEWY_ROOMS_ROOM16_H
#define CHEWY_ROOMS_ROOM16_H
namespace Chewy {
namespace Rooms {
class Room16 {
public:
static void entry();
static int16 use_gleiter();
};
} // namespace Rooms
} // namespace Chewy
#endif

Some files were not shown because too many files have changed in this diff Show More