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/chamber/POTFILES Normal file
View File

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

329
engines/chamber/anim.cpp Normal file
View File

@@ -0,0 +1,329 @@
/* 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 "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/resdata.h"
#include "chamber/cga.h"
#include "chamber/room.h"
#include "chamber/sound.h"
namespace Chamber {
byte *anima_end_ofs;
byte last_anim_y = 0;
byte last_anim_x = 0;
byte anim_shift_y = 0;
byte anim_shift_x = 0;
byte last_anim_height;
byte last_anim_width;
byte anim_cycle;
byte anim_flags;
byte anim_use_dot_effect;
uint16 anim_draw_delay;
byte dot_effect_step;
uint16 dot_effect_delay;
extern uint16 cpu_speed_delay;
extern void loadLutinSprite(uint16 lutidx);
void getScratchBuffer(byte mode) {
byte *buffer = scratch_mem2;
uint16 offs = 0;
if (mode & 0x80)
offs += 3200;
if (mode & 0x40)
offs += 1600;
lutin_mem = buffer + offs;
}
void animLoadSprite(byte **panim) {
byte mode;
byte index;
mode = *((*panim)++);
index = *((*panim)++);
getScratchBuffer(mode);
loadLutinSprite(index);
}
void clipSprite(byte *x, byte *y, byte *sprw, byte *sprh, byte **sprite, int8 dx, int8 dy) {
if (anim_flags == 7)
return;
if (anim_flags & 4) {
if (anim_cycle == 0)
return;
if (anim_flags & 2) {
*sprh = anim_cycle;
if (anim_cycle >= dy)
anim_cycle -= dy;
else
anim_cycle = 0;
} else if (anim_flags & 1) {
*sprw = anim_cycle;
anim_cycle--;
} else {
*x -= dx;
*sprite += (*sprw - anim_cycle) * 2;
*sprw = anim_cycle;
anim_cycle--;
}
} else if (anim_flags & 2) {
if (*sprw == anim_cycle) {
anim_cycle = 0;
} else if (anim_flags & 1) {
*sprw = anim_cycle;
anim_cycle++;
} else {
*x -= dx;
*sprite += (*sprw - anim_cycle) * 2;
*sprw = anim_cycle;
anim_cycle++;
}
}
}
void copyScreenBlockWithDotEffect(byte *source, byte x, byte y, byte width, byte height, byte *target) {
uint16 offs;
uint16 xx = x * 4;
uint16 ww = width * 4;
uint16 cur_image_end = ww * height;
for (offs = 0; offs != cur_image_end;) {
byte mask = 0xC0 >> (((xx + offs % ww) % 4) * 2);
uint16 ofs = cga_CalcXY(xx + offs % ww, y + offs / ww);
target[ofs] = (target[ofs] & ~mask) | (source[ofs] & mask);
if (dot_effect_delay / 4 != 0) {
uint16 i;
for (i = 0; i < dot_effect_delay / 4; i++) ; /*TODO: weak delay*/
}
offs += dot_effect_step;
if (offs > cur_image_end)
offs -= cur_image_end;
}
}
void animDrawSprite(byte x, byte y, byte sprw, byte sprh, byte *pixels, uint16 pitch) {
uint16 delay;
byte ex, ey, updx, updy, updw, updh;
uint16 ofs = CalcXY_p(x, y);
cga_BackupImage(backbuffer, ofs, sprw, sprh, sprit_load_buffer);
cga_BlitSprite(pixels, pitch, sprw, sprh, backbuffer, ofs);
ex = x + sprw;
ey = y + sprh;
if (last_anim_height != 0) {
if (last_anim_x + last_anim_width > ex)
ex = last_anim_x + last_anim_width;
if (last_anim_y + last_anim_height > ey)
ey = last_anim_y + last_anim_height;
updx = (x > last_anim_x) ? last_anim_x : x;
updy = (y > last_anim_y) ? last_anim_y : y;
} else {
updx = x;
updy = y;
}
updw = ex - updx;
updh = ey - updy;
ofs = CalcXY_p(updx, updy);
/*TODO looks like here was some code before*/
for (delay = 0; delay < anim_draw_delay; delay++) {
g_system->delayMillis(1000 / 16 / 25);
}
waitVBlank();
if (anim_use_dot_effect)
copyScreenBlockWithDotEffect(backbuffer, updx, updy, updw, updh, frontbuffer);
else {
cga_CopyScreenBlock(backbuffer, updw, updh, frontbuffer, ofs);
}
cga_RestoreImage(sprit_load_buffer, backbuffer);
last_anim_x = x;
last_anim_y = y;
last_anim_width = sprw;
last_anim_height = sprh;
anim_shift_x = anim_shift_y = 0;
}
void animUndrawSprite(void) {
cga_CopyScreenBlock(backbuffer, last_anim_width, last_anim_height, CGA_SCREENBUFFER, CalcXY_p(last_anim_x, last_anim_y));
last_anim_height = 0;
}
void playAnimCore(byte **panim) {
byte mode;
uint16 count, count2;
byte *pframe;
mode = *((*panim)++);
anim_flags = mode & 7;
count = mode >> 3;
while (count--) {
pframe = *panim;
mode = *pframe++;
anim_draw_delay = ((mode & ~7) >> 3) << 1;
dot_effect_step = (mode & ~7) >> 3;
dot_effect_delay = 500;
count2 = mode & 7;
while (count2--) {
byte *sprite;
byte sprw, sprh;
byte x, y;
int8 dx, dy;
uint16 pitch;
mode = *pframe++;
getScratchBuffer(mode);
dy = mode & 7;
dx = (mode >> 3) & 7;
dx = (dx & 1) ? -(dx & ~1) : dx;
dx /= 2;
dy = (dy & 1) ? -(dy & ~1) : dy;
x = last_anim_x + dx + anim_shift_x;
y = last_anim_y + dy + anim_shift_y;
sprite = lutin_mem;
sprw = *sprite++;
sprh = *sprite++;
pitch = sprw * 2;
clipSprite(&x, &y, &sprw, &sprh, &sprite, dx, dy);
animDrawSprite(x, y, sprw, sprh, sprite, pitch);
if (anim_flags & 4) {
if (anim_cycle == 0) {
animUndrawSprite();
goto end;
}
} else if (anim_flags & 2) {
if (anim_cycle == 0) {
goto end;
}
}
}
}
end:
;
mode = *((*panim)++);
*panim += mode & 7;
}
void anim1(byte **panim) {
anim_cycle = 0xFF;
anim_use_dot_effect = 0;
playAnimCore(panim);
}
void anim2(byte **panim) {
anim_cycle = 1;
anim_use_dot_effect = 0;
playAnimCore(panim);
}
void anim3(byte **panim) {
anim_cycle = 1;
anim_use_dot_effect = 0;
playAnimCore(panim);
}
void anim4(byte **panim) {
anim_cycle = last_anim_width - 1;
anim_use_dot_effect = 0;
playAnimCore(panim);
}
void anim5(byte **panim) {
anim_cycle = last_anim_width - 1;
anim_use_dot_effect = 0;
playAnimCore(panim);
}
void anim6(byte **panim) {
anim_cycle = last_anim_height;
anim_use_dot_effect = 0;
playAnimCore(panim);
}
void anim7(byte **panim) {
anim_cycle = 0xFF;
anim_use_dot_effect = 1;
playAnimCore(panim);
}
typedef void (*animhandler_t)(byte **panim);
animhandler_t anim_handlers[] = {
animLoadSprite,
anim1,
anim2,
anim3,
anim4,
anim5,
anim6,
anim7
};
void playAnim(byte index, byte x, byte y) {
byte sound;
byte *panim;
last_anim_width = 0;
last_anim_height = 0;
last_anim_x = x;
last_anim_y = y;
panim = seekToEntry(anima_data, index - 1, &anima_end_ofs);
while (panim != anima_end_ofs) {
byte mode = *panim;
switch (mode) {
case 0xFE: /*set shift*/
panim++;
anim_shift_x = *panim++;
anim_shift_y = *panim++;
break;
case 0xFD: /*play sfx*/
panim++;
sound = *panim++;
panim++; /*unused*/
playSound(sound);
break;
case 0xFC: /*nothing*/
panim++;
break;
default:
anim_handlers[mode & 7](&panim);
}
}
}
} // End of namespace Chamber

35
engines/chamber/anim.h Normal file
View File

@@ -0,0 +1,35 @@
/* 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 CHAMBER_ANIM_H
#define CHAMBER_ANIM_H
namespace Chamber {
void playAnim(byte index, byte x, byte y);
void copyScreenBlockWithDotEffect(byte *source, byte x, byte y, byte width, byte height, byte *target);
extern byte dot_effect_step;
extern uint16 dot_effect_delay;
} // End of namespace Chamber
#endif

View File

@@ -0,0 +1,30 @@
/* 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 "chamber/chamber.h"
namespace Chamber {
byte backbuffer[0xB800]; ///< CGA: 0x4000, HGS: 0xB800
} // End of namespace Chamber

1640
engines/chamber/cga.cpp Normal file

File diff suppressed because it is too large Load Diff

166
engines/chamber/cga.h Normal file
View File

@@ -0,0 +1,166 @@
/* 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 CHAMBER_cga_H
#define CHAMBER_cga_H
namespace Chamber {
// HGA Constants
#define HGA_WIDTH 720
#define HGA_HEIGHT 348
#define HGA_BASE_SEG 0xB000
#define HGA_PAGE2_SEG 0xB800
#define HGA_NEXT_LINES_OFS 0x2000
#define HGA_BITS_PER_PIXEL 1
#define HGA_PIXELS_PER_BYTE (8 / HGA_BITS_PER_PIXEL)
#define HGA_BYTES_PER_LINE (HGA_WIDTH / HGA_PIXELS_PER_BYTE)
#define HGA_CALCXY_RAW(x, y) ( ((y) % 4) * HGA_NEXT_LINES_OFS + ((y) / 4) * HGA_BYTES_PER_LINE + (x) / HGA_PIXELS_PER_BYTE )
#define HGA_CENTERED_BASE_OFS HGA_CALCXY_RAW(-76, 8)
#ifdef __386__
#define HGA_SCREENBUFFER ((byte*)(HGA_BASE_SEG * 16))
#define HGA_BACKBUFFER ((byte*)(HGA_PAGE2_SEG * 16))
#else
#if 0
#define HGA_SCREENBUFFER ((byte*)MK_FP(HGA_BASE_SEG, 0))
#define HGA_BACKBUFFER ((byte*)MK_FP(HGA_PAGE2_SEG, 0))
#define HGA_FONT_HEIGHT 6
#define frontbuffer HGA_SCREENBUFFER
#define backbuffer HGA_BACKBUFFER
#endif
#endif
// CGA Constants
#define CGA_WIDTH 320
#define CGA_HEIGHT 200
#define CGA_BASE_SEG 0xB800
#define CGA_ODD_LINES_OFS 0x2000
#define CGA_BITS_PER_PIXEL 2
#define CGA_PIXELS_PER_BYTE (8 / CGA_BITS_PER_PIXEL)
#define CGA_BYTES_PER_LINE (CGA_WIDTH / CGA_PIXELS_PER_BYTE)
extern byte CGA_SCREENBUFFER[0xB800];
#define CGA_FONT_HEIGHT 6
#define CGA_NEXT_LINE(offs) ((CGA_ODD_LINES_OFS ^ (offs)) + (((offs) & CGA_ODD_LINES_OFS) ? 0 : CGA_BYTES_PER_LINE))
#define CGA_PREV_LINE(offs) ((CGA_ODD_LINES_OFS ^ (offs)) - (((offs) & CGA_ODD_LINES_OFS) ? CGA_BYTES_PER_LINE : 0))
#define frontbuffer CGA_SCREENBUFFER
extern byte backbuffer[0xB800]; ///< CGA: 0x4000, HGS: 0xB800
extern byte sprit_load_buffer[1290];
extern byte cga_pixel_flip[256];
extern byte char_draw_coords_x;
extern byte char_draw_coords_y;
extern byte *char_xlat_table;
extern byte string_ended;
extern byte char_draw_max_width;
extern byte char_draw_max_height;
void switchToGraphicsMode(void);
void switchToTextMode(void);
void waitVBlank(void);
void cga_blitToScreen(int16 dx, int16 dy, int16 w, int16 h);
void cga_blitToScreen(int16 ofs, int16 w, int16 h);
void cga_ColorSelect(byte csel);
void cga_BackBufferToRealFull(void);
void cga_RealBufferToBackFull(void);
void cga_SwapRealBackBuffer(void);
void cga_SwapScreenRect(byte *pixels, uint16 w, uint16 h, byte *screen, uint16 ofs);
uint16 CalcXY(uint16 x, uint16 y);
uint16 CalcXY_p(uint16 x, uint16 y);
uint16 HGA_CalcXY(uint16 x, uint16 y);
uint16 HGA_CalcXY_p(uint16 x, uint16 y);
uint16 cga_CalcXY(uint16 x, uint16 y);
uint16 cga_CalcXY_p(uint16 x, uint16 y);
void cga_CopyScreenBlock(byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
byte *cga_BackupImage(byte *source, uint16 ofs, uint16 w, uint16 h, byte *buffer);
byte *cga_BackupImageReal(uint16 ofs, uint16 w, uint16 h);
void cga_RestoreImage(byte *buffer, byte *target);
void cga_RefreshImageData(byte *buffer);
void cga_RestoreBackupImage(byte *target);
void cga_Blit(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
void cga_BlitAndWait(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
void cga_FillAndWait(byte pixel, uint16 w, uint16 h, byte *screen, uint16 ofs);
void cga_DrawVLine(uint16 x, uint16 y, uint16 l, byte color, byte *target);
void cga_DrawHLine(uint16 x, uint16 y, uint16 l, byte color, byte *target);
uint16 cga_DrawHLineWithEnds(uint16 bmask, uint16 bpix, byte color, uint16 l, byte *target, uint16 ofs);
void cga_PrintChar(byte c, byte *target);
void cga_BlitScratchBackSprite(uint16 sprofs, uint16 w, uint16 h, byte *screen, uint16 ofs);
void cga_BlitFromBackBuffer(byte w, byte h, byte *screen, uint16 ofs);
void cga_BlitSprite(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
void cga_BlitSpriteFlip(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
void cga_BlitSpriteBak(byte *pixels, int16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs, byte *backup, byte mask);
void drawSprite(byte *sprite, byte *screen, uint16 ofs);
void drawSpriteFlip(byte *sprite, byte *screen, uint16 ofs);
void drawSpriteN(byte index, uint16 x, uint16 y, byte *target);
void drawSpriteNFlip(byte index, uint16 x, uint16 y, byte *target);
void backupAndShowSprite(byte index, byte x, byte y);
byte *loadSprite(byte index, byte *bank, byte *buffer, byte header_only);
byte *loadSprit(byte index);
byte *loadPersSprit(byte index);
void cga_AnimLiftToUp(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 x, uint16 y);
void cga_AnimLiftToDown(byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
void cga_AnimLiftToLeft(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
void cga_AnimLiftToRight(uint16 n, byte *pixels, uint16 pw, uint16 w, uint16 h, byte *screen, uint16 ofs);
void cga_HideScreenBlockLiftToUp(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
void cga_HideScreenBlockLiftToDown(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
void cga_HideScreenBlockLiftToLeft(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
void cga_HideScreenBlockLiftToRight(uint16 n, byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
void cga_HideShatterFall(byte *screen, byte *source, uint16 w, uint16 h, byte *target, uint16 ofs);
void cga_TraceLine(uint16 sx, uint16 ex, uint16 sy, uint16 ey, byte *source, byte *target);
void cga_ZoomImage(byte *pixels, byte w, byte h, byte nw, byte nh, byte *target, uint16 ofs);
void cga_AnimZoomIn(byte *pixels, byte w, byte h, byte *target, uint16 ofs);
void cga_ZoomInplaceXY(byte *pixels, byte w, byte h, byte nw, byte nh, uint16 x, uint16 y, byte *target);
} // End of namespace Chamber
#endif

View File

@@ -0,0 +1,93 @@
/* 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/scummsys.h"
#include "common/config-manager.h"
#include "common/debug.h"
#include "common/error.h"
#include "common/events.h"
#include "common/file.h"
#include "common/fs.h"
#include "common/system.h"
#include "engines/util.h"
#include "chamber/chamber.h"
namespace Chamber {
ChamberEngine *g_vm;
ChamberEngine::ChamberEngine(OSystem *syst, const ADGameDescription *desc)
: Engine(syst) {
g_vm = this;
_gameDescription = desc;
const Common::FSNode gameDataDir(ConfMan.getPath("path"));
// Don't forget to register your random source
_rnd = new Common::RandomSource("chamber");
_shouldQuit = false;
_shouldRestart = false;
_prioritycommand_1 = false;
_prioritycommand_2 = false;
_pxiData = NULL;
_videoMode = Common::kRenderCGA;
_screenH = _screenW = _screenBits = _screenBPL = _screenPPB = 0;
_line_offset = _line_offset2 = _fontHeight = _fontWidth = 0;
}
ChamberEngine::~ChamberEngine() {
// Dispose your resources here
delete _rnd;
delete[] _pxiData;
deinitSound();
}
bool ChamberEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsReturnToLauncher) ||
(f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime);
}
Common::Error ChamberEngine::loadGameStream(Common::SeekableReadStream *stream) {
Common::Serializer s(stream, nullptr);
syncGameStream(s);
return Common::kNoError;
}
Common::Error ChamberEngine::saveGameStream(Common::WriteStream *stream, bool isAutosave) {
Common::Serializer s(nullptr, stream);
syncGameStream(s);
return Common::kNoError;
}
void ChamberEngine::syncGameStream(Common::Serializer &s) {
// Use methods of Serializer to save/load fields
int16 dummy = 0;
s.syncAsUint16LE(dummy);
}
} // End of namespace Chamber

108
engines/chamber/chamber.h Normal file
View File

@@ -0,0 +1,108 @@
/* 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 CHAMBER_H
#define CHAMBER_H
#define RUNCOMMAND_RESTART 1337
#include "common/random.h"
#include "common/serializer.h"
#include "common/rendermode.h"
#include "engines/engine.h"
#include "gui/debugger.h"
namespace Audio {
class SoundHandle;
class PCSpeaker;
}
struct ADGameDescription;
namespace Chamber {
enum CHAMBERActions {
kActionNone,
kActionInteract,
kActionQuit,
kActionYes,
kActionNo,
};
class ChamberEngine : public Engine {
private:
// We need random numbers
Common::RandomSource *_rnd;
public:
ChamberEngine(OSystem *syst, const ADGameDescription *desc);
~ChamberEngine();
Common::Language getLanguage() const;
Common::Error run() override;
Common::Error init();
Common::Error execute();
bool hasFeature(EngineFeature f) const override;
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
void syncGameStream(Common::Serializer &s);
byte readKeyboardChar();
void initSound();
void deinitSound();
public:
bool _shouldQuit;
bool _shouldRestart;
bool _prioritycommand_1;
bool _prioritycommand_2;
Common::RenderMode _videoMode;
byte *_pxiData;
uint16 _screenW; ///< Screen Width
uint16 _screenH; ///< Screen Height
uint8 _screenBits; ///< Bits per pixel
uint16 _line_offset; ///< Memory offset of blanks
uint16 _line_offset2; ///< Memory offset of blanks
uint8 _screenPPB; ///< Pixels per byte
uint16 _screenBPL; ///< Bytes per line
uint8 _fontHeight; ///< Font height
uint8 _fontWidth; ///< Font height
Audio::PCSpeaker *_speaker;
private:
const ADGameDescription *_gameDescription;
};
void init(void);
extern ChamberEngine *g_vm;
} // End of namespace Chamber
#endif

97
engines/chamber/common.h Normal file
View File

@@ -0,0 +1,97 @@
/* 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 CHAMBER_COMMON_H
#define CHAMBER_COMMON_H
namespace Chamber {
#define BE(x) ((((x) >> 8) | ((x) << 8)) & 0xffff)
#define LE16(x) (x)
#define TODO(s) \
{ \
warning("%s", s); \
promptWait(); \
for(;;) ; \
}
#include "common/pack-start.h"
typedef struct rect_t {
byte sx;
byte ex;
byte sy;
byte ey;
} rect_t;
#include "common/pack-end.h"
#if 0
#define DEBUG_ENDING
#endif
#if 0
#define DEBUG
#endif
#if 0
/*0 - play intro*/
/*0xFF - skip intro, quest item and teleport*/
/*other - skip intro, play quest item seq, teleport to room*/
#define DEBUG_SKIP_INTRO 0xFF
#endif
#if 1
#define DEBUG_ZONE
#endif
#if 0
/*Rope -> De Profundis*/
#define DEBUG_QUEST 0x00
#endif
#if 0
/*Knife -> The Wall*/
#define DEBUG_QUEST 0x40
#endif
#if 0
/*Goblet -> The Twins*/
#define DEBUG_QUEST 0x80
#endif
#if 0
/*Fly -> Scorpion's*/
#define DEBUG_QUEST 0xC0
#endif
#if 0
/*win in fights*/
#define CHEAT
#endif
#if 0
/*never lose to the Skull Trader*/
#define CHEAT_TRADER
#endif
} // End of namespace Chamber
#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 chamber "Chamber" no

View File

@@ -0,0 +1,4 @@
begin_section("Chamber");
add_person("Retro-Junk;", "bambarbee", "");
add_person("Eugene Sandulenko", "sev", "");
end_section();

125
engines/chamber/cursor.cpp Normal file
View File

@@ -0,0 +1,125 @@
/* 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 "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/cursor.h"
#include "chamber/resdata.h"
#include "chamber/cga.h"
namespace Chamber {
byte cursor_color = 0;
byte *cursor_shape = NULL;
byte cursor_anim_ticks;
byte cursor_anim_phase;
/*cursors hotspot offsets*/
uint16 cursor_shifts[CURSOR_MAX][2] = {
{ 0, 0 },
{ 7, 7 },
{ 7, 7 },
{ 0, 0 },
{ 7, 7 },
{ 0, 15 },
{ 7, 7 },
{ 7, 7 },
{ 7, 7 }
};
uint16 cursor_x_shift;
byte cursor_y_shift;
uint16 cursor_x;
byte cursor_y;
byte cursor_backup[CURSOR_WIDTH_SPR * CURSOR_HEIGHT / CGA_BITS_PER_PIXEL];
uint16 last_cursor_draw_ofs = 0;
uint16 cursor_draw_ofs;
byte cursorImage[CURSOR_WIDTH * CURSOR_HEIGHT];
/*
Select cursor shape and its hotspot
*/
void selectCursor(uint16 num) {
cursor_x_shift = cursor_shifts[num][0];
cursor_y_shift = cursor_shifts[num][1];
cursor_shape = souri_data + num * CURSOR_WIDTH * CURSOR_HEIGHT * 2 / g_vm->_screenPPB;
byte *src = cursor_shape;
byte *dst = cursorImage;
for (int16 y = 0; y < CURSOR_HEIGHT; y++) {
for (int16 x = 0; x < CURSOR_HEIGHT / 4; x++) {
byte colors = *src;
byte masks = *(src++ + CURSOR_HEIGHT * CURSOR_WIDTH / 4);
for (int16 c = 0; c < 4; c++) {
byte color = (colors & 0xC0) >> 6;
byte mask = (masks & 0xC0) >> 6;
colors <<= 2;
masks <<= 2;
if (!mask)
*dst++ = color;
else {
*dst++ = 255;
}
}
}
}
g_system->setMouseCursor(cursorImage, CURSOR_WIDTH, CURSOR_HEIGHT, cursor_x_shift, cursor_y_shift, 255);
g_system->showMouse(true);
}
/*
Build cursor sprite for its current pixel-grained position
*/
void updateCursor(void) {
}
/*
Draw cursor sprite and backup background pixels
*/
void drawCursor(byte *target) {
g_system->updateScreen();
}
/*
Restore background pixels under cursor
*/
void undrawCursor(byte *target) {
}
/*
Restore pixels under cursor and update cursor sprite
*/
void updateUndrawCursor(byte *target) {
/*TODO: does this call order makes any sense?*/
updateCursor();
undrawCursor(target);
}
} // End of namespace Chamber

59
engines/chamber/cursor.h Normal file
View File

@@ -0,0 +1,59 @@
/* 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 CHAMBER_CURSOR_H
#define CHAMBER_CURSOR_H
namespace Chamber {
#define CURSOR_WIDTH 16
#define CURSOR_HEIGHT 16
#define CURSOR_WIDTH_SPR 20
enum Cursors {
CURSOR_FINGER,
CURSOR_TARGET,
CURSOR_FLY,
CURSOR_SNAKE,
CURSOR_GRAB,
CURSOR_POUR,
CURSOR_BODY,
CURSOR_ARROWS,
CURSOR_CROSSHAIR,
CURSOR_MAX
};
extern uint16 cursor_x;
extern byte cursor_y;
extern byte cursor_color;
extern byte *cursor_shape;
extern byte cursor_anim_ticks;
extern byte cursor_anim_phase;
void selectCursor(uint16 num);
void updateCursor(void);
void drawCursor(byte *target);
void undrawCursor(byte *target);
void updateUndrawCursor(byte *target);
} // End of namespace Chamber
#endif

119
engines/chamber/decompr.cpp Normal file
View File

@@ -0,0 +1,119 @@
/* 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 "chamber/chamber.h"
namespace Chamber {
static struct {
byte codes[256];
byte prefix[256];
byte suffix[256];
byte coddict[256];
byte codlink[256];
byte stackpos;
} DecompCtx;
byte decode_string(byte code, byte prev_n, byte *stack) {
byte n;
while ((n = DecompCtx.coddict[code]) != 0) {
while (n >= prev_n) {
n = DecompCtx.codlink[n];
if (n == 0)
return code;
}
/*if(DecompCtx.stackpos == 255) exit("stack exploded");*/
stack[DecompCtx.stackpos++] = prev_n = n;
code = DecompCtx.prefix[n];
}
return code;
}
uint32 decompress(byte *data, byte *result) {
byte dict_size, more;
uint16 compsize;
uint16 i;
byte code, n, suffix;
byte stack[256];
uint32 decompsize = 0;
do {
dict_size = *data++;
more = *data++;
compsize = *data++;
compsize |= (*data++) << 8;
if (dict_size == 0) {
/* uncompressed block */
decompsize += compsize;
while (compsize--)
*result++ = *data++;
} else {
/* compressed block */
/*
memcpy(DecompCtx.codes + 1, data, dict_size); data += dict_size;
memcpy(DecompCtx.prefix + 1, data, dict_size); data += dict_size;
memcpy(DecompCtx.suffix + 1, data, dict_size); data += dict_size;
*/
for (n = 1, i = 0; i < dict_size; n++, i++) DecompCtx.codes[n] = *data++;
for (n = 1, i = 0; i < dict_size; n++, i++) DecompCtx.prefix[n] = *data++;
for (n = 1, i = 0; i < dict_size; n++, i++) DecompCtx.suffix[n] = *data++;
memset(DecompCtx.coddict, 0, 256);
for (n = 1, i = 0; i < dict_size; n++, i++) {
code = DecompCtx.codes[n];
DecompCtx.codlink[n] = DecompCtx.coddict[code];
DecompCtx.coddict[code] = n;
}
while (compsize-- > 0) {
code = *data++;
if (DecompCtx.coddict[code] == 0) {
/* literal */
*result++ = code;
decompsize += 1;
} else {
/* string */
DecompCtx.stackpos = 0;
n = DecompCtx.coddict[code];
stack[DecompCtx.stackpos++] = n;
for (code = DecompCtx.prefix[n];; code = DecompCtx.suffix[n]) {
suffix = decode_string(code, n, stack);
*result++ = suffix;
decompsize += 1;
if (DecompCtx.stackpos == 0)
break;
n = stack[--DecompCtx.stackpos];
}
}
}
}
} while (more != 0);
return decompsize;
}
} // End of namespace Chamber

30
engines/chamber/decompr.h Normal file
View File

@@ -0,0 +1,30 @@
/* 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 CHAMBER_DECOMPR_H
#define CHAMBER_DECOMPR_H
namespace Chamber {
uint32 decompress(byte *data, byte *result);
} // End of namespace Chamber
#endif

View File

@@ -0,0 +1,75 @@
/* 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"
namespace Chamber {
static const PlainGameDescriptor ChamberGames[] = {
{"chamber", "Chamber of the Sci-Mutant Priestess"},
{ 0, 0 }
};
static const ADGameDescription gameDescriptions[] = {
{
"chamber",
"",
AD_ENTRY1s("ere.pxi", "5aa5bd2d79eefde70675b0b6734944f2", 134358),
Common::UNK_LANG, // EN/FR/DE
Common::kPlatformDOS,
ADGF_UNSTABLE,
GUIO0()
},
{
"chamber",
"",
AD_ENTRY1s("kult1.pxi", "fc0bd31a3c380338f76ff53e421e47b6", 140537),
Common::EN_USA,
Common::kPlatformDOS,
ADGF_UNSTABLE,
GUIO0()
},
AD_TABLE_END_MARKER
};
} // End of namespace Chamber
class ChamberMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
public:
ChamberMetaEngineDetection() : AdvancedMetaEngineDetection(Chamber::gameDescriptions, Chamber::ChamberGames) {
}
const char *getName() const override {
return "chamber";
}
const char *getEngineName() const override {
return "chamber";
}
const char *getOriginalCopyright() const override {
return "Chamber (C) 1989 ERE Informatique";
}
};
REGISTER_PLUGIN_STATIC(CHAMBER_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, ChamberMetaEngineDetection);

252
engines/chamber/dialog.cpp Normal file
View File

@@ -0,0 +1,252 @@
/* 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 "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/dialog.h"
#include "chamber/print.h"
#include "chamber/cga.h"
#include "chamber/script.h"
#include "chamber/cursor.h"
#include "chamber/input.h"
namespace Chamber {
uint16 cur_str_index;
uint16 cur_dlg_index;
dirty_rect_t dirty_rects[MAX_DIRTY_RECT];
dirty_rect_t *last_dirty_rect = dirty_rects;
void addDirtyRect(byte kind, byte x, byte y, byte w, byte h, uint16 offs) {
int16 i;
dirty_rect_t *r = dirty_rects;
for (i = 0; i < MAX_DIRTY_RECT; i++, r++) /*TODO: may go oob*/
if (r->kind == DirtyRectFree)
break;
r->kind = kind;
r->offs = offs;
r->width = w;
r->height = h;
r->y = y;
r->x = x;
script_byte_vars.dirty_rect_kind = dirty_rects[0].kind;
last_dirty_rect = r;
}
void getDirtyRect(int16 index, byte *kind, byte *x, byte *y, byte *w, byte *h, uint16 *offs, byte newkind) {
*kind = dirty_rects[index].kind;
*offs = dirty_rects[index].offs;
*w = dirty_rects[index].width;
*h = dirty_rects[index].height;
*y = dirty_rects[index].y;
*x = dirty_rects[index].x;
dirty_rects[index].kind = newkind;
script_byte_vars.dirty_rect_kind = dirty_rects[0].kind;
}
void getDirtyRectAndFree(int16 index, byte *kind, byte *x, byte *y, byte *w, byte *h, uint16 *offs) {
getDirtyRect(index - 1, kind, x, y, w, h, offs, DirtyRectFree);
}
void getDirtyRectAndSetSprite(int16 index, byte *kind, byte *x, byte *y, byte *w, byte *h, uint16 *offs) {
getDirtyRect(index - 1, kind, x, y, w, h, offs, DirtyRectSprite);
}
int16 findDirtyRectAndFree(byte kind, byte *x, byte *y, byte *w, byte *h, uint16 *offs) {
int16 i;
for (i = 0; i < MAX_DIRTY_RECT; i++) {
if (dirty_rects[i].kind == kind) {
getDirtyRect(i, &kind, x, y, w, h, offs, DirtyRectFree);
return 1;
}
}
return 0;
}
/*Restore screen data from back buffer as specified by dirty rects of kind*/
void popDirtyRects(byte kind) {
byte x, y;
byte width, height;
uint16 offs;
while (findDirtyRectAndFree(kind, &x, &y, &width, &height, &offs)) {
cga_CopyScreenBlock(backbuffer, width, height, frontbuffer, offs);
if (kind == DirtyRectBubble) {
/*pop bubble's spike*/
cga_CopyScreenBlock(backbuffer, 2, 21, frontbuffer, offs = (x << 8) | y);
}
}
}
void desciTextBox(uint16 x, uint16 y, uint16 width, byte *msg) {
draw_x = x;
draw_y = y;
char_draw_max_width = width;
cga_DrawTextBox(msg, frontbuffer);
addDirtyRect(DirtyRectText, draw_x, draw_y, char_draw_max_width + 2, char_draw_coords_y - draw_y + 8, CalcXY_p(draw_x, draw_y));
}
/*Draw dialog bubble with text and spike*/
void drawPersonBubble(byte x, byte y, byte flags, byte *msg) {
uint16 ofs;
byte w, h;
uint16 ww, nw;
char_draw_max_width = flags & 0x1F;
char_xlat_table = chars_color_bonw;
if (g_vm->getLanguage() == Common::EN_USA) {
calcStringSize(msg, &ww, &nw);
if (ww >= char_draw_max_width)
char_draw_max_width = ww;
}
/*upper border*/
ofs = CalcXY_p(x, y);
ofs = cga_DrawHLineWithEnds(0xF00F, 0, 0, char_draw_max_width, CGA_SCREENBUFFER, ofs);
ofs = cga_DrawHLineWithEnds(0xC003, 0x0FF0, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
ofs = cga_DrawHLineWithEnds(0, 0x3FFC, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
ofs = cga_DrawHLineWithEnds(0, 0x3FFC, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
/*body*/
char_draw_coords_x = x;
char_draw_coords_y = y + 4;
for (string_ended = 0; !string_ended; char_draw_coords_y += 6) {
cga_PrintChar(0x3B, CGA_SCREENBUFFER);
msg = printStringPadded(msg, CGA_SCREENBUFFER);
cga_PrintChar(0x3C, CGA_SCREENBUFFER);
char_draw_coords_x = x;
}
ofs = CalcXY_p(x, char_draw_coords_y);
ofs = cga_DrawHLineWithEnds(0xC003, 0x0FF0, 0xFF, char_draw_max_width, CGA_SCREENBUFFER, ofs);
ofs = cga_DrawHLineWithEnds(0xF00F, 0, 0, char_draw_max_width, CGA_SCREENBUFFER, ofs);
w = char_draw_max_width + 2;
h = char_draw_coords_y - y + 2;
/*draw spike*/
switch (flags & SPIKE_MASK) {
case SPIKE_UPLEFT: /*upper-left spike*/
ofs = CalcXY_p(x + 1, y - 7);
drawSpriteN(18, x + 1, y - 7, CGA_SCREENBUFFER);
break;
case SPIKE_UPRIGHT: /*upper-right spike*/
ofs = CalcXY_p(x + char_draw_max_width, y - 7) - 1;
drawSpriteNFlip(18, x + char_draw_max_width, y - 7, CGA_SCREENBUFFER);
break;
case SPIKE_DNRIGHT: /*lower-right spike*/
ofs = CalcXY_p(x + char_draw_max_width, char_draw_coords_y + 1) - 1;
drawSpriteNFlip(21, x + char_draw_max_width, char_draw_coords_y + 1, CGA_SCREENBUFFER);
break;
case SPIKE_DNLEFT: /*lower-left spike*/
ofs = CalcXY_p(x + 1, char_draw_coords_y + 1);
drawSpriteN(21, x + 1, char_draw_coords_y + 1, CGA_SCREENBUFFER);
break;
case SPIKE_BUBRIGHT: /*lower-right bubbles*/
ofs = CalcXY_p(x + char_draw_max_width, char_draw_coords_y + 4);
drawSpriteN(20, x + char_draw_max_width, char_draw_coords_y + 4, CGA_SCREENBUFFER);
break;
case SPIKE_BUBLEFT: /*lower-left bubbles*/
ofs = CalcXY_p(x + 1, char_draw_coords_y + 4);
drawSpriteN(19, x + 1, char_draw_coords_y + 4, CGA_SCREENBUFFER);
break;
}
addDirtyRect(DirtyRectBubble, ofs >> 8, ofs & 255, w, h, CalcXY_p(x, y));
}
void showPromptAnim(void) {
if (script_byte_vars.zone_index == 135)
return;
waitVBlank();
drawSpriteN(cursor_anim_phase ? 23 : 22, 300 / 4, 155, frontbuffer);
cursor_anim_phase = ~cursor_anim_phase;
}
void promptWait(void) {
cursor_anim_phase = 0;
do {
byte ticks = script_byte_vars.timer_ticks;
if ((ticks % 8) == 0 && ticks != cursor_anim_ticks) {
cursor_anim_ticks = ticks;
showPromptAnim();
}
pollInputButtonsOnly();
if (g_vm->_shouldQuit)
break;
g_system->updateScreen();
g_system->delayMillis(10);
} while (!buttons);
if (cursor_anim_phase)
showPromptAnim();
}
/*
Get string with index num from strings bank
*/
byte *seekToString(byte *bank, uint16 num) {
byte len;
byte *p = bank;
cur_str_index = num;
num -= 4;
while (num--) {
len = *p;
p += len;
}
len = *p;
cur_str_end = p + len;
return p + 1;
}
/*
Get string with index num from strings bank, with large string index support for scripts
*/
byte *seekToStringScr(byte *bank, uint16 num, byte **ptr) {
byte len;
byte *p = bank;
if (num < 4) {
num = (num << 8) | *(++(*ptr));
}
cur_str_index = num;
num -= 4;
while (num--) {
len = *p;
p += len;
}
len = *p;
cur_str_end = p + len;
return p + 1;
}
} // End of namespace Chamber

74
engines/chamber/dialog.h Normal file
View File

@@ -0,0 +1,74 @@
/* 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 CHAMBER_DIALOG_H
#define CHAMBER_DIALOG_H
namespace Chamber {
extern uint16 cur_str_index;
extern uint16 cur_dlg_index;
enum DirtyRectKind {
DirtyRectFree = 0,
DirtyRectBubble = 1, /*bubble with spike*/
DirtyRectSprite = 2, /*portrait*/
DirtyRectText = 3 /*text bubble w/o spike*/
};
typedef struct dirty_rect_t {
byte kind;
uint16 offs;
byte height;
byte width;
byte y; /*for DirtyRectBubble this is spike offs*/
byte x;
} dirty_rect_t;
#define MAX_DIRTY_RECT 10
extern dirty_rect_t dirty_rects[];
extern dirty_rect_t *last_dirty_rect;
#define SPIKE_MASK 0xE0
#define SPIKE_UPLEFT 0
#define SPIKE_UPRIGHT 0x20
#define SPIKE_DNRIGHT 0x80
#define SPIKE_DNLEFT 0xA0
#define SPIKE_BUBBLES 0x40
#define SPIKE_BUBRIGHT 0xC0
#define SPIKE_BUBLEFT 0xE0
void addDirtyRect(byte kind, byte x, byte y, byte w, byte h, uint16 offs);
void getDirtyRectAndFree(int16 index, byte *kind, byte *x, byte *y, byte *w, byte *h, uint16 *offs);
void getDirtyRectAndSetSprite(int16 index, byte *kind, byte *x, byte *y, byte *w, byte *h, uint16 *offs);
void popDirtyRects(byte kind);
void drawPersonBubble(byte x, byte y, byte flags, byte *msg);
void desciTextBox(uint16 x, uint16 y, uint16 width, byte *msg);
void promptWait(void);
byte *seekToString(byte *bank, uint16 num);
byte *seekToStringScr(byte *bank, uint16 num, byte **ptr);
} // End of namespace Chamber
#endif

240
engines/chamber/enums.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 CHAMBER_ENUMS_H
#define CHAMBER_ENUMS_H
namespace Chamber {
/*game items, mirrors inventory_items (except kItemNone)*/
enum Items {
kItemNone = 0,
kItemSkull1 = 1,
kItemSkull2 = 2,
kItemSkull3 = 3,
kItemSkull4 = 4,
kItemSkull5 = 5,
kItemRope1 = 6,
kItemRope2 = 7,
kItemRope3 = 8,
kItemRope4 = 9,
kItemRope5 = 10,
kItemFly1 = 11,
kItemFly2 = 12,
kItemFly3 = 13,
kItemFly4 = 14,
kItemGoblet1 = 15,
kItemGoblet2 = 16,
kItemGoblet3 = 17,
kItemGoblet4 = 18,
kItemDagger1 = 19,
kItemDagger2 = 20,
kItemDagger3 = 21,
kItemDagger4 = 22,
kItemLantern1 = 23,
kItemLantern2 = 24,
kItemLantern3 = 25,
kItemLantern4 = 26,
kItemBlueSpider1 = 27,
kItemBlueSpider2 = 28,
kItemBlueSpider3 = 29,
kItemBlueSpider4 = 30,
kItemRedSpider1 = 31,
kItemRedSpider2 = 32,
kItemRedSpider3 = 33,
kItemRedSpider4 = 34,
kItemDie1 = 35,
kItemDie2 = 36,
kItemDie3 = 37,
kItemDie4 = 38,
kItemZapstik1 = 39,
kItemZapstik2 = 40,
kItemZapstik3 = 41,
kItemZapstik4 = 42,
kItemZapstik5 = 43,
kItemZapstik6 = 44,
kItemZapstik7 = 45,
kItemZapstik8 = 46,
kItemZapstik9 = 47,
kItemZapstik10 = 48,
kItemZapstik11 = 49,
kItemZapstik12 = 50,
kItemZapstik13 = 51,
kItemZapstik14 = 52,
kItemMask = 53,
kItemWhistle = 54,
kItemEgg1 = 55,
kItemBlade = 56,
kItemChopper = 57,
kItemZorq = 58,
kItemSaura = 59,
kItemFlask = 60,
kItemBean = 61,
kItemEgg2 = 62,
kItemEgg3 = 63
};
/*game persons, mirrors pers_list*/
enum Persons {
kPersVort = 0,
kPersAspirant1 = 1,
kPersAspirant2 = 2,
kPersAspirant3 = 3,
kPersAspirant4 = 4,
kPersTurkey = 5,
kPersPriestess1 = 6,
kPersPriestess2 = 7,
kPersMaster = 8,
kPersProtozorq1 = 9,
kPersProtozorq2 = 10,
kPersProtozorq3 = 11,
kPersProtozorq4 = 12,
kPersProtozorq5 = 13,
kPersProtozorq6 = 14,
kPersProtozorq7 = 15,
kPersProtozorq8 = 16,
kPersProtozorq9 = 17,
kPersProtozorq10 = 18,
kPersProtozorq11 = 19,
kPersProtozorq12 = 20,
kPersProtozorq13 = 21,
kPersProtozorq14 = 22,
kPersPoormouth = 23,
kPersKhele = 24,
kPersMistress = 25,
kPersDeilos = 26,
kPersScifi = 27,
kPersNormajeen = 28,
kPersAsh = 29,
kPersMonkey = 30,
kPersHarssk = 31,
kPersZorq = 32,
kPersQriich = 33,
kPersVort2 = 34,
kPersVort3 = 35,
kPersPriestess3 = 36,
kPersPriestess4 = 37,
kPersCadaver = 38,
kPersTurkey1 = 39,
kPersTurkey2 = 40
};
#define PersonOffset(p) ((p) * 5)
enum Areas {
kAreaNone = 0,
kAreaTheMastersEye = 1,
kAreaTheMastersOrbit1 = 2,
kAreaTheMastersOrbit2 = 3,
kAreaTheMastersOrbit3 = 5,
kAreaTheReturn = 8,
kAreaTheRing1 = 10,
kAreaTheRing2 = 12,
kAreaTheRing3 = 14,
kAreaTheRing4 = 16,
kAreaTheRing5 = 18,
kAreaTheRing6 = 20,
kAreaDeProfundis = 22,
kAreaTheWall = 24,
kAreaTheInfidelsTomb1 = 25,
kAreaTheInfidelsTomb2 = 26,
kAreaVictoryOfTheFaith1 = 25,
kAreaVictoryOfTheFaith2 = 26,
kAreaDeadEnd = 29,
kAreaTheWall2 = 30,
kAreaTheInfidelsTomb3 = 31,
kAreaTheInfidelsTomb4 = 32,
kAreaVictoryOfTheFaith3 = 31,
kAreaVictoryOfTheFaith4 = 32,
kAreaDeadEnd2 = 35,
kAreaTheNoose = 36,
kAreaTheSource = 37,
kAreaTheTwins = 38,
kAreaWhoWillBeSaved = 39,
kAreaInTheScorpionsPresence = 40,
kAreaTheWeb = 41,
kAreaPassage1 = 44,
kAreaPassage2 = 46,
kAreaPassage3 = 48,
kAreaThePowersOfTheAbyss = 50,
kAreaTheConcourse = 51,
kAreaPassage4 = 52,
kAreaPassage5 = 54,
kAreaDreamsOfSlime = 55,
kAreaGuardRoom = 56,
kAreaAHiddenPlace = 57,
kAreaAnteChamber = 58,
kAreaPlacatingThePowers = 59,
kAreaInThePresenceOfGod = 60,
kAreaBirthOfADivineRace = 61,
kAreaSaurasRepose = 62,
kAreaTheThresholdOfTruth = 63,
kAreaTheScriptures = 63,
kAreaRefectory = 65,
kAreaPassage6 = 66,
kAreaPassage7 = 68,
kAreaAblutions = 70,
kAreaCell1 = 71,
kAreaCell2 = 72,
kAreaCell3 = 73,
kAreaCell4 = 74,
kAreaUpwardGallery = 75,
kAreaGallery1 = 75,
kAreaCavern = 77,
kAreaGallery2 = 78,
kAreaGallery3 = 79,
kAreaGallery4 = 82,
kAreaDownwardGallery = 83,
kAreaGallery5 = 83,
kAreaGallery6 = 85,
kAreaPinkGallery1 = 87,
kAreaGallery7 = 88,
kAreaPinkGallery2 = 90,
kAreaPinkGallery3 = 91,
kAreaTube = 93,
kAreaUnderwater = 94,
kAreaObscurity = 101
};
} // End of namespace Chamber
#endif

93
engines/chamber/ifgm.cpp Normal file
View File

@@ -0,0 +1,93 @@
/* 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 "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/ifgm.h"
#include "chamber/dialog.h"
#include "chamber/sound.h"
namespace Chamber {
byte ifgm_loaded = 0;
byte ifgm_flag2;
void IFGM_Init(void) {
if (g_vm->getLanguage() == Common::EN_USA) {
/*TODO*/
} else {
ifgm_loaded = 0;
}
}
void IFGM_Shutdown(void) {
}
void IFGM_Poll(void) {
if(!ifgm_loaded)
return;
/*
xor ax, ax
int 0F0h
*/
}
/*
Load and play a sound sample.
Return 0 if playback is unavailable
*/
int16 IFGM_PlaySound(byte index) {
if (!ifgm_loaded)
return 0;
/*TODO*/
return 0;
}
void IFGM_PlaySample(byte index) {
if (!ifgm_loaded)
return;
IFGM_PlaySound(index);
}
void IFGM_StopSample(void) {
if (!ifgm_loaded)
return;
}
static byte sfx_sounds[] = {
0, 5, 10, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
void IFGM_PlaySfx(byte index) {
if (!ifgm_loaded)
return;
if (cur_dlg_index == 0)
return;
playSound(sfx_sounds[index % 16]);
}
} // end of namespace Chamber

46
engines/chamber/ifgm.h Normal file
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 CHAMBER_IFGM_H
#define CHAMBER_IFGM_H
namespace Chamber {
extern byte ifgm_loaded;
extern uint16 ifgm_flag1;
extern byte ifgm_flag2;
void IFGM_Init(void);
void IFGM_Shutdown(void);
void IFGM_Poll(void);
void IFGM_PlaySample(byte index);
void IFGM_StopSample(void);
int16 IFGM_PlaySound(byte index);
void IFGM_PlaySfx(byte index);
} // end of namespace Chamber
#endif

317
engines/chamber/input.cpp Normal file
View File

@@ -0,0 +1,317 @@
/* 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/events.h"
#include "common/system.h"
#include "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/dialog.h"
#include "chamber/input.h"
#include "chamber/cursor.h"
#include "chamber/print.h"
#include "chamber/resdata.h"
#include "chamber/cga.h"
#include "chamber/timer.h"
#include "chamber/ifgm.h"
#include "backends/keymapper/keymapper.h"
namespace Chamber {
byte have_mouse = 0;
byte have_joystick = 0;
byte key_held;
volatile byte key_direction;
volatile byte key_code;
volatile byte keyboard_scan;
volatile byte keyboard_specials;
volatile byte keyboard_arrows;
volatile byte keyboard_buttons;
byte buttons_repeat = 0;
byte buttons;
byte right_button;
byte key_direction_old;
byte accel_countdown;
uint16 acceleration = 1;
byte mouseButtons = 0;
void pollDiscrete(void);
byte ChamberEngine::readKeyboardChar() {
Common::Event event;
Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
keymapper->disableAllGameKeymaps();
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
while (true) {
while (g_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_KEYDOWN:
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
keymapper->getKeymap("chamber-default")->setEnabled(true);
keymapper->getKeymap("game-shortcuts")->setEnabled(true);
return event.kbd.ascii;
case Common::EVENT_RETURN_TO_LAUNCHER:
case Common::EVENT_QUIT:
_shouldQuit = true;
return 0;
default:
break;
}
g_system->updateScreen();
g_system->delayMillis(10);
}
}
}
void clearKeyboard(void) {
}
void setInputButtons(byte keys) {
if (keys & 2)
right_button = 0xff;
if (keys & 1)
right_button = 0;
buttons = keys;
buttons_repeat = keys;
}
byte pollMouse(void) {
pollInput();
return buttons;
}
byte pollKeyboard(void) {
byte direction = key_direction;
if (direction && direction == key_direction_old) {
if (++accel_countdown == 10) {
acceleration++;
accel_countdown = 0;
}
} else {
acceleration = 1;
accel_countdown = 0;
}
key_direction_old = direction;
if (direction & 0x0F) {
if (direction == 1) {
cursor_x += acceleration;
if (cursor_x >= 304) /*TODO: >*/
cursor_x = 304;
} else {
cursor_x -= acceleration;
if ((int16)cursor_x < 0)
cursor_x = 0;
}
}
if (direction & 0xF0) {
if (direction == 0x10) {
cursor_y += acceleration;
if (cursor_y >= 184) /*TODO: >*/
cursor_y = 184;
} else {
cursor_y -= acceleration;
if ((int8)cursor_y < 0)
cursor_y = 0;
}
}
return key_code;
}
/*
Show game exit confirmation dialog and get user's input
*/
int16 askQuitGame(void) {
/*EU version comes without requited text string*/
if (g_vm->getLanguage() != Common::EN_USA)
return 0;
int16 quit = -1;
byte *msg = seekToString(desci_data, 411); /*DO YOU WANT TO QUIT ? (Y OR N).*/
char_draw_max_width = 32;
draw_x = 1;
draw_y = 188;
cga_DrawTextBox(msg, frontbuffer);
Common::Event event;
Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
keymapper->getKeymap("chamber-default")->setEnabled(false);
keymapper->getKeymap("game-shortcuts")->setEnabled(false);
keymapper->getKeymap("quit-dialog")->setEnabled(true);
while (quit == -1) {
while (g_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
if (event.customType == kActionYes)
quit = 1;
else if (event.customType == kActionNo)
quit = 0;
break;
case Common::EVENT_RETURN_TO_LAUNCHER:
case Common::EVENT_QUIT:
quit = 1;
break;
default:
break;
}
}
}
cga_CopyScreenBlock(backbuffer, char_draw_max_width + 2, char_draw_coords_y - draw_y + 8, frontbuffer, CalcXY_p(draw_x, draw_y));
keymapper->getKeymap("quit-dialog")->setEnabled(false);
keymapper->getKeymap("chamber-default")->setEnabled(true);
keymapper->getKeymap("game-shortcuts")->setEnabled(true);
return quit;
}
void pollInputButtonsOnly() {
pollInput();
}
void pollInput(void) {
Common::Event event;
while (g_system->getEventManager()->pollEvent(event)) {
switch (event.type) {
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
if (event.customType == kActionInteract)
mouseButtons |= 1;
else if (event.customType == kActionQuit) {
if (g_vm->getLanguage() == Common::EN_USA) {
if (askQuitGame() != 0)
g_vm->_shouldQuit = true;
}
}
break;
case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
if (event.customType == kActionInteract)
mouseButtons &= ~1;
break;
case Common::EVENT_RETURN_TO_LAUNCHER:
case Common::EVENT_QUIT:
g_vm->_shouldQuit = true;
break;
case Common::EVENT_MOUSEMOVE:
cursor_x = event.mouse.x;
cursor_y = event.mouse.y;
break;
case Common::EVENT_LBUTTONDOWN:
mouseButtons |= 1;
break;
case Common::EVENT_LBUTTONUP:
mouseButtons &= ~1;
break;
case Common::EVENT_RBUTTONDOWN:
mouseButtons |= 2;
break;
case Common::EVENT_RBUTTONUP:
mouseButtons &= ~2;
break;
default:
break;
}
}
setInputButtons(mouseButtons);
}
void processInput(void) {
pollInput();
updateCursor();
drawCursor(frontbuffer);
}
void keyboardIsr() {
warning("STUB: KeyboardIsr()");
#if 0
byte scan, strobe;
scan = inportb(0x60);
/*consume scan from kbd. controller*/
strobe = inportb(0x61);
outportb(0x61, strobe | 0x80);
outportb(0x61, strobe);
if (scan == 1) { /*esc*/
esc_pressed = ~0;
} else {
if (scan & 0x80) { /*key release?*/
key_code = 0;
key_direction = 0;
} else {
switch (scan) {
case 0x39: /*space*/
key_code = scan;
key_direction = 0;
break;
case 0x48: /*up*/
key_code = 0;
key_direction = 0xF0;
break;
case 0x50: /*down*/
key_code = 0;
key_direction = 0x10;
break;
case 0x4B: /*left*/
key_code = 0;
key_direction = 0x0F;
break;
case 0x4D: /*right*/
key_code = 0;
key_direction = 0x01;
break;
}
}
}
outportb(0x20, 0x20);
#endif
}
void initInput(void) {
have_mouse = 1;
}
void uninitInput(void) {
}
} // End of namespace Chamber

54
engines/chamber/input.h Normal file
View File

@@ -0,0 +1,54 @@
/* 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 CHAMBER_INPUT_H
#define CHAMBER_INPUT_H
namespace Chamber {
extern byte buttons;
extern byte right_button;
extern byte have_mouse;
extern volatile byte key_direction;
extern volatile byte key_code;
extern byte key_held;
byte readKeyboardChar(void);
void clearKeyboard(void);
byte getKeyScan(void);
byte pollMouse(uint16 *curs_x, uint8 *curs_y);
byte pollKeyboard(void);
void setInputButtons(byte keys);
void pollInput(void);
void processInput(void);
void pollInputButtonsOnly(void);
void resetInput(void);
void initInput(void);
void uninitInput(void);
} // End of namespace Chamber
#endif

141
engines/chamber/invent.cpp Normal file
View File

@@ -0,0 +1,141 @@
/* 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 "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/invent.h"
#include "chamber/script.h"
#include "chamber/cga.h"
#include "chamber/cursor.h"
#include "chamber/input.h"
#include "chamber/sound.h"
namespace Chamber {
/*inventory box cells*/
#define INVENTORY_SPOTS_MAX (4 * 4)
struct {
byte sx;
byte ex;
byte sy;
byte ey;
byte name;
byte unkn5;
uint16 command;
byte itemidx;
byte unkn9;
} inventory_spots[] = {
{58, 62, 56, 72, 0, 0, 0, 0, 0},
{62, 66, 56, 72, 0, 0, 0, 0, 0},
{66, 70, 56, 72, 0, 0, 0, 0, 0},
{70, 74, 56, 72, 0, 0, 0, 0, 0},
{58, 62, 72, 88, 0, 0, 0, 0, 0},
{62, 66, 72, 88, 0, 0, 0, 0, 0},
{66, 70, 72, 88, 0, 0, 0, 0, 0},
{70, 74, 72, 88, 0, 0, 0, 0, 0},
{58, 62, 88, 104, 0, 0, 0, 0, 0},
{62, 66, 88, 104, 0, 0, 0, 0, 0},
{66, 70, 88, 104, 0, 0, 0, 0, 0},
{70, 74, 88, 104, 0, 0, 0, 0, 0},
{58, 62, 104, 120, 0, 0, 0, 0, 0},
{62, 66, 104, 120, 0, 0, 0, 0, 0},
{66, 70, 104, 120, 0, 0, 0, 0, 0},
{70, 74, 104, 120, 0, 0, 0, 0, 0}
};
byte inv_count = 0; /*TODO: pass this as param?*/
byte inv_bgcolor = 0; /*TODO: pass this as param?*/
/*
Filter items and put them inventory box, then draw it if non-empty
filtermask/filtervalue specify area (in high 8 bits) and flags (in lower 8 bits)
*/
void drawInventoryBox(uint16 filtermask, uint16 filtervalue) {
int16 i;
byte count = 0;
for (i = 0; i < MAX_INV_ITEMS; i++) {
uint16 flags = (inventory_items[i].area << 8) | inventory_items[i].flags;
if ((flags & filtermask) != filtervalue)
continue;
if (count == 0) {
/*once first valid item found, draw the box*/
cga_FillAndWait(inv_bgcolor, 64 / 4, 64, CGA_SCREENBUFFER, CalcXY_p(232 / 4, 56));
playSound(20);
}
inventory_spots[count].name = inventory_items[i].name;
inventory_spots[count].command = inventory_items[i].command;
inventory_spots[count].itemidx = i + 1;
drawSpriteN(inventory_items[i].sprite, inventory_spots[count].sx, inventory_spots[count].sy, CGA_SCREENBUFFER);
count++;
}
inv_count = count;
}
void checkInventoryItemHover(byte count) {
int16 i;
for (i = 0; i < count; i++) {
if (isCursorInRect((rect_t *)&inventory_spots[i])) {
the_command = inventory_spots[i].command;
command_hint = inventory_spots[i].name;
cursor_color = 0xAA;
script_byte_vars.inv_item_index = inventory_spots[i].itemidx;
script_vars[kScrPool3_CurrentItem] = &inventory_items[script_byte_vars.inv_item_index - 1];
return;
}
}
/*nothing found*/
command_hint = 100;
cursor_color = 0xFF;
the_command = 0;
}
void openInventory(uint16 filtermask, uint16 filtervalue) {
the_command = 0;
cga_BackupImageReal(CalcXY_p(232 / 4, 56), 64 / 4, 64);
drawInventoryBox(filtermask, filtervalue);
if (inv_count != 0) {
selectCursor(CURSOR_FINGER);
processInput();
do {
pollInput();
checkInventoryItemHover(inv_count);
if (command_hint != last_command_hint)
drawCommandHint();
drawHintsAndCursor(frontbuffer);
} while (buttons == 0);
undrawCursor(frontbuffer);
}
cga_RestoreImage(scratch_mem2, frontbuffer);
playSound(20);
switch (((item_t *)script_vars[kScrPool3_CurrentItem])->name) {
case 108: /*DAGGER*/
case 115: /*SACRIFICIAL BLADE*/
case 117: /*CHOPPER*/
script_byte_vars.bvar_63 = 1;
break;
default:
script_byte_vars.bvar_63 = 0;
}
}
} // End of namespace Chamber

36
engines/chamber/invent.h Normal file
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 CHAMBER_INVENT_H
#define CHAMBER_INVENT_H
namespace Chamber {
extern byte inv_count;
extern byte inv_bgcolor;
void drawInventoryBox(uint16 filtermask, uint16 filtervalue);
void openInventory(uint16 filtermask, uint16 filtervalue);
} // End of namespace Chamber
#endif

411
engines/chamber/kult.cpp Normal file
View File

@@ -0,0 +1,411 @@
/* 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/error.h"
#include "common/system.h"
#include "engines/util.h"
#include "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/decompr.h"
#include "chamber/cga.h"
#include "chamber/anim.h"
#include "chamber/cursor.h"
#include "chamber/input.h"
#include "chamber/timer.h"
#include "chamber/portrait.h"
#include "chamber/room.h"
#include "chamber/savegame.h"
#include "chamber/resdata.h"
#include "chamber/script.h"
#include "chamber/print.h"
#include "chamber/dialog.h"
#include "chamber/menu.h"
#include "chamber/ifgm.h"
namespace Chamber {
uint16 cpu_speed_delay;
/*
Prompt user to insert disk #2 to any drive
*/
void askDisk2(void) {
drawMessage(seekToString(vepci_data, 179), frontbuffer);
}
void saveToFile(char *filename, void *data, uint16 size) {
warning("STUB: SaveToFile(%s, data, %d)", filename, size);
#if 0
FILE *f = fopen(filename, "wb");
fwrite(data, 1, size, f);
fclose(f);
#endif
}
int16 loadSplash(const char *filename) {
if (!loadFile(filename, scratch_mem1))
return 0;
decompress(scratch_mem1 + 8, backbuffer); /* skip compressed/decompressed size fields */
return 1;
}
uint16 benchmarkCpu(void) {
byte t;
uint16 cycles = 0;
for (t = script_byte_vars.timer_ticks; t == script_byte_vars.timer_ticks;) ;
for (t = script_byte_vars.timer_ticks; t == script_byte_vars.timer_ticks;) cycles++;
return cycles;
}
void randomize(void) {
warning("STUB: Randomize()");
#if 0
union REGS reg;
reg.h.ah = 0;
int86(0x1A, &reg, &reg);
rand_seed = reg.h.dl;
Rand();
#endif
}
void TRAP() {
promptWait();
for (;;) ;
}
/* Main Game Loop */
void gameLoop(byte *target) {
for (;;) {
animateSpots(target);
/* Update/check live things */
updateProtozorqs();
checkGameTimeLimit();
cleanupDroppedItems();
/* Get player input */
pollInput();
if (g_vm->_shouldQuit)
return;
the_command = 0;
if (isCursorInRect(&room_bounds_rect)) {
selectCursor(CURSOR_TARGET);
command_hint = 100;
selectSpotCursor();
} else {
selectCursor(CURSOR_FINGER);
object_hint = 117;
checkMenuCommandHover();
}
if (object_hint != last_object_hint)
drawObjectHint();
if (command_hint != last_command_hint)
drawCommandHint();
drawHintsAndCursor(target);
if (!buttons || !the_command) {
/*Pending / AI commands*/
if (script_byte_vars.check_used_commands < script_byte_vars.used_commands) {
the_command = Swap16(script_word_vars.next_aspirant_cmd);
if (the_command)
goto process;
}
if (script_byte_vars.bvar_45)
continue;
the_command = Swap16(script_word_vars.next_protozorqs_cmd);
if (the_command)
goto process;
if (Swap16(next_vorts_ticks) < script_word_vars.timer_ticks2) { /*TODO: is this ok? ticks2 is BE, ticks3 is LE*/
the_command = next_vorts_cmd;
if (the_command)
goto process;
}
if (Swap16(next_turkey_ticks) < script_word_vars.timer_ticks2) { /*TODO: is this ok? ticks2 is BE, ticks4 is LE*/
the_command = next_turkey_cmd;
if (the_command)
goto process;
}
continue;
process:
;
updateUndrawCursor(target);
refreshSpritesData();
runCommand();
if (g_vm->_shouldRestart)
return;
blitSpritesToBackBuffer();
processInput();
drawSpots(target);
} else {
/*Player action*/
updateUndrawCursor(target);
refreshSpritesData();
uint16 restart = runCommandKeepSp();
if (restart == RUNCOMMAND_RESTART && g_vm->_shouldRestart)
return;
script_byte_vars.used_commands++;
if (script_byte_vars.dead_flag) {
if (--script_byte_vars.tries_left == 0)
resetAllPersons();
}
blitSpritesToBackBuffer();
processInput();
drawSpots(target);
}
}
}
void exitGame(void) {
switchToTextMode();
uninitTimer();
}
#ifdef DEBUG_ENDING
extern theEnd(void);
#endif
Common::Error ChamberEngine::init() {
byte c;
// Initialize graphics using following:
if (_videoMode == Common::RenderMode::kRenderCGA) {
// 320x200x2
_screenW = 320;
_screenH = 200;
_screenBits = 2;
_screenPPB = 8 / _screenBits;
_screenBPL = _screenW / _screenPPB;
_line_offset = 0x2000;
_fontHeight = 6;
_fontWidth = 4;
initGraphics(_screenW, _screenH);
} else if (_videoMode == Common::RenderMode::kRenderHercG) {
// 720x348x1
_screenW = 720;
_screenH = 348;
_screenBits = 1;
_screenPPB = 8 / _screenBits;
_screenBPL = _screenW / _screenPPB;
_line_offset = 0x2000;
_line_offset2 = 0x2000;
_fontHeight = 6;
_fontWidth = 4;
initGraphics(_screenW, _screenH);
}
initSound();
/*TODO: DetectCPU*/
IFGM_Init();
switchToGraphicsMode();
/* Install timer callback */
initTimer();
if (g_vm->getLanguage() == Common::EN_USA) {
/* Load title screen */
if (!loadSplash("PRESCGA.BIN"))
exitGame();
if (ifgm_loaded) {
/*TODO*/
}
} else {
/* Load title screen */
if (!loadSplash("PRES.BIN"))
exitGame();
}
if (_videoMode == Common::RenderMode::kRenderCGA) {
/* Select intense cyan-mageta palette */
cga_ColorSelect(0x30);
cga_BackBufferToRealFull();
} else if (_videoMode == Common::RenderMode::kRenderHercG) {
/* Select intense cyan-mageta palette */
cga_ColorSelect(0x30);
cga_BackBufferToRealFull();
}
/* Wait for a keypress */
clearKeyboard();
readKeyboardChar();
if (g_vm->getLanguage() == Common::EN_USA) {
if (ifgm_loaded) {
/*TODO*/
}
/* Force English language */
c = 'E';
} else {
/* Load language selection screen */
if (!loadSplash("DRAP.BIN"))
exitGame();
/* Wait for a keypress and show the language selection screen */
clearKeyboard();
readKeyboardChar();
if (_shouldQuit)
return Common::kNoError;
cga_BackBufferToRealFull();
clearKeyboard();
/* Wait for a valid language choice */
do {
c = readKeyboardChar();
if (c > 'F')
c -= ' ';
} while (c < 'D' || c > 'F');
}
if (_shouldQuit)
return Common::kNoError;
/* Patch resource names for chosen language */
res_texts[0].name[4] = c;
res_texts[1].name[4] = c;
res_desci[0].name[4] = c;
res_diali[0].name[4] = c;
if (g_vm->getLanguage() != Common::EN_USA)
cga_BackBufferToRealFull();
/* Load script and other static resources */
/* Those are normally embedded in the executable, but here we load extracted ones*/
if (!loadStaticData())
exitGame();
/* Load text resources */
if (!loadVepciData() || !loadDesciData() || !loadDialiData())
exitGame();
/* Detect/Initialize input device */
initInput();
/* Load graphics resources */
while (!loadFond() || !loadSpritesData() || !loadPersData())
askDisk2();
/*TODO: is this necessary?*/
cga_BackBufferToRealFull();
/* Create clean game state snapshot */
saveRestartGame();
/* Detect CPU speed for delay routines */
cpu_speed_delay = benchmarkCpu() / 8;
if (g_vm->getLanguage() == Common::EN_USA) {
if (ifgm_loaded) {
/*TODO*/
}
}
return Common::kNoError;
}
Common::Error ChamberEngine::execute() {
randomize();
/* Set start zone */
script_byte_vars.zone_index = 7;
/* Begin the game */
script_byte_vars.game_paused = 0;
#ifdef DEBUG_SCRIPT
unlink(DEBUG_SCRIPT_LOG);
#endif
#ifdef DEBUG_SKIP_INTRO
/*bypass characters introduction*/
script_byte_vars.load_flag = DEBUG_SKIP_INTRO;
#endif
/* Discard all pending input */
//ResetInput();
/* Play introduction sequence and initialize game */
the_command = 0xC001;
runCommand();
if (_shouldQuit)
return Common::kNoError;
/* Sync graphics */
blitSpritesToBackBuffer();
/* Initialize cursor backup */
processInput();
#ifdef DEBUG_ENDING
script_byte_vars.game_paused = 5;
theEnd();
for (;;) ;
#endif
/* Main game loop */
gameLoop(frontbuffer);
if (g_vm->_shouldRestart)
run();
/*TODO: the following code is never executed since gameLoop is infinite (or the whole game is restarted) */
/* Release hardware */
uninitInput();
exitGame();
return Common::kNoError;
}
Common::Error ChamberEngine::run() {
if (!g_vm->_shouldRestart)
init();
do {
g_vm->_shouldRestart = false;
execute();
} while (g_vm->_shouldRestart);
return Common::kNoError;
}
} // End of namespace Chamber

255
engines/chamber/menu.cpp Normal file
View File

@@ -0,0 +1,255 @@
/* 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 "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/menu.h"
#include "chamber/cga.h"
#include "chamber/input.h"
#include "chamber/cursor.h"
#include "chamber/room.h"
#include "chamber/sound.h"
#include "chamber/script.h"
namespace Chamber {
byte act_menu_x = 0;
byte act_menu_y = 0;
rect_t *act_dot_rects_cur;
rect_t *act_dot_rects_end;
/*choice dots placement on actions menu*/
rect_t act_dot_rects[8 + 1];
struct {
byte x, y;
} act_dot_coords[8] = {
{ 2, 0},
{ 8, 32},
{ 2, 32},
{10, 8},
{ 0, 24},
{ 8, 0},
{ 0, 8},
{10, 24}
};
/*Handle keyboard keys in actions menu (to cycle through choices with directional keys)*/
byte pollKeyboardInActionsMenu(void) {
pollInput();
if (!(key_direction & 0xF)) {
key_held = 0;
return key_code;
}
if (key_held)
return key_code;
key_held = 1;
/*cycle through menu choices*/
cursor_x = act_dot_rects_cur->sx * 4 + 1;
cursor_y = act_dot_rects_cur->sy + 4;
if (++act_dot_rects_cur == act_dot_rects_end)
act_dot_rects_cur = act_dot_rects;
return key_code;
}
/*Handle player input in actions menu*/
void pollInputInActionsMenu(void) {
pollInput();
}
/*Draw actions menu and process its choices*/
void actionsMenu(byte **pinfo) {
byte x, y;
byte choices;
int16 i, choice, numchoices;
byte *menurecs;
last_object_hint = object_hint;
if (act_menu_x == 0xFF) {
/*recalc menu pos*/
x = cursor_x / 4;
if ((int)(x + 48 / 4) >= 296 / 4)
x -= x + 48 / 4 - 296 / 4;
if (x < 32 / 4)
x = 32 / 4;
act_menu_x = x;
y = cursor_y;
if ((int)(y + 45) >= 180)
y -= y + 45 - 180;
act_menu_y = y;
}
x = act_menu_x;
y = act_menu_y;
/*menu sprite*/
backupAndShowSprite(0, x, y);
playSound(18);
choices = *((*pinfo)++);
menurecs = *pinfo;
numchoices = 0;
for (i = 0; i < 8; i++) {
if (choices & (1 << i)) {
act_dot_rects[numchoices].sx = x + act_dot_coords[i].x;
act_dot_rects[numchoices].ex = act_dot_rects[numchoices].sx + 8 / 4;
act_dot_rects[numchoices].sy = y + act_dot_coords[i].y;
act_dot_rects[numchoices].ey = act_dot_rects[numchoices].sy + 8;
numchoices++;
}
}
act_dot_rects[numchoices].sx = x + 24 / 4;
act_dot_rects[numchoices].sy = y + 22;
/*TODO: no ex/ey?*/
act_dot_rects_end = act_dot_rects + numchoices + 1;
for (i = 0; i < numchoices; i++)
drawSpriteN(1, act_dot_rects[i].sx, act_dot_rects[i].sy, CGA_SCREENBUFFER);
selectCursor(CURSOR_FINGER);
processInput();
choice = 0;
act_dot_rects_cur = act_dot_rects;
do {
pollInputInActionsMenu();
for (choice = 0; choice < numchoices; choice++) {
if (isCursorInRect(&act_dot_rects[choice]))
break;
}
if (choice < numchoices) {
cursor_color = 0xAA;
command_hint = menurecs[choice * 3];
the_command = (menurecs[choice * 3 + 1] << 8) | menurecs[choice * 3 + 2];
} else {
cursor_color = 0xFF;
command_hint = 100;
the_command = 0xFFFF;
}
if (command_hint != last_command_hint)
drawCommandHint(); /*to backbuffer*/
drawHintsAndCursor(CGA_SCREENBUFFER);
} while (buttons == 0);
undrawCursor(CGA_SCREENBUFFER);
if (the_command != 0xFFFF) {
playSound(19);
waitVBlank();
/*draw dot explosion animation*/
drawSpriteN(24, act_dot_rects[choice].sx, act_dot_rects[choice].sy, CGA_SCREENBUFFER);
for (i = 0; i < 0xFFF; i++) ; /*TODO: weak delay*/
drawSpriteN(2, act_dot_rects[choice].sx, act_dot_rects[choice].sy, CGA_SCREENBUFFER);
for (i = 0; i < 0xFFF; i++) ; /*TODO: weak delay*/
drawSpriteN(25, act_dot_rects[choice].sx, act_dot_rects[choice].sy, CGA_SCREENBUFFER);
for (i = 0; i < 0xFFF; i++) ; /*TODO: weak delay*/
}
cga_RestoreBackupImage(CGA_SCREENBUFFER);
*pinfo += numchoices * 3;
}
/*TODO: maybe rename to SpotsLoop*/
void menuLoop(byte spotmask, byte spotvalue) {
processInput();
do {
pollInput();
checkHotspots(spotmask, spotvalue);
if (object_hint != last_object_hint)
drawObjectHint();
drawHintsAndCursor(frontbuffer);
} while (buttons == 0);
undrawCursor(frontbuffer);
}
void processMenu(void) {
selectCursor(CURSOR_BODY);
menuLoop(SPOTFLG_80 | SPOTFLG_20 | SPOTFLG_10 | SPOTFLG_8, SPOTFLG_80 | SPOTFLG_10);
}
rect_t menu_buttons_rects[] = {
{296 / 4, 312 / 4, 15, 30}, /*Room's Objects*/
{296 / 4, 312 / 4, 40, 56}, /*Psi Powers*/
{296 / 4, 312 / 4, 56, 72}, /*Possessions*/
{296 / 4, 312 / 4, 72, 88}, /*Energy Level*/
{296 / 4, 312 / 4, 88, 104}, /*Wait*/
{296 / 4, 312 / 4, 104, 120}, /*Load*/
{296 / 4, 312 / 4, 120, 136}, /*Save*/
{296 / 4, 312 / 4, 136, 152} /*Time*/
};
void checkMenuCommandHover(void) {
int16 i;
for (i = 0; i < 8; i++) {
if (isCursorInRect(&menu_buttons_rects[i])) {
the_command = 0xA001 + i;
command_hint = i ? (i + 3) : 101;
cursor_color = 0xAA;
return;
}
}
/*nothing found*/
command_hint = 100;
cursor_color = 0xFF;
the_command = 0;
}
rect_t psi_buttons_rects[] = {
{280 / 4, 296 / 4, 40, 56}, /*Solar Eyes*/
{280 / 4, 296 / 4, 56, 72}, /*Sticky Fingers*/
{280 / 4, 296 / 4, 72, 88}, /*Know Mind*/
{280 / 4, 296 / 4, 88, 104}, /*Brainwarp*/
{280 / 4, 296 / 4, 104, 120}, /*Zone Scan*/
{280 / 4, 296 / 4, 120, 136}, /*Psi Shift*/
{280 / 4, 296 / 4, 136, 152}, /*Extreme Violence*/
{280 / 4, 296 / 4, 152, 168} /*Tune In*/
};
void checkPsiCommandHover(void) {
/*TODO: maybe merge it with CheckMenuCommandHover()*/
int16 i;
for (i = 0; i < 8; i++) {
if (isCursorInRect(&psi_buttons_rects[i])) {
the_command = 0xA00A + i;
command_hint = i + 12;
cursor_color = 0xAA;
return;
}
}
/*nothing found*/
command_hint = 100;
cursor_color = 0xFF;
the_command = 0;
}
} // End of namespace Chamber

39
engines/chamber/menu.h Normal file
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 CHAMBER_MENU_H
#define CHAMBER_MENU_H
namespace Chamber {
extern byte act_menu_x;
extern byte act_menu_y;
void actionsMenu(byte **pinfo);
void menuLoop(byte spotmask, byte spotvalue);
void processMenu(void);
void checkMenuCommandHover(void);
void checkPsiCommandHover(void);
} // End of namespace Chamber
#endif

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/>.
*
*/
#include "chamber/chamber.h"
#include "engines/advancedDetector.h"
#include "common/translation.h"
#include "backends/keymapper/action.h"
#include "backends/keymapper/keymapper.h"
#include "backends/keymapper/standard-actions.h"
namespace Chamber {
Common::Language ChamberEngine::getLanguage() const {
return _gameDescription->language;
}
} // end of namespace Chamber
class ChamberMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
public:
const char *getName() const override {
return "chamber";
}
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
Common::KeymapArray initKeymaps(const char *target) const override;
};
Common::Error ChamberMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
*engine = new Chamber::ChamberEngine(syst, desc);
return Common::kNoError;
}
Common::KeymapArray ChamberMetaEngine::initKeymaps(const char *target) const {
using namespace Common;
using namespace Chamber;
Keymap *engineKeymap = new Keymap(Keymap::kKeymapTypeGame, "chamber-default", _("Default keymappings"));
Keymap *gameKeymap = new Keymap(Keymap::kKeymapTypeGame, "game-shortcuts", _("Game keymappings"));
Keymap *quitDialogKeymap = new Keymap(Keymap::kKeymapTypeGame, "quit-dialog", _("Quit dialog keymappings"));
Action *act;
act = new Action(kStandardActionLeftClick, _("Select / Interact"));
act->setLeftClickEvent();
act->addDefaultInputMapping("MOUSE_LEFT");
act->addDefaultInputMapping("JOY_A");
engineKeymap->addAction(act);
act = new Action(kStandardActionRightClick, _("Select / Interact"));
act->setRightClickEvent();
act->addDefaultInputMapping("MOUSE_RIGHT");
act->addDefaultInputMapping("JOY_B");
engineKeymap->addAction(act);
act = new Action("INTERACT", _("Select / Interact"));
act->setCustomEngineActionEvent(kActionInteract);
act->addDefaultInputMapping("SPACE");
gameKeymap->addAction(act);
// Only the EN_USA version has a quit dialog. Input handling does a similar check.
if (parseLanguage(ConfMan.get("language")) == EN_USA) {
act = new Action("QUIT", _("Quit"));
act->setCustomEngineActionEvent(kActionQuit);
act->addDefaultInputMapping("ESCAPE");
act->addDefaultInputMapping("JOY_X");
gameKeymap->addAction(act);
}
act = new Action("YES", _("Yes"));
act->setCustomEngineActionEvent(kActionYes);
act->addDefaultInputMapping("y");
act->addDefaultInputMapping("JOY_A");
quitDialogKeymap->addAction(act);
act = new Action("NO", _("No"));
act->setCustomEngineActionEvent(kActionNo);
act->addDefaultInputMapping("n");
act->addDefaultInputMapping("JOY_B");
quitDialogKeymap->addAction(act);
Common::KeymapArray keymaps(3);
keymaps[0] = engineKeymap;
keymaps[1] = gameKeymap;
keymaps[2] = quitDialogKeymap;
quitDialogKeymap->setEnabled(false);
return keymaps;
}
#if PLUGIN_ENABLED_DYNAMIC(CHAMBER)
REGISTER_PLUGIN_DYNAMIC(CHAMBER, PLUGIN_TYPE_ENGINE, ChamberMetaEngine);
#else
REGISTER_PLUGIN_STATIC(CHAMBER, PLUGIN_TYPE_ENGINE, ChamberMetaEngine);
#endif

42
engines/chamber/module.mk Normal file
View File

@@ -0,0 +1,42 @@
MODULE := engines/chamber
MODULE_OBJS := \
anim.o \
bkbuff.o \
cga.o \
chamber.o \
cursor.o \
decompr.o \
dialog.o \
ifgm.o \
input.o \
invent.o \
kult.o \
menu.o \
metaengine.o \
portrait.o \
print.o \
r_pers.o \
r_puzzl.o \
r_sprit.o \
r_texts.o \
resdata.o \
room.o \
savegame.o \
script.o \
sound.o \
timer.o
MODULE_DIRS += \
engines/chamber
# This module can be built as a plugin
ifeq ($(ENABLE_CHAMBER), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk
# Detection objects
DETECT_OBJS += $(MODULE)/detection.o

View File

@@ -0,0 +1,376 @@
/* 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 "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/portrait.h"
#include "chamber/resdata.h"
#include "chamber/room.h"
#include "chamber/cga.h"
#include "chamber/script.h"
#include "chamber/dialog.h"
#include "chamber/input.h"
#include "chamber/sound.h"
#include "chamber/ifgm.h"
namespace Chamber {
extern uint16 cpu_speed_delay;
byte *cur_image_pixels;
byte cur_image_size_w;
byte cur_image_size_h;
byte cur_image_coords_x;
byte cur_image_coords_y;
uint16 cur_image_offs;
uint16 cur_image_end;
byte cur_image_idx;
byte cur_image_anim1;
byte cur_image_anim2;
uint16 cur_frame_width;
typedef struct persframe_t {
byte height;
byte width;
byte topbot; /*border and fill colors*/
byte fill;
byte left;
byte right;
} persframe_t;
persframe_t pers_frames[] = {
{65, 16, 0xFF, 0xAA, 0xEA, 0xAB},
{70, 16, 0xFF, 0xAA, 0xEA, 0xAB},
{65, 17, 0xFF, 0xAA, 0xEA, 0xAB},
{75, 17, 0xFF, 0xAA, 0xEA, 0xAB},
{85, 16, 0xFF, 0xAA, 0xEA, 0xAB},
{47, 13, 0xFF, 0, 0xC0, 3},
{65, 18, 0xFF, 0xAA, 0xEA, 0xAB},
{38, 11, 0xFF, 0, 0xC0, 3},
{27, 34, 0, 0, 0, 0}
};
void makePortraitFrame(byte index, byte *target) {
uint16 i;
persframe_t *pframe = &pers_frames[index];
*target++ = pframe->height;
*target++ = pframe->width;
cur_frame_width = pframe->width;
memset(target, pframe->topbot, pframe->width);
target += pframe->width;
for (i = 0; i < pframe->height - 2; i++) {
*target++ = pframe->left;
memset(target, pframe->fill, pframe->width - 2);
target += pframe->width - 2;
*target++ = pframe->right;
}
memset(target, pframe->topbot, pframe->width);
}
/*TODO: move this to CGA ?*/
/*
Superimpose source sprite data over target image data
*/
void mergeImageAndSpriteData(byte *target, int16 pitch, byte *source, uint16 w, uint16 h) {
uint16 x;
while (h--) {
for (x = 0; x < w; x++) {
byte m = *source++;
*target &= m;
*target++ |= *source++;
}
target -= w;
target += pitch;
}
}
/*
Superimpose horizontally-flipped source sprite data over target image data
*/
void mergeImageAndSpriteDataFlip(byte *target, int16 pitch, byte *source, uint16 w, uint16 h) {
uint16 x;
target += w - 1;
while (h--) {
for (x = 0; x < w; x++) {
byte m = cga_pixel_flip[*source++];
*target &= m;
*target |= cga_pixel_flip[*source++];
target -= 1;
}
target += w;
target += pitch;
}
}
/*
Build portrait from multiple pers sprites
*/
byte *loadPortrait(byte **pinfo, byte *end) {
while (*pinfo != end) {
byte index;
uint16 flags;
int16 pitch;
byte *buffer, *sprite;
byte sprw, sprh;
index = *((*pinfo)++);
flags = *((*pinfo)++);
flags |= (*((*pinfo)++)) << 8;
buffer = sprit_load_buffer + 2 + 2 + (flags & 0x3FFF);
pitch = cur_frame_width;
sprite = loadPersSprit(index);
sprw = *sprite++;
sprh = *sprite++;
if (flags & 0x8000) { /*vertical flip*/
buffer += pitch * (sprh - 1);
pitch = -pitch;
}
if (flags & 0x4000) /*horizontal flip*/
mergeImageAndSpriteDataFlip(buffer, pitch, sprite, sprw, sprh);
else
mergeImageAndSpriteData(buffer, pitch, sprite, sprw, sprh);
}
return sprit_load_buffer + 2;
}
byte *loadPortraitWithFrame(byte index) {
byte *pinfo, *end;
pinfo = seekToEntry(icone_data, index, &end);
makePortraitFrame(*pinfo++, sprit_load_buffer + 2);
return loadPortrait(&pinfo, end);
}
#define STATIC_ANIMS_MAX 24
struct {
byte index;
byte image;
byte x;
byte y;
byte anim1;
byte anim2;
} static_anims[] = {
{ 24, 13, 35, 10, 4, 5},
{ 88, 42, 35, 10, 11, 12},
{152, 50, 35, 10, 13, 14},
{216, 58, 35, 10, 15, 16},
{ 40, 9, 30, 20, 3, 3},
{ 48, 1, 35, 20, 1, 2},
{ 32, 66, 35, 20, 17, 18},
{128, 21, 20, 10, 6, 6},
{192, 25, 2, 70, 7, 7},
{ 56, 85, 25, 20, 26, 27},
{ 64, 74, 56, 85, 23, 23},
{ 72, 74, 56, 85, 23, 23},
{ 80, 78, 27, 20, 24, 24},
{144, 80, 27, 20, 25, 25},
{ 96, 100, 27, 20, 29, 29},
{104, 92, 27, 20, 28, 28},
{112, 100, 27, 20, 29, 53},
{224, 96, 27, 20, 48, 48},
{232, 92, 27, 20, 47, 47},
{184, 160, 27, 20, 50, 52},
{200, 78, 27, 20, 24, 24},
{160, 106, 33, 2, 49, 49},
{168, 147, 16, 2, 32, 32},
{248, 117, 16, 2, 33, 33}
};
byte selectCurrentAnim(byte *x, byte *y, byte *index) {
int16 i;
byte aniidx = ((pers_t *)(script_vars[kScrPool8_CurrentPers]))->index & ~7;
for (i = 0; i < STATIC_ANIMS_MAX; i++) {
if (static_anims[i].index == aniidx) {
*x = static_anims[i].x;
*y = static_anims[i].y;
*index = static_anims[i].image;
cur_image_anim1 = static_anims[i].anim1;
cur_image_anim2 = static_anims[i].anim2;
return 1;
}
}
warning("SelectCurrentAnim: not found for %d", aniidx);
return 0;
}
void drawBoxAroundSpot(void) {
byte *buffer;
uint16 w, h;
uint16 ofs;
uint16 x, y;
if (*spot_sprite == 0)
return;
zone_spots_cur = found_spot;
zone_spr_index = script_byte_vars.cur_spot_idx - 1;
buffer = *spot_sprite;
h = *(byte *)(buffer + 0);
w = *(byte *)(buffer + 1);
ofs = *(uint16 *)(buffer + 2);
/*decode ofs back to x:y*/
/*TODO: this is CGA-only!*/
y = (ofs & g_vm->_line_offset) ? 1 : 0;
ofs &= ~g_vm->_line_offset;
x = (ofs % g_vm->_screenBPL) * g_vm->_screenPPB;
y += (ofs / g_vm->_screenBPL) * 2;
w *= g_vm->_screenPPB; /*TODO: this will overflow on large sprite*/
cga_DrawVLine(x, y, h - 1, 0, CGA_SCREENBUFFER);
cga_DrawHLine(x, y, w - 1, 0, CGA_SCREENBUFFER);
cga_DrawVLine(x + w - 1, y, h - 1, 0, CGA_SCREENBUFFER);
cga_DrawHLine(x, y + h - 1, w - 1, 0, CGA_SCREENBUFFER);
cga_RefreshImageData(*spot_sprite);
}
/*Get on-screen image as specified by script to temp buffer and register it with dirty rect of kind 2
If rmb is pressed, draw it immediately and return 0
*/
int16 drawPortrait(byte **desc, byte *x, byte *y, byte *width, byte *height) {
byte index;
byte xx, yy;
byte *image;
index = *((*desc)++);
if (index == 0xFF) {
if (script_byte_vars.dirty_rect_kind != 0)
return 0;
drawBoxAroundSpot();
if (!selectCurrentAnim(&xx, &yy, &index))
return 0;
} else {
xx = *((*desc)++);
yy = *((*desc)++);
}
cur_image_coords_x = xx;
cur_image_coords_y = yy;
cur_image_idx = index;
image = loadPortraitWithFrame(index - 1);
cur_image_size_h = *image++;
cur_image_size_w = *image++;
cur_image_pixels = image;
cur_image_offs = CalcXY_p(cur_image_coords_x, cur_image_coords_y);
addDirtyRect(DirtyRectSprite, cur_image_coords_x, cur_image_coords_y, cur_image_size_w, cur_image_size_h, cur_image_offs);
/*TODO: remove and use only globals?*/
*x = cur_image_coords_x;
*y = cur_image_coords_y;
*width = cur_image_size_w;
*height = cur_image_size_h;
if (right_button) {
cga_BlitAndWait(cur_image_pixels, cur_image_size_w, cur_image_size_w, cur_image_size_h, CGA_SCREENBUFFER, cur_image_offs);
return 0;
}
return 1;
}
void playHurtSound() {
if (!ifgm_loaded)
playSound(144);
else
playSound(144 + (getRand() / 4) % 4);
}
void blinkWithSound(byte color) {
cga_ColorSelect(color);
playHurtSound();
selectPalette();
}
void blinkToRed(void) {
blinkWithSound(0x3C);
}
void blinkToWhite(void) {
if (g_vm->getLanguage() == Common::EN_USA)
playHurtSound(); /*TODO: play here and later? looks like a bug, original code will trash palette selection if pcspeaker is used*/
blinkWithSound(0x3F);
}
volatile byte vblank_ticks;
void waitVBlankTimer(void) {
if (g_vm->getLanguage() == Common::EN_USA) {
/*A crude attempt to fix the animation speed...*/
while (vblank_ticks < 3) ;
vblank_ticks = 0;
}
waitVBlank();
}
void animPortrait(byte layer, byte index, byte delay) {
byte *ani, *ani_end;
byte temp;
selectCurrentAnim(&temp, &temp, &temp);
if (index == 0xFF)
index = cur_image_anim1;
if (index == 0xFE)
index = cur_image_anim2;
IFGM_PlaySfx(index);
ani = seekToEntry(anico_data, index - 1, &ani_end);
cur_image_pixels = sprit_load_buffer + 2 + 2;
while (ani != ani_end) {
byte kind;
byte x, y;
byte width, height;
uint16 offs;
byte portrait = *ani++;
loadPortraitWithFrame(portrait - 1);
if (*ani == 0xFF) {
ani++;
loadPortrait(&ani, ani + 3);
}
getDirtyRectAndSetSprite(layer, &kind, &x, &y, &width, &height, &offs);
waitVBlank();
cga_BlitAndWait(cur_image_pixels, width, width, height, CGA_SCREENBUFFER, offs);
waitVBlankTimer();
if (delay) {
if (ani[-1] == 37) { /*TODO: what is it?*/
if (script_byte_vars.extreme_violence)
blinkToRed();
else
blinkToWhite();
} else {
int16 i;
while (delay--) for (i = 0; i < cpu_speed_delay; i++) ; /*TODO: FIXME weak delay*/
}
}
}
}
} // End of namespace Chamber

View File

@@ -0,0 +1,55 @@
/* 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 CHAMBER_PORTRAIT_H
#define CHAMBER_PORTRAIT_H
namespace Chamber {
extern byte *cur_image_pixels;
extern byte cur_image_size_w;
extern byte cur_image_size_h;
extern byte cur_image_coords_x;
extern byte cur_image_coords_y;
extern uint16 cur_image_offs;
extern uint16 cur_image_end;
extern byte cur_image_idx;
extern byte cur_image_anim1;
extern byte cur_image_anim2;
extern uint16 cur_frame_width;
extern volatile byte vblank_ticks;
int16 drawPortrait(byte **desc, byte *x, byte *y, byte *width, byte *height);
void animPortrait(byte layer, byte index, byte delay);
void drawBoxAroundSpot(void);
void mergeImageAndSpriteData(byte *target, int16 pitch, byte *source, uint16 w, uint16 h);
void mergeImageAndSpriteDataFlip(byte *target, int16 pitch, byte *source, uint16 w, uint16 h);
void blinkToRed(void);
void blinkToWhite(void);
} // End of namespace Chamber
#endif

300
engines/chamber/print.cpp Normal file
View File

@@ -0,0 +1,300 @@
/* 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 "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/cga.h"
#include "chamber/cursor.h"
#include "chamber/dialog.h"
namespace Chamber {
byte *cur_str_end;
byte draw_x;
byte draw_y;
/*
Calculate number of string's character until whitespace
Return current word's characters count and the next word ptr
*/
byte *calcStringWordWidth(byte *str, uint16 *w) {
uint16 ww = 0;
byte c;
if ((*str & 0x3F) == 0) {
str++;
ww++;
}
while (str != cur_str_end) {
if ((*str & 0x3F) == 0)
break;
ww++;
c = *str & 0xC0;
if (c != 0) {
if (c == 0x40) { /*space?*/
str++;
break;
}
ww++;
}
str++;
}
*w = ww;
return str;
}
/*
Calculate number of text's words and max word width (in chars)
*/
void calcStringSize(byte *str, uint16 *w, uint16 *n) {
uint16 ww = 0, nw = 0, lw;
byte *s = str;
do {
s = calcStringWordWidth(s, &lw);
if (lw > ww)
ww = lw;
nw += 1;
} while (s != cur_str_end);
*w = ww;
*n = nw;
}
/*
Calculate number of text's lines with respect to set max width
If a line is longer, wrap it to the next line
*/
uint16 calcTextLines(byte *str) {
uint16 lines = 1;
uint16 w, left = char_draw_max_width;
while (str != cur_str_end) {
str = calcStringWordWidth(str, &w);
if (left > w) {
left = left - w - 1;
} else {
lines++;
left = char_draw_max_width - w - 1;
}
}
return lines;
}
/*; translate 1-bit raster (4 columns per byte) to 4 2-bit color pixels*/
byte chars_color_bonw[] = {0xFF, 0xFC, 0xF3, 0xF0, 0xCF, 0xCC, 0xC3, 0xC0, 0x3F, 0x3C, 0x33, 0x30, 0x0F, 0x0C, 3, 0}; /*black on white*/
byte chars_color_bonc[] = {0x55, 0x54, 0x51, 0x50, 0x45, 0x44, 0x41, 0x40, 0x15, 0x14, 0x11, 0x10, 5, 4, 1, 0}; /*black on cyan*/
byte chars_color_wonb[] = { 0, 3, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F, 0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF}; /*white on black*/
byte chars_color_wonc[] = {0x55, 0x57, 0x5D, 0x5F, 0x75, 0xF7, 0x7D, 0x7F, 0xD5, 0xD7, 0xDD, 0xDF, 0xF5, 0xF7, 0xFD, 0xFF}; /*white on cyan*/
void printStringPad(uint16 w, byte *target) {
while (w--)
cga_PrintChar(0, target);
}
byte *printWord(byte *str, byte *target) {
byte c, f;
if ((*str & 0x3F) == 0)
goto skip_1st;
while (str != cur_str_end) {
f = *str;
c = f & 0x3F;
if (c == 0) {
if ((f & 0xC0) == 0)
str++;
return str;
}
cga_PrintChar(c, target);
skip_1st:
;
f = *str & 0xC0;
str++;
if (f) {
if (f == 0x80)
cga_PrintChar(0x25, target);
else if (f != 0x40)
cga_PrintChar(0x21, target);
else
return str;
}
}
string_ended = 1;
return str;
}
byte *printStringLine(byte *str, uint16 *left, byte *target) {
uint16 mw = char_draw_max_width;
for (;;) {
uint16 w;
calcStringWordWidth(str, &w);
if (mw < w)
break;
mw -= w;
str = printWord(str, target);
if (string_ended || (mw == 0))
break;
mw--;
cga_PrintChar(0, target);
}
*left = mw;
return str;
}
byte *printStringPadded(byte *str, byte *target) {
uint16 w;
if (g_vm->getLanguage() != Common::EN_USA) {
uint16 n;
calcStringSize(str, &w, &n);
if (w + 2 >= char_draw_max_width)
char_draw_max_width = w + 2;
}
str = printStringLine(str, &w, target);
if (w != 0)
printStringPad(w, target);
return str;
}
void printStringCentered(byte *str, byte *target) {
byte pad = 0;
uint16 ww = 0, lw;
byte *s = str;
do {
s = calcStringWordWidth(s, &lw);
ww += lw;
} while (s != cur_str_end);
pad = (char_draw_max_width - ww) / 2;
if (pad) {
char_draw_max_width -= pad;
printStringPad(pad, target);
}
string_ended = 0; /*TODO: move me elsewhere*/
printStringPadded(str, target);
}
void cga_DrawTextBox(byte *msg, byte *target) {
uint16 x, y, w, i;
uint16 ww, nw;
char_xlat_table = chars_color_bonc;
if (g_vm->getLanguage() == Common::EN_USA) {
calcStringSize(msg, &ww, &nw);
if (ww >= char_draw_max_width)
char_draw_max_width = ww;
}
x = draw_x * 4;
y = draw_y;
w = (char_draw_max_width + 2) * 4 - 2;
cga_DrawHLine(x + 2, y, w - 2, 0, target); /*box top*/
for (i = 0; i < 3; i++)
cga_DrawHLine(x + 1, y + 1 + i, w, 1, target); /*top margin*/
cga_DrawVLine(x, y + 2, 2, 0, target); /*left top corner 1*/
cga_DrawVLine(x + 1, y + 1, 1, 0, target); /*left top corner 2*/
cga_DrawVLine(x + w, y + 1, 1, 0, target); /*right top corner 1*/
cga_DrawVLine(x + w + 1, y + 2, 2, 0, target); /*right top corner 2*/
char_draw_coords_y = draw_y + 4;
string_ended = 0;
do {
char_draw_coords_x = draw_x;
cga_PrintChar(0x3B, target);
msg = printStringPadded(msg, target);
cga_PrintChar(0x3C, target);
char_draw_coords_y += 6;
} while (!string_ended);
x = draw_x * 4;
y = char_draw_coords_y;
cga_DrawHLine(x + 1, y, w, 1, target); /*bottom margin*/
cga_DrawVLine(x + 1, y, 1, 0, target); /*bottom left corner 1*/
cga_DrawHLine(x + 2, y + 1, w - 2, 0, target); /*box bottom*/
cga_DrawVLine(x + 1, y, 1, 0, target); /*TODO: duplicated?*/
cga_DrawVLine(x + w, y, 1, 0, target); /*bottom right corner*/
}
void drawMessage(byte *msg, byte *target) {
uint16 x, y;
uint16 w, h;
calcStringSize(msg, &w, &h);
char_draw_max_width = (h < 5) ? (w + 2) : 20;
char_draw_max_height = calcTextLines(msg) * 6 + 7;
x = cursor_x / 4;
if (x < 9)
x = 9;
if (x + char_draw_max_width + 2 >= 73)
x = 73 - (char_draw_max_width + 2);
y = cursor_y;
if (y + char_draw_max_height >= 200)
y = 200 - char_draw_max_height;
draw_x = x;
draw_y = y;
cga_BackupImageReal(CalcXY_p(x, y), char_draw_max_width + 2, char_draw_max_height); /*backup orig. screen data*/
cga_DrawTextBox(msg, target); /*draw box with text*/
promptWait(); /*wait keypress*/
cga_RestoreBackupImage(target); /*restore screen data*/
}
#if 1
void debugMessage(char *msg, ...) {
int16 i;
byte c;
byte m[256];
va_list ap;
va_start(ap, msg);
vsnprintf((char *)m, 256, msg, ap);
va_end(ap);
for (i = 0; m[i]; i++) {
c = m[i];
if (c >= 'A' && c <= 'Z')
c = 0x21 + (c - 'A');
else if (c >= 'a' && c <= 'z')
c = 0x21 + (c - 'a');
else if (c >= '0' && c <= '9')
c = 0x10 + (c - '0');
else if (c == ' ')
c = 0x20;
else if (c == '\n')
c = 0x00;
else
c = 0x1F;
m[i] = c;
}
cur_str_end = m + i;
drawMessage(m, frontbuffer);
}
#endif
} // End of namespace Chamber

48
engines/chamber/print.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 CHAMBER_PRINT_H
#define CHAMBER_PRINT_H
namespace Chamber {
extern byte *cur_str_end;
extern byte draw_x;
extern byte draw_y;
extern byte chars_color_bonw[];
extern byte chars_color_bonc[];
extern byte chars_color_wonb[];
extern byte chars_color_wonc[];
void printStringCentered(byte *str, byte *target);
byte *printStringPadded(byte *str, byte *target);
void drawMessage(byte *msg, byte *target);
void cga_DrawTextBox(byte *msg, byte *target);
void calcStringSize(byte *str, uint16 *w, uint16 *n);
} // End of namespace Chamber
#endif

View File

@@ -0,0 +1,34 @@
/* 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 "chamber/chamber.h"
#include "chamber/resdata.h"
namespace Chamber {
byte pers1_data[RES_PERS1_MAX];
byte pers2_data[RES_PERS2_MAX];
byte desci_data[RES_DESCI_MAX];
byte diali_data[RES_DIALI_MAX];
} // End of namespace Chamber

View File

@@ -0,0 +1,29 @@
/* 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 "chamber/chamber.h"
#include "chamber/resdata.h"
namespace Chamber {
byte puzzl_data[RES_PUZZL_MAX];
} // End of namespace Chamber

View File

@@ -0,0 +1,29 @@
/* 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 "chamber/chamber.h"
#include "chamber/resdata.h"
namespace Chamber {
byte sprit_data[RES_SPRIT_MAX];
} // End of namespace Chamber

View File

@@ -0,0 +1,31 @@
/* 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 "chamber/chamber.h"
#include "chamber/resdata.h"
namespace Chamber {
byte vepci_data[RES_VEPCI_MAX];
byte motsi_data[RES_MOTSI_MAX];
} // End of namespace Chamber

302
engines/chamber/resdata.cpp Normal file
View File

@@ -0,0 +1,302 @@
/* 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 "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/resdata.h"
#include "chamber/decompr.h"
namespace Chamber {
extern void askDisk2(void);
extern int16 loadSplash(const char *filename);
/*
Get bank entry
TODO: port SeekToString to this routine
*/
byte *seekToEntry(byte *bank, uint16 num, byte **end) {
byte len;
byte *p = bank;
while (num--) {
len = *p;
p += len;
}
len = *p;
*end = p + len;
return p + 1;
}
byte *seekToEntryW(byte *bank, uint16 num, byte **end) {
uint16 len;
byte *p = bank;
while (num--) {
len = p[0] | (p[1] << 8);
p += len;
}
len = p[0] | (p[1] << 8);
*end = p + len;
return p + 2;
}
uint16 loadFile(const char *filename, byte *buffer) {
Common::File in;
in.open(filename);
if (!in.isOpen())
return 0;
return in.read(buffer, 0xFFFF0);
}
uint16 saveFile(char *filename, byte *buffer, uint16 size) {
warning("STUB: SaveFile(%s, buffer, %d)", filename, size);
return 0;
#if 0
int16 f;
int16 wlen;
f = open(filename, O_RDONLY | O_BINARY);
if (f == -1)
return 0;
wlen = write(f, buffer, size);
close(f);
if (wlen == -1)
return 0;
return (uint16)wlen;
#endif
}
int16 loadFilesList(ResEntry_t *entries) {
int16 i;
for (i = 0; entries[i].name[0] != '$'; i++) {
if (!loadFile(entries[i].name, (byte *)entries[i].buffer))
return 0;
}
return 1;
}
byte *arpla_data = NULL;
byte *aleat_data = NULL;
byte *icone_data = NULL;
byte *souco_data = NULL;
byte *carpc_data = NULL;
byte *souri_data = NULL;
byte *templ_data = NULL;
byte *mursm_data = NULL;
byte *gauss_data = NULL;
byte *lutin_data = NULL;
byte *anima_data = NULL;
byte *anico_data = NULL;
byte *zones_data = NULL;
ResEntry_tp res_static[] = {
{"ARPLA.BIN", &arpla_data},
{"ALEAT.BIN", &aleat_data},
{"ICONE.BIN", &icone_data},
{"SOUCO.BIN", &souco_data},
{"CARPC.BIN", &carpc_data},
{"SOURI.BIN", &souri_data},
{"TEMPL.BIN", &templ_data},
{"MURSM.BIN", &mursm_data},
{"GAUSS.BIN", &gauss_data},
{"LUTIN.BIN", &lutin_data},
{"ANIMA.BIN", &anima_data},
{"ANICO.BIN", &anico_data},
{"ZONES.BIN", &zones_data},
{"$", NULL}
};
/*
Load resident data files. Original game has all these data files embedded in the executable.
NB! Static data includes the font file, don't use any text print routines before it's loaded.
*/
int16 loadStaticData() {
Common::File pxi;
if (g_vm->getLanguage() == Common::EN_USA)
pxi.open("kult1.pxi");
else
pxi.open("ere.pxi");
uint numMods = pxi.readUint16BE();
uint modBase = 2 + numMods * 4;
uint32 *modOffs = new uint32[numMods];
for (uint i = 0; i < numMods; i++)
modOffs[i] = modBase + pxi.readUint32BE();
// So far, take only resource 0. Additional selection is required
uint32 modOfs = modOffs[0];
pxi.seek(modOfs);
uint32 modPsize = pxi.readUint32BE();
uint32 modUsize = pxi.readUint32BE();
byte *modData = new byte[modPsize];
pxi.read(modData, modPsize);
warning("Module %d : at 0x%6X, psize = %6d, usize = %6d", 0, modOfs, modPsize, modUsize);
byte *rawData = new byte[modUsize];
g_vm->_pxiData = rawData;
uint32 rawSize = decompress(modData, rawData);
warning("decoded to %d bytes", rawSize);
delete[] modData;
if (rawData[0] != 'M' || rawData[1] != 'Z')
error("Module decompressed, but is not an EXE file");
uint16 hdrparas = READ_LE_UINT16(rawData + 8);
uint32 off = hdrparas * 16;
warning("hdrparas: 0x%x, off: 0x%x", hdrparas, off);
const char *firstRes = "ARPLA.";
int32 resOffs = -1;
for (uint i = off; i < rawSize; i++)
if (!strncmp((char *)rawData + i, firstRes, strlen(firstRes))) {
resOffs = i;
break;
}
if (resOffs == -1)
error("No internal resources table found");
warning("Found resources table at 0x%X", resOffs - off);
while (rawData[resOffs] != '$') {
Common::String resName((char *)rawData + resOffs);
resOffs += MAX(resName.size() + 1, 10U); // work around malformed resource entry in the US release
uint16 reso = READ_LE_UINT16(rawData + resOffs);
resOffs += 2;
uint16 ress = READ_LE_UINT16(rawData + resOffs);
resOffs += 2;
warning("%s : %X", resName.c_str(), ress * 16 + reso);
int i;
for (i = 0; res_static[i].name[0] != '$'; i++) { // Yeah, linear search
if (!strcmp(res_static[i].name, resName.c_str())) {
*res_static[i].buffer = rawData + off + ress * 16 + reso;
break;
}
}
if (res_static[i].name[0] == '$')
warning("loadStaticData(): Extra resource %s", resName.c_str());
}
// And now check that everything was loaded
bool missing = false;
for (int i = 0; res_static[i].name[0] != '$'; i++) {
if (*res_static[i].buffer == NULL) {
warning("loadStaticData(): Resource %s is not present", res_static[i].name);
missing = true;
}
}
delete[] modOffs;
return !missing;
}
ResEntry_t res_texts[] = {
{"VEPCI.BIN", vepci_data},
{"MOTSI.BIN", motsi_data},
{"$", NULL}
};
/*
Load strings data (commands/names)
*/
int16 loadVepciData() {
return loadFilesList(res_texts);
}
int16 loadFond(void) {
return loadSplash("FOND.BIN");
}
ResEntry_t res_sprites[] = {
{"PUZZL.BIN", puzzl_data},
{"SPRIT.BIN", sprit_data},
{"$", NULL}
};
int16 loadSpritesData(void) {
return loadFilesList(res_sprites);
}
ResEntry_t res_person[] = {
{"PERS1.BIN", pers1_data},
{"PERS2.BIN", pers2_data},
{"$", NULL}
};
int16 loadPersData(void) {
/*Originally it tries to load pers1 + pers2 as a single contiguos resource, if have enough memory*/
/*If memory is low, necessary file is loaded on demand, according to requested bank resource index*/
/*Here we load both parts to their own memory buffers then select one in LoadPersSprit()*/
return loadFilesList(res_person);
}
ResEntry_t res_desci[] = {
{"DESCI.BIN", desci_data},
{"$", NULL}
};
/*
Load strings data (obj. descriptions)
*/
int16 loadDesciData(void) {
while (!loadFilesList(res_desci))
askDisk2();
return 1;
}
ResEntry_t res_diali[] = {
{"DIALI.BIN", diali_data},
{"$", NULL}
};
/*
Load strings data (dialogs)
*/
int16 loadDialiData(void) {
while (!loadFilesList(res_diali))
askDisk2();
return 1;
}
} // End of namespace Chamber

109
engines/chamber/resdata.h Normal file
View File

@@ -0,0 +1,109 @@
/* 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 CHAMBER_RESDATA_H
#define CHAMBER_RESDATA_H
namespace Chamber {
typedef struct ResEntry_t {
char name[5 + 1 + 3 + 1];
void *buffer;
} ResEntry_t;
typedef struct ResEntry_tp {
char name[5 + 1 + 3 + 1];
byte **buffer;
} ResEntry_tp;
/* Max resource file size among all languages */
#define RES_ALEAT_MAX 256
#define RES_ANICO_MAX 667
#define RES_ANIMA_MAX 2046
#define RES_ARPLA_MAX 7910
#define RES_CARPC_MAX 384
#define RES_GAUSS_MAX 1449
#define RES_ICONE_MAX 2756
#define RES_LUTIN_MAX 2800
#define RES_MURSM_MAX 76
#define RES_SOUCO_MAX 424
#define RES_SOURI_MAX 1152
#define RES_TEMPL_MAX 27337
#define RES_ZONES_MAX 9014
#define RES_PUZZL_MAX 45671
#define RES_SPRIT_MAX 23811
#define RES_PERS1_MAX 14294
#define RES_PERS2_MAX 10587
#define RES_DESCI_MAX 10515
#define RES_DIALI_MAX 9636
#define RES_MOTSI_MAX 1082
#define RES_VEPCI_MAX 1345
extern byte vepci_data[];
extern byte motsi_data[];
extern byte puzzl_data[];
extern byte sprit_data[];
extern byte pers1_data[];
extern byte pers2_data[];
extern byte desci_data[];
extern byte diali_data[];
extern byte *arpla_data;
extern byte *aleat_data;
extern byte *carpc_data;
extern byte *icone_data;
extern byte *souco_data;
extern byte *souri_data;
extern byte *templ_data;
extern byte *mursm_data;
extern byte *gauss_data;
extern byte *lutin_data;
extern byte *anima_data;
extern byte *anico_data;
extern byte *zones_data;
byte *seekToEntry(byte *bank, uint16 num, byte **end);
byte *seekToEntryW(byte *bank, uint16 num, byte **end);
uint16 loadFile(const char *filename, byte *buffer);
uint16 saveFile(char *filename, byte *buffer, uint16 size);
int16 loadFilesList(ResEntry_t *entries);
int16 loadStaticData(void);
int16 loadFond(void);
int16 loadSpritesData(void);
int16 loadPersData(void);
extern ResEntry_t res_texts[];
int16 loadVepciData(void);
extern ResEntry_t res_desci[];
int16 loadDesciData(void);
extern ResEntry_t res_diali[];
int16 loadDialiData(void);
} // End of namespace Chamber
#endif

1918
engines/chamber/room.cpp Normal file

File diff suppressed because it is too large Load Diff

237
engines/chamber/room.h Normal file
View File

@@ -0,0 +1,237 @@
/* 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 CHAMBER_ROOM_H
#define CHAMBER_ROOM_H
namespace Chamber {
#define SPOTFLG_1 0x01
#define SPOTFLG_2 0x02
#define SPOTFLG_8 0x08
#define SPOTFLG_10 0x10
#define SPOTFLG_20 0x20
#define SPOTFLG_40 0x40
#define SPOTFLG_80 0x80
/*static room object*/
/*TODO: manipulated from script, do not change*/
#include "common/pack-start.h"
typedef struct spot_t {
byte sx;
byte ex;
byte sy;
byte ey;
byte flags;
byte hint;
uint16 command;
} spot_t;
#include "common/pack-end.h"
#define PERSFLAGS 0xF0
#define PERSFLG_10 0x10
#define PERSFLG_20 0x20
#define PERSFLG_40 0x40
#define PERSFLG_80 0x80
/*person*/
/*TODO: manipulated from script, do not change*/
#include "common/pack-start.h"
typedef struct pers_t {
byte area; /*location*/
byte flags; /*flags in bits 7..4 and room index in bits 3..0*/
byte name; /*name index*/
byte index; /*animations index (in lutins_table) in bits 7..3 , spot index in bits 2..0*/
byte item; /*inventory item index (1-based)*/
} pers_t;
#include "common/pack-end.h"
#define ANIMFLG_USESPOT 0x80
typedef struct animdesc_t {
byte index; /*flag in bit 7, animation index in bits 6..0*/
union {
struct {
byte x, y;
} coords;
uint16 desc;
} params;
} animdesc_t;
typedef struct vortanims_t {
byte room;
animdesc_t field_1;
animdesc_t field_4;
animdesc_t field_7;
animdesc_t field_A;
} vortanims_t;
typedef struct turkeyanims_t {
byte room;
animdesc_t field_1;
animdesc_t field_4;
} turkeyanims_t;
extern byte scratch_mem1[8010];
extern byte *scratch_mem2;
extern rect_t room_bounds_rect;
extern byte last_object_hint;
extern byte object_hint;
extern byte command_hint;
extern byte last_command_hint;
extern uint16 next_protozorqs_ticks;
extern uint16 next_vorts_ticks;
extern uint16 next_vorts_cmd;
extern uint16 next_turkey_ticks;
extern uint16 next_turkey_cmd;
#define MAX_SPRITES 16
extern byte *sprites_list[MAX_SPRITES];
#define MAX_DOORS 5
extern byte *doors_list[MAX_DOORS];
extern byte zone_palette;
extern spot_t *zone_spots;
extern spot_t *zone_spots_end;
extern spot_t *zone_spots_cur;
extern vortanims_t vortsanim_list[];
extern vortanims_t *vortanims_ptr;
extern turkeyanims_t turkeyanim_list[];
extern turkeyanims_t *turkeyanims_ptr;
extern pers_t *aspirant_ptr;
extern spot_t *aspirant_spot;
extern spot_t *found_spot;
extern byte **spot_sprite;
extern byte *lutin_mem;
extern byte skip_zone_transition;
extern byte in_de_profundis;
extern byte zone_name;
extern byte room_hint_bar_width;
extern byte zone_spr_index;
extern byte zone_obj_count;
extern byte room_hint_bar_coords_x;
extern byte room_hint_bar_coords_y;
extern uint16 drops_cleanup_time;
extern const byte patrol_route[];
extern const byte *timed_seq_ptr;
typedef struct thewalldoor_t {
byte height;
byte width;
uint16 pitch;
uint16 offs;
byte *pixels;
} thewalldoor_t;
extern thewalldoor_t the_wall_doors[2];
int16 isInRect(byte x, byte y, rect_t *rect);
int16 isCursorInRect(rect_t *rect);
void selectSpotCursor(void);
void checkHotspots(byte m, byte v);
void animateSpot(const animdesc_t *info);
byte *loadPuzzlToScratch(byte index);
void drawObjectHint(void);
void showObjectHint(byte *target);
void drawCommandHint(void);
void showCommandHint(byte *target);
void drawCharacterSprite(byte spridx, byte x, byte y, byte *target);
char drawZoneAniSprite(rect_t *rect, uint16 index, byte *target);
void drawHintsAndCursor(byte *target);
void drawTheWallDoors(void);
void mergeSpritesData(byte *target, uint16 pitch, byte *source, uint16 w, uint16 h);
void mergeSpritesDataFlip(byte *target, uint16 pitch, byte *source, uint16 w, uint16 h);
void refreshSpritesData(void);
void blitSpritesToBackBuffer(void);
byte *backupSpotImage(spot_t *spot, byte **spotback, byte *buffer);
void backupSpotsImages(void);
void selectPalette(void);
void selectSpecificPalette(byte index);
byte findSpotByFlags(byte mask, byte value);
byte selectPerson(byte offset);
void findPerson(void);
void beforeChangeZone(byte index);
void drawRoomItemsIndicator(void);
void drawRoomStaticObject(byte *aptr, byte *rx, byte *ry, byte *rw, byte *rh);
void drawRoomStatics(void);
void redrawRoomStatics(byte index, byte y_step);
void drawPersons(void);
void refreshZone(void);
void changeZone(byte index);
void drawSpots(byte *target);
void animateSpots(byte *target);
byte findInitialSpot(void);
void animRoomDoorOpen(byte index);
void animRoomDoorClose(byte index);
uint16 getPuzzlSprite(byte index, byte x, byte y, uint16 *w, uint16 *h, uint16 *ofs);
void bounceCurrentItem(byte flags, byte y);
void backupScreenOfSpecialRoom(void);
void restoreScreenOfSpecialRoom(void);
void theWallPhase3_DoorOpen1(void);
void theWallPhase0_DoorOpen2(void);
void theWallPhase1_DoorClose1(void);
void theWallPhase2_DoorClose2(void);
void prepareAspirant(void);
void prepareVorts(void);
void prepareTurkey(void);
void updateProtozorqs(void);
void checkGameTimeLimit(void);
void cleanupDroppedItems(void);
void resetAllPersons(void);
} // End of namespace Chamber
#endif

View File

@@ -0,0 +1,699 @@
/* 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 "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/savegame.h"
#include "chamber/resdata.h"
#include "chamber/script.h"
#include "chamber/cga.h"
#include "chamber/room.h"
#include "chamber/dialog.h"
#include "chamber/room.h"
namespace Chamber {
#if 0
static const char restart_name[] = "CLEARx.BIN";
#ifdef VERSION_USA
static const char savegame_name[] = "SCENACx.BIN";
#else
static const char savegame_name[] = "SCENAx.BIN";
#endif
#endif
#ifdef VERSION_USA
#define CGA_SAVE_BEG_OFS 0x769B
#define CGA_SAVE_END_OFS 0x9EDA
#define CGA_SAVE_WORD_VARS_OFS 0x79C1
#define CGA_SAVE_BYTE_VARS_OFS 0x7B33
#define CGA_SAVE_INVENTORY_OFS 0x7762
#define CGA_SAVE_ZONES_OFS 0x7BA4
#define CGA_SAVE_PERS_OFS 0x78E2
#define CGA_SAVE_STACK_OFS 0x76DF
#define CGA_SAVE_SPRITES_OFS 0x5264
#define CGA_SAVE_SPRLIST_OFS 0x76AD
#define CGA_SAVE_SPRBUFF_OFS 0x4C68
#define CGA_SAVE_ARPLA_OFS 0x26F6
#define CGA_SAVE_SCRSTACK_OFS 0x76DF
#define CGA_SAVE_TEMPL_OFS 0x1AC7
#define CGA_SAVE_VORTANIMS_OFS 0xA7B7
#define CGA_SAVE_TURKEYANIMS_OFS 0xA8FC
#define CGA_SAVE_TIMEDSEQ_OFS 0xA96E
#else
#define CGA_SAVE_BEG_OFS 0x751E
#define CGA_SAVE_END_OFS 0x9D5D
#define CGA_SAVE_WORD_VARS_OFS 0x7844
#define CGA_SAVE_BYTE_VARS_OFS 0x79B6
#define CGA_SAVE_INVENTORY_OFS 0x75E5
#define CGA_SAVE_ZONES_OFS 0x7A27
#define CGA_SAVE_PERS_OFS 0x7765
#define CGA_SAVE_STACK_OFS 0x7562
#define CGA_SAVE_SPRITES_OFS 0x5264
#define CGA_SAVE_SPRLIST_OFS 0x7530
#define CGA_SAVE_SPRBUFF_OFS 0x4C68
#define CGA_SAVE_ARPLA_OFS 0x26F6
#define CGA_SAVE_SCRSTACK_OFS 0x7562
#define CGA_SAVE_TEMPL_OFS 0x182C
#define CGA_SAVE_VORTANIMS_OFS 0xA609
#define CGA_SAVE_TURKEYANIMS_OFS 0xA74E
#define CGA_SAVE_TIMEDSEQ_OFS 0xA7C0
#endif
#define SAVEADDR(value, base, nativesize, origsize, origbase) \
((value) ? LE16(((((byte*)(value)) - (byte*)(base)) / nativesize) * origsize + origbase) : 0)
#define LOADADDR(value, base, nativesize, origsize, origbase) \
((value) ? ((((LE16(value)) - (origbase)) / origsize) * nativesize + (byte*)base) : 0)
#define WRITE(buffer, size) \
wlen = write(f, buffer, size); if(wlen != size) goto error;
#define READ(buffer, size) \
rlen = read(f, buffer, size); if(rlen != size) goto error;
#if 0
int16 readSaveData(int16 f, int16 clean) {
int16 rlen;
uint16 zero = 0;
byte *p;
int16 i;
#define BYTES(buffer, size) READ(buffer, size)
#define UBYTE(variable) { byte temp_v; READ(&temp_v, 1); variable = temp_v; }
#define SBYTE(variable) { int8 temp_v; READ(&temp_v, 1); variable = temp_v; }
#define USHORT(variable) { uint16 temp_v; READ(&temp_v, 2); variable = temp_v; }
#define SSHORT(variable) { int16 temp_v; READ(&temp_v, 2); variable = temp_v; }
#define POINTER(variable, base, nativesize, origsize, origbase) \
{ int16 temp_v; READ(&temp_v, 2); variable = LOADADDR(temp_v, base, nativesize, origsize, origbase); }
/*script_vars pointers*/
POINTER(script_vars[ScrPool0_WordVars0], &script_word_vars, 2, 2, CGA_SAVE_WORD_VARS_OFS);
POINTER(script_vars[ScrPool1_WordVars1], &script_word_vars, 2, 2, CGA_SAVE_WORD_VARS_OFS);
POINTER(script_vars[ScrPool2_ByteVars], &script_byte_vars, 1, 1, CGA_SAVE_BYTE_VARS_OFS);
POINTER(script_vars[ScrPool3_CurrentItem], inventory_items, sizeof(item_t), sizeof(item_t), CGA_SAVE_INVENTORY_OFS);
POINTER(script_vars[ScrPool4_ZoneSpots], zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
POINTER(script_vars[ScrPool5_Persons], pers_list, 1, 1, CGA_SAVE_PERS_OFS);
POINTER(script_vars[ScrPool6_Inventory], inventory_items, sizeof(item_t), sizeof(item_t), CGA_SAVE_INVENTORY_OFS);
POINTER(script_vars[ScrPool7_Zapstiks], inventory_items, sizeof(item_t), sizeof(item_t), CGA_SAVE_INVENTORY_OFS);
POINTER(script_vars[ScrPool8_CurrentPers], pers_list, 1, 1, CGA_SAVE_PERS_OFS);
/* sprites_list */
for (i = 0; i < MAX_SPRITES; i++) {
POINTER(sprites_list[i], scratch_mem1, 1, 1, CGA_SAVE_SPRITES_OFS);
}
/* doors list */
for (i = 0; i < MAX_DOORS; i++) {
POINTER(doors_list[i], arpla_data, 1, 1, CGA_SAVE_ARPLA_OFS);
}
/* zone_spots */
POINTER((byte *)zone_spots, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
/* zone_spots_end */
POINTER((byte *)zone_spots_end, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
/* zone_spots_cur */
POINTER((byte *)zone_spots_cur, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
/* script_stack_ptr */
/*TODO: FIX ME: original stack works in reverse order (from higher address to lower)*/
POINTER((byte *)script_stack_ptr, script_stack, 1, 1, CGA_SAVE_SCRSTACK_OFS);
/* script_stack */
/*TODO: FIX ME: original stack works in reverse order (from higher address to lower)*/
for (i = 0; i < 5 * 2; i++) {
POINTER(script_stack[i], templ_data, 1, 1, CGA_SAVE_TEMPL_OFS);
}
/* padding */
USHORT(zero);
/* vort_ptr */
POINTER((byte *)vort_ptr, pers_list, 1, 1, CGA_SAVE_PERS_OFS);
/* vortanims_ptr */
POINTER((byte *)vortanims_ptr, vortsanim_list, 1, 1, CGA_SAVE_VORTANIMS_OFS);
/* turkeyanims_ptr */
POINTER((byte *)turkeyanims_ptr, turkeyanim_list, 1, 1, CGA_SAVE_TURKEYANIMS_OFS);
/* aspirant_ptr */
POINTER((byte *)aspirant_ptr, pers_list, 1, 1, CGA_SAVE_PERS_OFS);
/* aspirant_spot */
POINTER((byte *)aspirant_spot, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
/* found_spot */
POINTER((byte *)found_spot, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
/* spot_sprite */
POINTER((byte *)spot_sprite, sprites_list, sizeof(sprites_list[0]), 2, CGA_SAVE_SPRLIST_OFS);
/* timed_seq_ptr */
POINTER(timed_seq_ptr, patrol_route, 1, 1, CGA_SAVE_TIMEDSEQ_OFS);
/* keep_sp */
/* TODO: how to save it? but it's probably useless anyway */
USHORT(zero);
/* unused ptr to script code */
p = templ_data;
POINTER(p, templ_data, 1, 1, CGA_SAVE_TEMPL_OFS);
/* padding */
UBYTE(zero);
/* the wall doors state */
for (i = 0; i < 2; i++) {
thewalldoor_t *door = &the_wall_doors[i];
UBYTE(door->height);
UBYTE(door->width);
USHORT(door->pitch);
USHORT(door->offs);
POINTER(door->pixels, sprit_load_buffer, 1, 1, CGA_SAVE_SPRBUFF_OFS);
}
/* wait_delta */
UBYTE(wait_delta);
/* padding */
UBYTE(zero);
/* dirty_rects */
for (i = 0; i < MAX_DIRTY_RECT; i++) {
dirty_rect_t *dr = &dirty_rects[i];
UBYTE(dr->kind);
USHORT(dr->offs);
UBYTE(dr->height);
UBYTE(dr->width);
UBYTE(dr->y);
UBYTE(dr->x);
}
/* inventory_items */
for (i = 0; i < MAX_INV_ITEMS; i++) {
/*TODO: properly serialize this*/
BYTES(&inventory_items[i], sizeof(item_t));
}
/* room_hint_bar_coords_y */
UBYTE(room_hint_bar_coords_y);
/* room_hint_bar_coords_x */
UBYTE(room_hint_bar_coords_x);
/* padding */
USHORT(zero);
/* fight_pers_ofs */
/* NB! raw offset */
USHORT(fight_pers_ofs);
/* pers_list */
for (i = 0; i < PERS_MAX; i++) {
/*TODO: properly serialize this*/
BYTES(&pers_list[i], sizeof(pers_t));
}
/* drops_cleanup_time */
USHORT(drops_cleanup_time);
/* room_bounds_rect */
/*TODO: properly serialize this*/
BYTES(&room_bounds_rect, sizeof(rect_t));
/* last_object_hint */
UBYTE(last_object_hint);
/* object_hint */
UBYTE(object_hint);
/* command_hint */
UBYTE(command_hint);
/* zone_name */
UBYTE(zone_name);
/* room_hint_bar_width */
UBYTE(room_hint_bar_width);
/* last_command_hint */
UBYTE(last_command_hint);
/* zone_spr_index */
UBYTE(zone_spr_index);
/* zone_obj_count */
UBYTE(zone_obj_count);
/* padding */
USHORT(zero);
/* padding */
UBYTE(zero);
/* in_de_profundis */
UBYTE(in_de_profundis);
/* script_word_vars */
BYTES(&script_word_vars, sizeof(script_word_vars));
/* menu_commands_12 */
BYTES(menu_commands_12, sizeof(menu_commands_12));
/* menu_commands_22 */
BYTES(menu_commands_22, sizeof(menu_commands_22));
/* menu_commands_24 */
BYTES(menu_commands_24, sizeof(menu_commands_24));
/* menu_commands_23 */
BYTES(menu_commands_23, sizeof(menu_commands_23));
/* next_vorts_cmd */
USHORT(next_vorts_cmd);
/* next_vorts_ticks */
USHORT(next_vorts_ticks);
/* next_turkey_cmd */
USHORT(next_turkey_cmd);
/* next_turkey_ticks */
USHORT(next_turkey_ticks);
/* next_protozorqs_ticks */
USHORT(next_protozorqs_ticks);
/* padding */
for (i = 0; i < 7; i++) USHORT(zero);
/* script_byte_vars */
BYTES(&script_byte_vars, sizeof(script_byte_vars));
/* zones_data */
BYTES(zones_data, RES_ZONES_MAX);
if (clean == 0) {
/* screen data */
BYTES(backbuffer, 0x3FFF);
CGA_BackBufferToRealFull();
SelectPalette();
BYTES(backbuffer, 0x3FFF);
}
#undef BYTES
#undef UBYTE
#undef SBYTE
#undef USHORT
#undef SSHORT
#undef POINTER
return 0;
error:;
return 1;
}
int16 writeSaveData(int16 f, int16 clean) {
int16 wlen;
uint16 zero = 0;
byte *p;
int16 i;
#define BYTES(buffer, size) WRITE(buffer, size)
#define UBYTE(variable) { byte temp_v = variable; WRITE(&temp_v, 1); }
#define SBYTE(variable) { int8 temp_v = variable; WRITE(&temp_v, 1); }
#define USHORT(variable) { uint16 temp_v = variable; WRITE(&temp_v, 2); }
#define SSHORT(variable) { int16 temp_v = variable; WRITE(&temp_v, 2); }
#define POINTER(variable, base, nativesize, origsize, origbase) \
{ int16 temp_v = SAVEADDR(variable, base, nativesize, origsize, origbase); WRITE(&temp_v, 2); }
/*script_vars pointers*/
POINTER(script_vars[ScrPool0_WordVars0], &script_word_vars, 2, 2, CGA_SAVE_WORD_VARS_OFS);
POINTER(script_vars[ScrPool1_WordVars1], &script_word_vars, 2, 2, CGA_SAVE_WORD_VARS_OFS);
POINTER(script_vars[ScrPool2_ByteVars], &script_byte_vars, 1, 1, CGA_SAVE_BYTE_VARS_OFS);
POINTER(script_vars[ScrPool3_CurrentItem], inventory_items, sizeof(item_t), sizeof(item_t), CGA_SAVE_INVENTORY_OFS);
POINTER(script_vars[ScrPool4_ZoneSpots], zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
POINTER(script_vars[ScrPool5_Persons], pers_list, 1, 1, CGA_SAVE_PERS_OFS);
POINTER(script_vars[ScrPool6_Inventory], inventory_items, sizeof(item_t), sizeof(item_t), CGA_SAVE_INVENTORY_OFS);
POINTER(script_vars[ScrPool7_Zapstiks], inventory_items, sizeof(item_t), sizeof(item_t), CGA_SAVE_INVENTORY_OFS);
POINTER(script_vars[ScrPool8_CurrentPers], pers_list, 1, 1, CGA_SAVE_PERS_OFS);
/* sprites_list */
for (i = 0; i < MAX_SPRITES; i++) {
POINTER(sprites_list[i], scratch_mem1, 1, 1, CGA_SAVE_SPRITES_OFS);
}
/* doors list */
for (i = 0; i < MAX_DOORS; i++) {
POINTER(doors_list[i], arpla_data, 1, 1, CGA_SAVE_ARPLA_OFS);
}
/* zone_spots */
POINTER(zone_spots, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
/* zone_spots_end */
POINTER(zone_spots_end, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
/* zone_spots_cur */
POINTER(zone_spots_cur, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
/* script_stack_ptr */
/*TODO: FIX ME: original stack works in reverse order (from higher address to lower)*/
POINTER(script_stack_ptr, script_stack, 1, 1, CGA_SAVE_SCRSTACK_OFS);
/* script_stack */
/*TODO: FIX ME: original stack works in reverse order (from higher address to lower)*/
for (i = 0; i < 5 * 2; i++) {
POINTER(script_stack[i], templ_data, 1, 1, CGA_SAVE_TEMPL_OFS);
}
/* padding */
USHORT(zero);
/* vort_ptr */
POINTER(vort_ptr, pers_list, 1, 1, CGA_SAVE_PERS_OFS);
/* vortanims_ptr */
POINTER(vortanims_ptr, vortsanim_list, 1, 1, CGA_SAVE_VORTANIMS_OFS);
/* turkeyanims_ptr */
POINTER(turkeyanims_ptr, turkeyanim_list, 1, 1, CGA_SAVE_TURKEYANIMS_OFS);
/* aspirant_ptr */
POINTER(aspirant_ptr, pers_list, 1, 1, CGA_SAVE_PERS_OFS);
/* aspirant_spot */
POINTER(aspirant_spot, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
/* found_spot */
POINTER(found_spot, zones_data, 1, 1, CGA_SAVE_ZONES_OFS);
/* spot_sprite */
POINTER(spot_sprite, sprites_list, sizeof(sprites_list[0]), 2, CGA_SAVE_SPRLIST_OFS);
/* timed_seq_ptr */
POINTER(timed_seq_ptr, patrol_route, 1, 1, CGA_SAVE_TIMEDSEQ_OFS);
/* keep_sp */
/* TODO: how to save it? but it's probably useless anyway */
USHORT(zero);
/* unused ptr to script code */
p = templ_data;
POINTER(p, templ_data, 1, 1, CGA_SAVE_TEMPL_OFS);
/* padding */
UBYTE(zero);
/* the wall doors state */
for (i = 0; i < 2; i++) {
thewalldoor_t *door = &the_wall_doors[i];
UBYTE(door->height);
UBYTE(door->width);
USHORT(door->pitch);
USHORT(door->offs);
POINTER(door->pixels, sprit_load_buffer, 1, 1, CGA_SAVE_SPRBUFF_OFS);
}
/* wait_delta */
UBYTE(wait_delta);
/* padding */
UBYTE(zero);
/* dirty_rects */
for (i = 0; i < MAX_DIRTY_RECT; i++) {
dirty_rect_t *dr = &dirty_rects[i];
UBYTE(dr->kind);
USHORT(dr->offs);
UBYTE(dr->height);
UBYTE(dr->width);
UBYTE(dr->y);
UBYTE(dr->x);
}
/* inventory_items */
for (i = 0; i < MAX_INV_ITEMS; i++) {
/*TODO: properly serialize this*/
BYTES(&inventory_items[i], sizeof(item_t));
}
/* room_hint_bar_coords_y */
UBYTE(room_hint_bar_coords_y);
/* room_hint_bar_coords_x */
UBYTE(room_hint_bar_coords_x);
/* padding */
USHORT(zero);
/* fight_pers_ofs */
/* NB! raw offset */
USHORT(fight_pers_ofs);
/* pers_list */
for (i = 0; i < PERS_MAX; i++) {
/*TODO: properly serialize this*/
BYTES(&pers_list[i], sizeof(pers_t));
}
/* drops_cleanup_time */
USHORT(drops_cleanup_time);
/* room_bounds_rect */
/*TODO: properly serialize this*/
BYTES(&room_bounds_rect, sizeof(rect_t));
/* last_object_hint */
UBYTE(last_object_hint);
/* object_hint */
UBYTE(object_hint);
/* command_hint */
UBYTE(command_hint);
/* zone_name */
UBYTE(zone_name);
/* room_hint_bar_width */
UBYTE(room_hint_bar_width);
/* last_command_hint */
UBYTE(last_command_hint);
/* zone_spr_index */
UBYTE(zone_spr_index);
/* zone_obj_count */
UBYTE(zone_obj_count);
/* padding */
USHORT(zero);
/* padding */
UBYTE(zero);
/* in_de_profundis */
UBYTE(in_de_profundis);
/* script_word_vars */
BYTES(&script_word_vars, sizeof(script_word_vars));
/* menu_commands_12 */
BYTES(menu_commands_12, sizeof(menu_commands_12));
/* menu_commands_22 */
BYTES(menu_commands_22, sizeof(menu_commands_22));
/* menu_commands_24 */
BYTES(menu_commands_24, sizeof(menu_commands_24));
/* menu_commands_23 */
BYTES(menu_commands_23, sizeof(menu_commands_23));
/* next_vorts_cmd */
USHORT(next_vorts_cmd);
/* next_vorts_ticks */
USHORT(next_vorts_ticks);
/* next_turkey_cmd */
USHORT(next_turkey_cmd);
/* next_turkey_ticks */
USHORT(next_turkey_ticks);
/* next_protozorqs_ticks */
USHORT(next_protozorqs_ticks);
/* padding */
for (i = 0; i < 7; i++) USHORT(zero);
/* script_byte_vars */
BYTES(&script_byte_vars, sizeof(script_byte_vars));
/* zones_data */
BYTES(zones_data, RES_ZONES_MAX);
if (clean == 0) {
/* screen data */
BYTES(frontbuffer, 0x3FFF);
BYTES(backbuffer, 0x3FFF);
}
#undef BYTES
#undef UBYTE
#undef SBYTE
#undef USHORT
#undef SSHORT
#undef POINTER
return 0;
error:;
return 1;
}
#endif
int16 loadScena(void) {
warning("STUB: loadScena()");
return 1;
#if 0
int16 f;
int16 res;
script_byte_vars.game_paused = 1;
f = open(savegame_name, O_RDONLY | O_BINARY);
if (f == -1) {
script_byte_vars.game_paused = 0;
return 1; /*error*/
}
/*
Save format:
vars memory (751E-9D5D)
frontbuffer (0x3FFF bytes)
backbuffer (0x3FFF bytes)
*/
res = ReadSaveData(f, 0);
if (res == 0) {
/*re-initialize sprites list*/
BackupSpotsImages();
}
close(f);
script_byte_vars.game_paused = 0;
return res;
#endif
}
int16 saveScena(void) {
warning("STUB: saveScena()");
return 1;
#if 0
int16 f;
int16 res;
script_byte_vars.game_paused = 1;
BlitSpritesToBackBuffer();
command_hint = 100;
DrawCommandHint();
ShowCommandHint(frontbuffer);
f = open(savegame_name, O_CREAT | O_WRONLY | O_BINARY);
if (f == -1) {
script_byte_vars.game_paused = 0;
return 1; /*error*/
}
res = WriteSaveData(f, 0);
close(f);
if (res != 0)
unlink(savegame_name);
script_byte_vars.game_paused = 0;
return res;
#endif
}
void saveRestartGame(void) {
warning("STUB: saveRestartGame()");
#if 0
int16 f;
f = open(restart_name, O_CREAT | O_WRONLY | O_BINARY);
if (f == -1) {
return; /*error*/
}
WriteSaveData(f, 1);
close(f);
return;
#endif
}
//extern jmp_buf restart_jmp;
extern void askDisk2(void);
void restartGame(void) {
warning("STUB: restartGame()");
g_vm->_shouldRestart = true;
#if 0
int16 f;
int16 res;
for (;; askDisk2()) {
f = open(restart_name, O_RDONLY | O_BINARY);
if (f != -1) {
res = readSaveData(f, 1);
close(f);
if (res == 0)
break;
}
}
script_byte_vars.cur_spot_flags = 0xFF;
script_byte_vars.load_flag = 2;
#endif
}
} // End of namespace Chamber

View File

@@ -0,0 +1,34 @@
/* 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 CHAMBER_SAVEGAME_H
#define CHAMBER_SAVEGAME_H
namespace Chamber {
int16 loadScena(void);
int16 saveScena(void);
void saveRestartGame(void);
void restartGame(void);
} // End of namespace Chamber
#endif

4458
engines/chamber/script.cpp Normal file

File diff suppressed because it is too large Load Diff

245
engines/chamber/script.h Normal file
View File

@@ -0,0 +1,245 @@
/* 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 CHAMBER_SCRIPT_H
#define CHAMBER_SCRIPT_H
#include "chamber/common.h"
#include "chamber/room.h"
namespace Chamber {
enum ScriptPools {
kScrPool0_WordVars0,
kScrPool1_WordVars1,
kScrPool2_ByteVars,
kScrPool3_CurrentItem,
kScrPool4_ZoneSpots,
kScrPool5_Persons,
kScrPool6_Inventory,
kScrPool7_Zapstiks,
kScrPool8_CurrentPers,
kScrPools_MAX
};
/*Byte-packed, members accessed from script code by hardcoded offsets*/
typedef struct script_byte_vars_t {
byte zone_index; /* 0 */
byte zone_room; /* 1 */
byte last_door; /* 2 */
byte cur_spot_idx; /* 3 */
byte the_wall_phase; /* 4 */
byte prev_zone_index; /* 5 */
byte bvar_06; /* 6 */
byte bvar_07; /* 7 */
byte bvar_08; /* 8 */
byte bvar_09; /* 9 */
byte bvar_0A; /* A */
byte bvar_0B; /* B */
byte zone_area; /* C */
byte dead_flag; /* D */
volatile byte timer_ticks; /* E */
byte gauss_phase; /* F */
byte bvar_10; /* 10 */
byte rand_value; /* 11 */
byte load_flag; /* 12 */
byte spot_m; /* 13 */
byte spot_v; /* 14 */
byte bvar_15; /* 15 */
byte bvar_16; /* 16 */
byte bvar_17; /* 17 */
byte bvar_18; /* 18 */
byte bvar_19; /* 19 */
byte bvar_1A; /* 1A */
byte bvar_1B; /* 1B */
byte bvar_1C; /* 1C */
byte bvar_1D; /* 1D */
byte bvar_1E; /* 1E */
byte bvar_1F; /* 1F */
byte cur_pers; /* 20 */
byte used_commands; /* 21 */
byte tries_left; /* 22 */
byte inv_item_index; /* 23 */
byte bvar_24; /* 24 */
byte bvar_25; /* 25 */
byte bvar_26; /* 26 */
byte bvar_27; /* 27 */
byte bvar_28; /* 28 */
byte bvar_29; /* 29 */
byte bvar_2A; /* 2A */
byte hands; /* 2B */
byte check_used_commands; /* 2C */
byte bvar_2D; /* 2D */
byte palette_index; /* 2E */
byte bvar_2F; /* 2F */
byte bvar_30; /* 30 */
byte zapstiks_owned; /* 31 */
byte bvar_32; /* 32 */
byte bvar_33; /* 33 */
byte bvar_34; /* 34 */
byte skulls_submitted; /* 35 */
byte bvar_36; /* 36 */
byte bvar_37; /* 37 */
byte zone_area_copy; /* 38 */
byte aspirant_flags; /* 39 */
byte aspirant_pers_ofs;/* 3A */
byte steals_count; /* 3B */
byte fight_status; /* 3C */
byte extreme_violence; /* 3D */
byte trade_accepted; /* 3E */
byte bvar_3F; /* 3F */
byte bvar_40; /* 40 */
byte bvar_41; /* 41 */
byte bvar_42; /* 42 */
byte bvar_43; /* 43 */
byte dirty_rect_kind; /* 44 */
byte bvar_45; /* 45 */
byte bvar_46; /* 46 */
byte game_paused; /* 47 */
byte skull_trader_status;/* 48 */
byte cur_spot_flags; /* 49 */
byte bvar_4A; /* 4A */
byte bvar_4B; /* 4B */
byte bvar_4C; /* 4C */
byte bvar_4D; /* 4D */
byte bvar_4E; /* 4E */
byte bvar_4F; /* 4F */
byte bvar_50; /* 50 */
byte bvar_51; /* 51 */
byte bvar_52; /* 52 */
byte bvar_53; /* 53 */
byte bvar_54; /* 54 */
byte bvar_55; /* 55 */
byte bvar_56; /* 56 */
byte need_draw_spots; /* 57 */
byte bvar_58; /* 58 */
byte bvar_59; /* 59 */
byte psy_energy; /* 5A */
byte bvar_5B; /* 5B */
byte bvar_5C; /* 5C */
byte bvar_5D; /* 5D */
byte bvar_5E; /* 5E */
byte bvar_5F; /* 5F */
byte bvar_60; /* 60 */
byte bvar_61; /* 61 */
byte bvar_62; /* 62 */
byte bvar_63; /* 63 */
byte bvar_64; /* 64 */
byte bvar_65; /* 65 */
byte bvar_66; /* 66 */
byte bvar_67; /* 67 */
byte zapstik_stolen; /* 68 */
byte bvar_69; /* 69 */
byte bvar_6A; /* 6A */
byte bvar_6B; /* 6B */
byte bvar_6C; /* 6C */
byte bvar_6D[4]; /* 6D */
} script_byte_vars_t;
/*2-byte long vars, in BIG-endian order*/
typedef struct script_word_vars_t {
uint16 psi_cmds[6]; /* 0 */
uint16 wvar_0C; /* C */
uint16 wvar_0E; /* E */
uint16 timer_ticks2; /* 10 */
uint16 zone_obj_cmds[15 * 5]; /* 12 */
uint16 next_aspirant_cmd; /* A8 */
uint16 wvar_AA; /* AA */
uint16 wvar_AC; /* AC */
uint16 wvar_AE; /* AE */
uint16 wvar_B0; /* B0 */
uint16 wvar_B2; /* B2 */
uint16 wvar_B4; /* B4 */
uint16 next_protozorqs_cmd; /* B6 */
uint16 wvar_B8; /* B8 */
} script_word_vars_t;
extern void *script_vars[kScrPools_MAX];
extern script_word_vars_t script_word_vars;
extern script_byte_vars_t script_byte_vars;
/*Don't trade this item*/
#define ITEMFLG_DONTWANT 1
#define ITEMFLG_04 0x04
#define ITEMFLG_08 0x08
/*Skull Trader's item*/
#define ITEMFLG_TRADER 0x10
/*Aspirant's item*/
#define ITEMFLG_ASPIR 0x20
/*In a room?*/
#define ITEMFLG_ROOM 0x40
/*In pocket?*/
#define ITEMFLG_OWNED 0x80
/*TODO: manipulated from script, do not change*/
#include "common/pack-start.h"
typedef struct item_t {
byte flags;
byte area; /*item location*/
byte sprite; /*item sprite index*/
byte name; /*item name index (relative)*/
uint16 command; /*TODO: warning! in native format, check if never accessed from scripts*/
} item_t;
#include "common/pack-end.h"
#define MAX_INV_ITEMS 63
extern item_t inventory_items[MAX_INV_ITEMS];
#define PERS_MAX 41
extern pers_t pers_list[PERS_MAX];
extern byte *script_stack[5 * 2];
extern byte **script_stack_ptr;
extern pers_t *vort_ptr;
#define SPECIAL_COMMANDS_MAX 20
extern uint16 menu_commands_12[SPECIAL_COMMANDS_MAX];
extern uint16 menu_commands_22[SPECIAL_COMMANDS_MAX];
extern uint16 menu_commands_24[SPECIAL_COMMANDS_MAX];
extern uint16 menu_commands_23[SPECIAL_COMMANDS_MAX];
extern uint16 fight_pers_ofs;
extern byte wait_delta;
extern byte rand_seed;
byte getRand(void);
uint16 getRandW(void);
extern uint16 the_command;
byte *getScriptSubroutine(uint16 index);
uint16 runCommand(void);
uint16 runCommandKeepSp(void);
uint16 Swap16(uint16 x);
} // End of namespace Chamber
#endif

275
engines/chamber/scrvars.h Normal file
View File

@@ -0,0 +1,275 @@
/* 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 CHAMBER_SCRVARS_H
#define CHAMBER_SCRVARS_H
namespace Chamber {
script_byte_vars_t script_byte_vars = {
135, /* 0 */
0, /* 1 */
0, /* 2 */
0, /* 3 */
0, /* 4 */
0, /* 5 */
1, /* 6 */
0, /* 7 */
0, /* 8 */
0, /* 9 */
0, /* A */
0, /* B */
0, /* C */
0, /* D */
0, /* E */
0, /* F */
0, /* 10 */
0, /* 11 */
0, /* 12 */
0, /* 13 */
0, /* 14 */
0, /* 15 */
0, /* 16 */
0, /* 17 */
0, /* 18 */
0, /* 19 */
0, /* 1A */
0, /* 1B */
0, /* 1C */
0, /* 1D */
0, /* 1E */
0, /* 1F */
0, /* 20 */
0, /* 21 */
0, /* 22 */
0, /* 23 */
0xB, /* 24 */
0, /* 25 */
0, /* 26 */
0, /* 27 */
0, /* 28 */
0, /* 29 */
0, /* 2A */
0, /* 2B */
0, /* 2C */
0, /* 2D */
0, /* 2E */
0, /* 2F */
0, /* 30 */
0, /* 31 */
0, /* 32 */
0, /* 33 */
0, /* 34 */
0, /* 35 */
0, /* 36 */
0, /* 37 */
0, /* 38 */
0, /* 39 */
0, /* 3A */
0, /* 3B */
0, /* 3C */
0, /* 3D */
0, /* 3E */
0, /* 3F */
0, /* 40 */
0, /* 41 */
0, /* 42 */
0, /* 43 */
0, /* 44 */
0, /* 45 */
0, /* 46 */
1, /* 47 */
0, /* 48 */
0xFF, /* 49 */
0, /* 4A */
0, /* 4B */
0, /* 4C */
0, /* 4D */
0, /* 4E */
0, /* 4F */
0, /* 50 */
0, /* 51 */
0, /* 52 */
0, /* 53 */
2, /* 54 */
1, /* 55 */
0, /* 56 */
0, /* 57 */
0, /* 58 */
0, /* 59 */
63, /* 5A */
0, /* 5B */
0, /* 5C */
0, /* 5D */
0, /* 5E */
0, /* 5F */
0, /* 60 */
0, /* 61 */
1, /* 62 */
0, /* 63 */
0, /* 64 */
0, /* 65 */
0, /* 66 */
0, /* 67 */
0, /* 68 */
0, /* 69 */
0, /* 6A */
0, /* 6B */
0, /* 6C */
{0,0,0,0} /* 6D..70 */
};
script_word_vars_t script_word_vars = {
{BE(0x9007), BE(0x9007), BE(0x9007), BE(0x9007), BE(0x9007), BE(0x9007)}, /* 00 .. 0B */
BE(0), /* 0C */
BE(0), /* 0E */
BE(0), /* 10 */
{0}, /* 12 */
BE(0), /* A8 */
BE(0), /* AA */
BE(0), /* AC */
BE(0), /* AE */
BE(0), /* B0 */
BE(0), /* B2 */
BE(0), /* B4 */
BE(0), /* B6 */
BE(0) /* B8 */
};
item_t inventory_items[MAX_INV_ITEMS] = {
{0x00, 0, 26, 109, 0xC0D9}, /* 0 : SKULL */
{0x00, 0, 26, 109, 0xC0D9}, /* 1 : SKULL */
{0x00, 0, 26, 109, 0xC0D9}, /* 2 : SKULL */
{ITEMFLG_TRADER|ITEMFLG_08, 0, 26, 109, 0xC0D9}, /* 3 : SKULL */
{0x00, 0, 26, 109, 0xC0D9}, /* 4 : SKULL */
{0x00, 0, 32, 104, 0xC0ED}, /* 5 : ROPE */
{0x00, 0, 32, 104, 0xC0ED}, /* 6 : ROPE */
{0x00, 0, 32, 104, 0xC0ED}, /* 7 : ROPE */
{ITEMFLG_TRADER, 0, 32, 104, 0xC0ED}, /* 8 : ROPE */
{0x00, 0, 32, 104, 0xC0ED}, /* 9 : ROPE */
{0x00, 0, 33, 106, 0xC0EE}, /* 10 : STONE FLY */
{0x00, 0, 33, 106, 0xC0EE}, /* 11 : STONE FLY */
{0x00, 0, 33, 106, 0xC0EE}, /* 12 : STONE FLY */
{ITEMFLG_TRADER, 0, 33, 106, 0xC0EE}, /* 13 : STONE FLY */
{0x00, 0, 36, 107, 0xC0EC}, /* 14 : GOBLET */
{0x00, 0, 36, 107, 0xC0EC}, /* 15 : GOBLET */
{0x00, 0, 36, 107, 0xC0EC}, /* 16 : GOBLET */
{ITEMFLG_TRADER, 0, 36, 107, 0xC0EC}, /* 17 : GOBLET */
{0x00, 0, 37, 108, 0xC0D3}, /* 18 : DAGGER */
{0x00, 0, 37, 108, 0xC0D3}, /* 19 : DAGGER */
{0x00, 0, 37, 108, 0xC0D3}, /* 20 : DAGGER */
{ITEMFLG_TRADER, 0, 37, 108, 0xC0D3}, /* 21 : DAGGER */
{0x00, 0, 39, 105, 0xC0D6}, /* 22 : LANTERN */
{0x00, 0, 39, 105, 0xC0D6}, /* 23 : LANTERN */
{0x00, 0, 39, 105, 0xC0D6}, /* 24 : LANTERN */
{ITEMFLG_TRADER, 0, 39, 105, 0xC0D6}, /* 25 : LANTERN */
{ITEMFLG_DONTWANT, 0, 30, 136, 0xC126}, /* 26 : BLUE SPIDER */
{ITEMFLG_DONTWANT, 0, 30, 136, 0xC126}, /* 27 : BLUE SPIDER */
{ITEMFLG_DONTWANT, 0, 30, 136, 0xC126}, /* 28 : BLUE SPIDER */
{ITEMFLG_DONTWANT, 0, 30, 136, 0xC126}, /* 29 : BLUE SPIDER */
{ITEMFLG_DONTWANT, 0, 31, 135, 0xC126}, /* 30 : RED SPIDER */
{ITEMFLG_DONTWANT, 0, 31, 135, 0xC126}, /* 31 : RED SPIDER */
{ITEMFLG_DONTWANT, 0, 31, 135, 0xC126}, /* 32 : RED SPIDER */
{ITEMFLG_DONTWANT, 0, 31, 135, 0xC126}, /* 33 : RED SPIDER */
{ITEMFLG_DONTWANT, kAreaTheTwins, 38, 120, 0xC132}, /* 34 : DIE */
{ITEMFLG_DONTWANT, kAreaTheTwins, 38, 120, 0xC132}, /* 35 : DIE */
{ITEMFLG_DONTWANT, kAreaTheTwins, 38, 120, 0xC132}, /* 36 : DIE */
{ITEMFLG_DONTWANT, kAreaTheTwins, 38, 120, 0xC132}, /* 37 : DIE */
{0x00, 0, 28, 132, 0xC0EF}, /* 38 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 39 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 40 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 41 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 42 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 43 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 44 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 45 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 46 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 47 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 48 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 49 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 50 : ZAPSTIK */
{0x00, 0, 28, 132, 0xC0EF}, /* 51 : ZAPSTIK */
{0x00, 0, 106, 142, 0xC2C0}, /* 52 : MASK */
{0x00, 0, 34, 111, 0xC315}, /* 53 : WHISTLE */
{0x00, 0, 35, 110, 0xC27E}, /* 54 : EGG */
{0x00, 0, 40, 115, 0xC0D3}, /* 55 : SACRIFICIAL BLADE */
{ITEMFLG_ROOM, kAreaRefectory, 58, 117, 0xC127}, /* 56 : CHOPPER */
{ITEMFLG_TRADER|ITEMFLG_08|ITEMFLG_DONTWANT, 0, 59, 116, 0xC2BD}, /* 57 : STATUE OF ZORQ */
{0x00, 0, 105, 167, 0xC2BD}, /* 58 : STATUE OF SAURA */
{0x00, 0, 107, 118, 0xC245}, /* 59 : FLASK */
{0x00, 0, 108, 119, 0xC244}, /* 60 : BEAN */
{0x35, 0, 35, 110, 0xC27E}, /* 61 : EGG */
{0x35, 0, 35, 110, 0xC27E}, /* 62 : EGG */
};
pers_t pers_list[PERS_MAX] = {
{ 0, 0, 44, 16, 0}, /* 0 : VORT */
{ kAreaTheMastersOrbit3, 0, 49, 25, kItemRope1}, /* 1 : ASPIRANT */
{ 0, 0, 49, 89, kItemDagger1}, /* 2 : ASPIRANT */
{ 0, 0, 49, 153, kItemGoblet1}, /* 3 : ASPIRANT */
{ 0, 0, 49, 217, kItemFly1}, /* 4 : ASPIRANT */
{ kAreaPlacatingThePowers, 0, 51, 209, 0}, /* 5 : TURKEY */
{ kAreaAblutions, 0, 52, 186, 0}, /* 6 : PRIESTESS */
{ kAreaCell1, 0, 52, 202, 0}, /* 7 : PRIESTESS */
{ kAreaTheMastersOrbit1, 0, 42, 42, 0}, /* 8 : THE MASTER OF ORDEALS */
{ kAreaTheConcourse, 0, 43, 52, 0}, /* 9 : PROTOZORQ */
{ kAreaTheConcourse, 0, 43, 52, 0}, /* 10 : PROTOZORQ */
{ kAreaTheConcourse, 0, 43, 52, 0}, /* 11 : PROTOZORQ */
{ kAreaTheConcourse, 0, 43, 52, 0}, /* 12 : PROTOZORQ */
{ kAreaTheRing2, 0, 43, 52, 0}, /* 13 : PROTOZORQ */
{ kAreaTheMastersOrbit3, 0, 43, 52, 0}, /* 14 : PROTOZORQ */
{ kAreaTheMastersOrbit1, 0, 43, 52, 0}, /* 15 : PROTOZORQ */
{ kAreaTheMastersOrbit1, 0, 43, 53, 0}, /* 16 : PROTOZORQ */
{ kAreaTheMastersOrbit1, 0, 43, 54, 0}, /* 17 : PROTOZORQ */
{ kAreaTheMastersOrbit3, 0, 43, 53, 0}, /* 18 : PROTOZORQ */
{ kAreaDreamsOfSlime, 0, 43, 36, 0}, /* 19 : PROTOZORQ */
{ kAreaGuardRoom, 0, 43, 53, 0}, /* 20 : PROTOZORQ */
{ kAreaGuardRoom, 0, 43, 54, 0}, /* 21 : PROTOZORQ */
{ 0, 0, 43, 55, 0}, /* 22 : PROTOZORQ */
{ kAreaTheNoose, 0, 45, 130, 0}, /* 23 : THE POORMOUTH */
{kAreaInTheScorpionsPresence, 0, 46, 2, 0}, /* 24 : KHELE */
{ kAreaTheWeb, 0, 47, 194, 0}, /* 25 : THE MISTRESS */
{ kAreaThePowersOfTheAbyss, 0, 48, 138, 0}, /* 26 : DEILOS */
{ 99, 0, 53, 236, 0}, /* 27 : SCI FI */
{ kAreaCavern, 0, 54, 58, 0}, /* 28 : NORMAJEEN */
{ kAreaCavern, 0, 55, 65, 0}, /* 29 : ASH */
{ kAreaPlacatingThePowers, 0, 56, 125, 0}, /* 30 : MONKEY */
{ 0, 0, 57, 166, 0}, /* 31 : HARSSK */
{ 0, 0, 58, 175, 0}, /* 32 : ZORQ */
{ 0, 0, 59, 183, 0}, /* 33 : QRIICH */
{ 0, 0, 44, 8, 0}, /* 34 : VORT */
{ 0, 0, 44, 0, 0}, /* 35 : VORT */
{ kAreaPlacatingThePowers, 0, 52, 146, 0}, /* 36 : PRIESTESS */
{ kAreaTheThresholdOfTruth, 0, 52, 82, 0}, /* 37 : PRIESTESS */
{ 0, 0, 93, 243, 0}, /* 38 : CADAVER */
{ kAreaPlacatingThePowers, 0, 51, 209, 0}, /* 39 : TURKEY */
{ kAreaPlacatingThePowers, 0, 51, 209, 0}, /* 40 : TURKEY */
};
} // End of namespace Chamber
#endif

137
engines/chamber/sound.cpp Normal file
View File

@@ -0,0 +1,137 @@
/* 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 "audio/mixer.h"
#include "audio/softsynth/pcspk.h"
#include "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/sound.h"
#include "chamber/ifgm.h"
namespace Chamber {
typedef struct pcsample_t {
unsigned short repeat;
unsigned short delay1;
unsigned short delay1sweep;
unsigned short delay2;
unsigned short delay2sweep;
unsigned short freq;
unsigned short freqsweep;
} pcsample_t;
#define N(x) (0xF000|x)
pcsample_t pc_samples[] = {
{ 64, 32, 0, 32, 0, 256, 0},
{ 1, 2560, 0, 2560, 0, 0, 0},
{ 8, 2048, 0, 256, 256, 0, 0},
{ 11, 2816, N(256), 2816, N(256), 256, 256},
{ 1, 768, 0, 768, 0, 256, 0},
{128, 48, 1, 48, 0, 61440u, 1},
{128, 80, 1, 80, 0, 1, 1},
{128, 128, 1, 128, 1, 16, 1},
{128, 128, 1, 128, 0, 256, 16},
{128, 128, 1, 128, 1, 61440u, N(16)},
{ 16, 1536, 0, 1536, 0, 0, 0},
{ 3, 768, 0, 768, N(256), 256, N(256)},
};
#undef N
static void speakerPlay(pcsample_t *sample) {
uint16 rep, freq, delay1, delay2;
freq = sample->freq;
delay1 = sample->delay1;
delay2 = sample->delay2;
for (rep = 0; rep < sample->repeat; rep++) {
uint32 frequency = 1193180 / (freq ? freq : 1);
uint32 delayOff = delay1 * 16; // Around 335 ticks per second
uint32 delayOn = delay2 * 16;
g_vm->_speaker->playQueue(Audio::PCSpeaker::kWaveFormSilence, frequency, delayOff);
g_vm->_speaker->playQueue(Audio::PCSpeaker::kWaveFormSquare, frequency, delayOn);
if (sample->delay1sweep & 0xF000)
delay1 -= sample->delay1sweep & 0xFFF;
else
delay1 += sample->delay1sweep;
if (sample->delay2sweep & 0xF000)
delay2 -= sample->delay2sweep & 0xFFF;
else
delay2 += sample->delay2sweep;
if (sample->freqsweep & 0xF000)
freq -= sample->freqsweep & 0xFFF;
else
freq += sample->freqsweep;
}
}
#define kMaxSounds 12
byte sounds_table[kMaxSounds][3] = {
{20, 0, 0},
{19, 0, 0},
{176, 0, 0},
{144, 145, 146},
{243, 0, 0},
{18, 0, 0},
{149, 21, 0},
{27, 0, 0},
{241, 25, 151},
{22, 0, 0},
{224, 0, 0},
{31, 0, 0}
};
void playSound(byte index) {
int16 i;
if (IFGM_PlaySound(index))
return;
for (i = 0; i < kMaxSounds; i++) {
if (sounds_table[i][0] == index
|| sounds_table[i][1] == index
|| sounds_table[i][2] == index) {
speakerPlay(&pc_samples[i]);
break;
}
}
}
void ChamberEngine::initSound() {
// Setup mixer
syncSoundSettings();
_speaker = new Audio::PCSpeaker();
_speaker->init();
}
void ChamberEngine::deinitSound() {
delete g_vm->_speaker;
}
} // End of namespace Chamber

31
engines/chamber/sound.h Normal file
View File

@@ -0,0 +1,31 @@
/* 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 CHAMBER_SOUND_H
#define CHAMBER_SOUND_H
namespace Chamber {
void playSound(byte index);
} // End of namespace Chamber
#endif

64
engines/chamber/timer.cpp Normal file
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 "common/system.h"
#include "common/timer.h"
#include "chamber/chamber.h"
#include "chamber/common.h"
#include "chamber/cga.h"
#include "chamber/script.h"
#include "chamber/resdata.h"
namespace Chamber {
void animateGauss(byte *target) {
byte *sprite;
byte phase = getRand() % 4;
if (phase == script_byte_vars.gauss_phase)
phase = (phase + 1) % 4;
script_byte_vars.gauss_phase = phase;
sprite = gauss_data + 8 + phase * (8 * 30);
cga_Blit(sprite, 8, 8, 30, target, 80); /*draw to 0:4*/
}
void timerCallback(void *refCon) {
script_byte_vars.timer_ticks++;
if (!script_byte_vars.game_paused) {
if (script_byte_vars.timer_ticks % 16 == 0) {
script_word_vars.timer_ticks2 = Swap16(Swap16(script_word_vars.timer_ticks2) + 1);
#if 1
animateGauss(frontbuffer);
#endif
}
}
}
void initTimer(void) {
g_system->getTimerManager()->installTimerProc(&timerCallback, 1000000 / 16, NULL, "mainTimer");
}
void uninitTimer(void) {
g_system->getTimerManager()->removeTimerProc(&timerCallback);
}
} // End of namespace Chamber

32
engines/chamber/timer.h Normal file
View File

@@ -0,0 +1,32 @@
/* 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 CHAMBER_TIMER_H
#define CHAMBER_TIMER_H
namespace Chamber {
void initTimer(void);
void uninitTimer(void);
} // End of namespace Chamber
#endif