Add initial support for Personal Nightmare.
Thanks to dreammaster for file decompression and icon decoding code. NOTE: setjmp/longjmp code will require conversion for portability. svn-id: r39216
This commit is contained in:
parent
7bfab75a08
commit
2620d6836c
34 changed files with 4245 additions and 143 deletions
|
@ -182,6 +182,7 @@ AGOSEngine::AGOSEngine(OSystem *syst)
|
||||||
_lastVgaTick = 0;
|
_lastVgaTick = 0;
|
||||||
|
|
||||||
_marks = 0;
|
_marks = 0;
|
||||||
|
_scanFlag = false;
|
||||||
|
|
||||||
_scriptVar2 = 0;
|
_scriptVar2 = 0;
|
||||||
_runScriptReturn1 = 0;
|
_runScriptReturn1 = 0;
|
||||||
|
@ -288,11 +289,14 @@ AGOSEngine::AGOSEngine(OSystem *syst)
|
||||||
_firstTimeStruct = 0;
|
_firstTimeStruct = 0;
|
||||||
_pendingDeleteTimeEvent = 0;
|
_pendingDeleteTimeEvent = 0;
|
||||||
|
|
||||||
|
_initMouse = 0;
|
||||||
_leftButtonDown = 0;
|
_leftButtonDown = 0;
|
||||||
|
_mouseDown = 0;
|
||||||
_rightButtonDown = 0;
|
_rightButtonDown = 0;
|
||||||
_clickOnly = 0;
|
_clickOnly = 0;
|
||||||
_leftClick = 0;
|
|
||||||
_oneClick = 0;
|
_oneClick = 0;
|
||||||
|
_leftClick = 0;
|
||||||
|
_rightClick = 0;
|
||||||
_noRightClick = false;
|
_noRightClick = false;
|
||||||
|
|
||||||
_leftButton = 0;
|
_leftButton = 0;
|
||||||
|
@ -321,11 +325,14 @@ AGOSEngine::AGOSEngine(OSystem *syst)
|
||||||
_soundFileId = 0;
|
_soundFileId = 0;
|
||||||
_lastMusicPlayed = 0;
|
_lastMusicPlayed = 0;
|
||||||
_nextMusicToPlay = 0;
|
_nextMusicToPlay = 0;
|
||||||
|
_sampleEnd = 0;
|
||||||
|
_sampleWait = 0;
|
||||||
|
|
||||||
_showPreposition = 0;
|
_showPreposition = 0;
|
||||||
_showMessageFlag = 0;
|
_showMessageFlag = 0;
|
||||||
|
|
||||||
_newDirtyClip = false;
|
_newDirtyClip = false;
|
||||||
|
_wiped = false;
|
||||||
_copyScnFlag = 0;
|
_copyScnFlag = 0;
|
||||||
_vgaSpriteChanged = 0;
|
_vgaSpriteChanged = 0;
|
||||||
|
|
||||||
|
@ -341,6 +348,7 @@ AGOSEngine::AGOSEngine(OSystem *syst)
|
||||||
_curVgaFile1 = 0;
|
_curVgaFile1 = 0;
|
||||||
_curVgaFile2 = 0;
|
_curVgaFile2 = 0;
|
||||||
_curSfxFile = 0;
|
_curSfxFile = 0;
|
||||||
|
_curSfxFileSize = 0;
|
||||||
|
|
||||||
_syncCount = 0;
|
_syncCount = 0;
|
||||||
|
|
||||||
|
@ -683,6 +691,14 @@ static const uint16 initialVideoWindows_Common[20] = {
|
||||||
3, 3, 14, 127,
|
3, 3, 14, 127,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const uint16 initialVideoWindows_PN[20] = {
|
||||||
|
3, 0, 14, 136,
|
||||||
|
0, 0, 3, 136,
|
||||||
|
17, 0, 3, 136,
|
||||||
|
0, 0, 20, 200,
|
||||||
|
3, 2, 14, 129,
|
||||||
|
};
|
||||||
|
|
||||||
void AGOSEngine_PuzzlePack::setupGame() {
|
void AGOSEngine_PuzzlePack::setupGame() {
|
||||||
gss = &puzzlepack_settings;
|
gss = &puzzlepack_settings;
|
||||||
_numVideoOpcodes = 85;
|
_numVideoOpcodes = 85;
|
||||||
|
@ -836,6 +852,18 @@ void AGOSEngine_Elvira1::setupGame() {
|
||||||
AGOSEngine::setupGame();
|
AGOSEngine::setupGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::setupGame() {
|
||||||
|
gss = &simon1_settings;
|
||||||
|
_numVideoOpcodes = 57;
|
||||||
|
_vgaMemSize = 1000000;
|
||||||
|
_frameCount = 4;
|
||||||
|
_vgaBaseDelay = 1;
|
||||||
|
_vgaPeriod = 50;
|
||||||
|
_numVars = 256;
|
||||||
|
|
||||||
|
AGOSEngine::setupGame();
|
||||||
|
}
|
||||||
|
|
||||||
void AGOSEngine::setupGame() {
|
void AGOSEngine::setupGame() {
|
||||||
allocItemHeap();
|
allocItemHeap();
|
||||||
allocTablesHeap();
|
allocTablesHeap();
|
||||||
|
@ -870,6 +898,8 @@ void AGOSEngine::setupGame() {
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
|
if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
|
||||||
_videoWindows[i] = initialVideoWindows_Simon[i];
|
_videoWindows[i] = initialVideoWindows_Simon[i];
|
||||||
|
} else if (getGameType() == GType_PN) {
|
||||||
|
_videoWindows[i] = initialVideoWindows_PN[i];
|
||||||
} else {
|
} else {
|
||||||
_videoWindows[i] = initialVideoWindows_Common[i];
|
_videoWindows[i] = initialVideoWindows_Common[i];
|
||||||
}
|
}
|
||||||
|
@ -965,7 +995,7 @@ void AGOSEngine::pause() {
|
||||||
|
|
||||||
while (_pause && !shouldQuit()) {
|
while (_pause && !shouldQuit()) {
|
||||||
delay(1);
|
delay(1);
|
||||||
if (_keyPressed.keycode == Common::KEYCODE_p)
|
if (_keyPressed.keycode == Common::KEYCODE_PAUSE)
|
||||||
pauseEngine(false);
|
pauseEngine(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1037,7 +1067,6 @@ uint32 AGOSEngine::getTime() const {
|
||||||
return _system->getMillis() / 1000;
|
return _system->getMillis() / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AGOSEngine::syncSoundSettings() {
|
void AGOSEngine::syncSoundSettings() {
|
||||||
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
|
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
|
||||||
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
|
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "common/array.h"
|
#include "common/array.h"
|
||||||
#include "common/keyboard.h"
|
#include "common/keyboard.h"
|
||||||
#include "common/rect.h"
|
#include "common/rect.h"
|
||||||
|
#include "common/stack.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
||||||
#include "agos/animation.h"
|
#include "agos/animation.h"
|
||||||
|
@ -38,6 +39,9 @@
|
||||||
#include "agos/sound.h"
|
#include "agos/sound.h"
|
||||||
#include "agos/vga.h"
|
#include "agos/vga.h"
|
||||||
|
|
||||||
|
// TODO: Replace with more portable code
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
namespace AGOS {
|
namespace AGOS {
|
||||||
|
|
||||||
/* Enable and set to zone number number to dump */
|
/* Enable and set to zone number number to dump */
|
||||||
|
@ -72,6 +76,9 @@ struct HitArea {
|
||||||
Item *itemPtr;
|
Item *itemPtr;
|
||||||
uint16 verb;
|
uint16 verb;
|
||||||
uint16 priority;
|
uint16 priority;
|
||||||
|
|
||||||
|
// Personal Nightmare specific
|
||||||
|
uint16 msg1, msg2;
|
||||||
HitArea() { memset(this, 0, sizeof(*this)); }
|
HitArea() { memset(this, 0, sizeof(*this)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -127,6 +134,7 @@ struct AnimTable {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SIMONGameType {
|
enum SIMONGameType {
|
||||||
|
GType_PN = 0,
|
||||||
GType_ELVIRA1 = 1,
|
GType_ELVIRA1 = 1,
|
||||||
GType_ELVIRA2 = 2,
|
GType_ELVIRA2 = 2,
|
||||||
GType_WW = 3,
|
GType_WW = 3,
|
||||||
|
@ -167,7 +175,7 @@ class AGOSEngine : public Engine {
|
||||||
|
|
||||||
// Engine APIs
|
// Engine APIs
|
||||||
Common::Error init();
|
Common::Error init();
|
||||||
Common::Error go();
|
virtual Common::Error go();
|
||||||
virtual Common::Error run() {
|
virtual Common::Error run() {
|
||||||
Common::Error err;
|
Common::Error err;
|
||||||
err = init();
|
err = init();
|
||||||
|
@ -282,6 +290,7 @@ protected:
|
||||||
uint32 _lastVgaTick;
|
uint32 _lastVgaTick;
|
||||||
|
|
||||||
uint16 _marks;
|
uint16 _marks;
|
||||||
|
bool _scanFlag;
|
||||||
|
|
||||||
bool _scriptVar2;
|
bool _scriptVar2;
|
||||||
bool _runScriptReturn1;
|
bool _runScriptReturn1;
|
||||||
|
@ -346,7 +355,7 @@ protected:
|
||||||
int16 _scriptAdj1, _scriptAdj2;
|
int16 _scriptAdj1, _scriptAdj2;
|
||||||
|
|
||||||
uint16 _curWindow;
|
uint16 _curWindow;
|
||||||
WindowBlock *_textWindow;
|
WindowBlock *_inputWindow, *_textWindow;
|
||||||
|
|
||||||
Item *_subjectItem, *_objectItem;
|
Item *_subjectItem, *_objectItem;
|
||||||
Item *_currentPlayer;
|
Item *_currentPlayer;
|
||||||
|
@ -387,6 +396,7 @@ protected:
|
||||||
|
|
||||||
TimeEvent *_firstTimeStruct, *_pendingDeleteTimeEvent;
|
TimeEvent *_firstTimeStruct, *_pendingDeleteTimeEvent;
|
||||||
|
|
||||||
|
bool _initMouse;
|
||||||
Common::Point _mouse;
|
Common::Point _mouse;
|
||||||
Common::Point _mouseOld;
|
Common::Point _mouseOld;
|
||||||
|
|
||||||
|
@ -401,8 +411,10 @@ protected:
|
||||||
|
|
||||||
byte _leftButtonDown;
|
byte _leftButtonDown;
|
||||||
byte _leftButton, _leftButtonCount, _leftButtonOld;
|
byte _leftButton, _leftButtonCount, _leftButtonOld;
|
||||||
|
byte _mouseDown;
|
||||||
byte _rightButtonDown;
|
byte _rightButtonDown;
|
||||||
bool _clickOnly, _leftClick, _oneClick;
|
bool _clickOnly, _oneClick;
|
||||||
|
bool _leftClick, _rightClick;
|
||||||
bool _noRightClick;
|
bool _noRightClick;
|
||||||
|
|
||||||
Item *_dummyItem1;
|
Item *_dummyItem1;
|
||||||
|
@ -429,11 +441,11 @@ protected:
|
||||||
uint16 _soundFileId;
|
uint16 _soundFileId;
|
||||||
int16 _lastMusicPlayed;
|
int16 _lastMusicPlayed;
|
||||||
int16 _nextMusicToPlay;
|
int16 _nextMusicToPlay;
|
||||||
|
|
||||||
bool _showPreposition;
|
bool _showPreposition;
|
||||||
bool _showMessageFlag;
|
bool _showMessageFlag;
|
||||||
|
|
||||||
bool _newDirtyClip;
|
bool _newDirtyClip;
|
||||||
|
bool _wiped;
|
||||||
uint16 _copyScnFlag, _vgaSpriteChanged;
|
uint16 _copyScnFlag, _vgaSpriteChanged;
|
||||||
|
|
||||||
byte *_block, *_blockEnd;
|
byte *_block, *_blockEnd;
|
||||||
|
@ -443,7 +455,6 @@ protected:
|
||||||
|
|
||||||
byte *_curVgaFile1;
|
byte *_curVgaFile1;
|
||||||
byte *_curVgaFile2;
|
byte *_curVgaFile2;
|
||||||
byte *_curSfxFile;
|
|
||||||
|
|
||||||
uint16 _syncCount;
|
uint16 _syncCount;
|
||||||
|
|
||||||
|
@ -503,10 +514,12 @@ protected:
|
||||||
byte _stringReturnBuffer[2][180];
|
byte _stringReturnBuffer[2][180];
|
||||||
|
|
||||||
HitArea _hitAreas[250];
|
HitArea _hitAreas[250];
|
||||||
|
HitArea *_hitAreaList;
|
||||||
|
|
||||||
AnimTable _screenAnim1[90];
|
AnimTable _screenAnim1[90];
|
||||||
VgaPointersEntry _vgaBufferPointers[450];
|
VgaPointersEntry _vgaBufferPointers[450];
|
||||||
VgaSprite _vgaSprites[200];
|
VgaSprite _vgaSprites[200];
|
||||||
|
VgaSleepStruct _onStopTable[60];
|
||||||
VgaSleepStruct _waitEndTable[60];
|
VgaSleepStruct _waitEndTable[60];
|
||||||
VgaSleepStruct _waitSyncTable[60];
|
VgaSleepStruct _waitSyncTable[60];
|
||||||
|
|
||||||
|
@ -585,6 +598,10 @@ public:
|
||||||
AGOSEngine(OSystem *syst);
|
AGOSEngine(OSystem *syst);
|
||||||
virtual ~AGOSEngine();
|
virtual ~AGOSEngine();
|
||||||
|
|
||||||
|
byte *_curSfxFile;
|
||||||
|
uint32 _curSfxFileSize;
|
||||||
|
uint16 _sampleEnd, _sampleWait;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual uint16 to16Wrapper(uint value);
|
virtual uint16 to16Wrapper(uint value);
|
||||||
virtual uint16 readUint16Wrapper(const void *src);
|
virtual uint16 readUint16Wrapper(const void *src);
|
||||||
|
@ -598,17 +615,17 @@ protected:
|
||||||
void readGamePcText(Common::SeekableReadStream *in);
|
void readGamePcText(Common::SeekableReadStream *in);
|
||||||
virtual void readItemChildren(Common::SeekableReadStream *in, Item *item, uint tmp);
|
virtual void readItemChildren(Common::SeekableReadStream *in, Item *item, uint tmp);
|
||||||
void readItemFromGamePc(Common::SeekableReadStream *in, Item *item);
|
void readItemFromGamePc(Common::SeekableReadStream *in, Item *item);
|
||||||
void loadGamePcFile();
|
virtual void loadGamePcFile();
|
||||||
void readGamePcFile(Common::SeekableReadStream *in);
|
void readGamePcFile(Common::SeekableReadStream *in);
|
||||||
void decompressData(const char *srcName, byte *dst, uint32 offset, uint32 srcSize, uint32 dstSize);
|
void decompressData(const char *srcName, byte *dst, uint32 offset, uint32 srcSize, uint32 dstSize);
|
||||||
|
void decompressPN(Common::Stack<uint32> &dataList, uint8 *&dataOut, int &dataOutSize);
|
||||||
void loadOffsets(const char *filename, int number, uint32 &file, uint32 &offset, uint32 &compressedSize, uint32 &size);
|
void loadOffsets(const char *filename, int number, uint32 &file, uint32 &offset, uint32 &compressedSize, uint32 &size);
|
||||||
void loadSound(uint sound);
|
void loadSound(uint16 sound, int16 pan, int16 vol, uint16 type);
|
||||||
void loadSound(uint sound, int pan, int vol, uint type);
|
void loadSound(uint16 sound, uint16 freq, uint16 flags);
|
||||||
void loadVoice(uint speechId);
|
void loadVoice(uint speechId);
|
||||||
|
|
||||||
void loadSoundFile(const char *filename);
|
void loadSoundFile(const char *filename);
|
||||||
|
|
||||||
|
|
||||||
int getUserFlag(Item *item, int a);
|
int getUserFlag(Item *item, int a);
|
||||||
int getUserFlag1(Item *item, int a);
|
int getUserFlag1(Item *item, int a);
|
||||||
int getUserItem(Item *item, int n);
|
int getUserItem(Item *item, int n);
|
||||||
|
@ -638,6 +655,7 @@ protected:
|
||||||
|
|
||||||
/* used in debugger */
|
/* used in debugger */
|
||||||
void dumpAllSubroutines();
|
void dumpAllSubroutines();
|
||||||
|
void dumpAllVgaFiles();
|
||||||
void dumpSubroutines();
|
void dumpSubroutines();
|
||||||
void dumpSubroutine(Subroutine *sub);
|
void dumpSubroutine(Subroutine *sub);
|
||||||
void dumpSubroutineLine(SubroutineLine *sl, Subroutine *sub);
|
void dumpSubroutineLine(SubroutineLine *sl, Subroutine *sub);
|
||||||
|
@ -707,6 +725,8 @@ protected:
|
||||||
bool isBoxDead(uint hitarea);
|
bool isBoxDead(uint hitarea);
|
||||||
void undefineBox(uint hitarea);
|
void undefineBox(uint hitarea);
|
||||||
void defineBox(int id, int x, int y, int width, int height, int flags, int verb, Item *itemPtr);
|
void defineBox(int id, int x, int y, int width, int height, int flags, int verb, Item *itemPtr);
|
||||||
|
void defineBox(uint16 id, uint16 x, uint16 y, uint16 width, uint16 height, uint16 msg1, uint16 msg2, uint16 flags);
|
||||||
|
|
||||||
HitArea *findEmptyHitArea();
|
HitArea *findEmptyHitArea();
|
||||||
|
|
||||||
virtual void resetVerbs();
|
virtual void resetVerbs();
|
||||||
|
@ -749,6 +769,7 @@ protected:
|
||||||
virtual int weightOf(Item *x);
|
virtual int weightOf(Item *x);
|
||||||
void xPlace(Item *x, Item *y);
|
void xPlace(Item *x, Item *y);
|
||||||
|
|
||||||
|
void restoreMenu();
|
||||||
void drawMenuStrip(uint windowNum, uint menuNum);
|
void drawMenuStrip(uint windowNum, uint menuNum);
|
||||||
void lightMenuStrip(int a);
|
void lightMenuStrip(int a);
|
||||||
void unlightMenuStrip();
|
void unlightMenuStrip();
|
||||||
|
@ -826,7 +847,7 @@ protected:
|
||||||
void loadIconFile();
|
void loadIconFile();
|
||||||
void loadMenuFile();
|
void loadMenuFile();
|
||||||
|
|
||||||
bool processSpecialKeys();
|
virtual bool processSpecialKeys();
|
||||||
void hitarea_stuff_helper();
|
void hitarea_stuff_helper();
|
||||||
|
|
||||||
void permitInput();
|
void permitInput();
|
||||||
|
@ -835,12 +856,13 @@ protected:
|
||||||
void justifyStart();
|
void justifyStart();
|
||||||
void justifyOutPut(byte chr);
|
void justifyOutPut(byte chr);
|
||||||
|
|
||||||
void loadZone(uint16 zoneNum);
|
void loadZone(uint16 zoneNum, bool useError = true);
|
||||||
|
|
||||||
void animate(uint16 windowNum, uint16 zoneNum, uint16 vgaSpriteId, int16 x, int16 y, uint16 palette, bool vgaScript = false);
|
void animate(uint16 windowNum, uint16 zoneNum, uint16 vgaSpriteId, int16 x, int16 y, uint16 palette, bool vgaScript = false);
|
||||||
void setImage(uint16 vgaSpriteId, bool vgaScript = false);
|
void setImage(uint16 vgaSpriteId, bool vgaScript = false);
|
||||||
void setWindowImage(uint16 mode, uint16 vgaSpriteId);
|
void setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCase = false);
|
||||||
void setWindowImageEx(uint16 mode, uint16 vgaSpriteId);
|
virtual void setWindowImageEx(uint16 mode, uint16 vgaSpriteId);
|
||||||
|
void drawEdging();
|
||||||
|
|
||||||
void skipSpeech();
|
void skipSpeech();
|
||||||
|
|
||||||
|
@ -908,6 +930,17 @@ public:
|
||||||
void vc41_scrollLeft();
|
void vc41_scrollLeft();
|
||||||
void vc42_delayIfNotEQ();
|
void vc42_delayIfNotEQ();
|
||||||
|
|
||||||
|
// Video Script Opcodes, Personal Nightmare
|
||||||
|
void vc11_onStop();
|
||||||
|
void vc36_pause();
|
||||||
|
void vc39_volume();
|
||||||
|
void vc44_enableBox();
|
||||||
|
void vc45_disableBox();
|
||||||
|
void vc46_maxBox();
|
||||||
|
void vc48_specialEffect();
|
||||||
|
void vc50_setBox();
|
||||||
|
void vc55_scanFlag();
|
||||||
|
|
||||||
// Video Script Opcodes, Elvira 1
|
// Video Script Opcodes, Elvira 1
|
||||||
void vc17_waitEnd();
|
void vc17_waitEnd();
|
||||||
void vc22_setPaletteOld();
|
void vc22_setPaletteOld();
|
||||||
|
@ -1121,11 +1154,12 @@ protected:
|
||||||
void clearVideoBackGround(uint16 windowNum, uint16 color);
|
void clearVideoBackGround(uint16 windowNum, uint16 color);
|
||||||
|
|
||||||
void setPaletteSlot(uint16 srcOffs, uint8 dstOffs);
|
void setPaletteSlot(uint16 srcOffs, uint8 dstOffs);
|
||||||
|
void checkOnStopTable();
|
||||||
void checkWaitEndTable();
|
void checkWaitEndTable();
|
||||||
|
|
||||||
bool ifObjectHere(uint16 val);
|
virtual bool ifObjectHere(uint16 val);
|
||||||
bool ifObjectAt(uint16 a, uint16 b);
|
virtual bool ifObjectAt(uint16 a, uint16 b);
|
||||||
bool ifObjectState(uint16 a, int16 b);
|
virtual bool ifObjectState(uint16 a, int16 b);
|
||||||
|
|
||||||
bool isVgaQueueEmpty();
|
bool isVgaQueueEmpty();
|
||||||
void haltAnimation();
|
void haltAnimation();
|
||||||
|
@ -1152,7 +1186,7 @@ protected:
|
||||||
void colorBlock(WindowBlock *window, uint16 x, uint16 y, uint16 w, uint16 h);
|
void colorBlock(WindowBlock *window, uint16 x, uint16 y, uint16 w, uint16 h);
|
||||||
|
|
||||||
void restoreWindow(WindowBlock *window);
|
void restoreWindow(WindowBlock *window);
|
||||||
void restoreBlock(uint16 h, uint16 w, uint16 y, uint16 x);
|
void restoreBlock(uint16 x, uint16 y, uint16 w, uint16 h);
|
||||||
|
|
||||||
byte *getBackBuf();
|
byte *getBackBuf();
|
||||||
byte *getBackGround();
|
byte *getBackGround();
|
||||||
|
@ -1162,7 +1196,7 @@ protected:
|
||||||
|
|
||||||
bool decrunchFile(byte *src, byte *dst, uint32 size);
|
bool decrunchFile(byte *src, byte *dst, uint32 size);
|
||||||
void loadVGABeardFile(uint16 id);
|
void loadVGABeardFile(uint16 id);
|
||||||
void loadVGAVideoFile(uint16 id, uint8 type);
|
void loadVGAVideoFile(uint16 id, uint8 type, bool useError = true);
|
||||||
bool loadVGASoundFile(uint16 id, uint8 type);
|
bool loadVGASoundFile(uint16 id, uint8 type);
|
||||||
|
|
||||||
void openGameFile();
|
void openGameFile();
|
||||||
|
@ -1247,6 +1281,253 @@ protected:
|
||||||
virtual char *genSaveName(int slot);
|
virtual char *genSaveName(int slot);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AGOSEngine_PN : public AGOSEngine {
|
||||||
|
struct stackframe {
|
||||||
|
struct stackframe *nextframe;
|
||||||
|
int16 flag[6];
|
||||||
|
int16 param[8];
|
||||||
|
int16 classnum;
|
||||||
|
uint8 *linpos;
|
||||||
|
uint8 *lbase;
|
||||||
|
int16 ll;
|
||||||
|
int16 linenum;
|
||||||
|
int16 process;
|
||||||
|
jmp_buf *savearea;
|
||||||
|
stackframe() { memset(this, 0, sizeof(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
virtual Common::Error go();
|
||||||
|
void demoSeq();
|
||||||
|
void introSeq();
|
||||||
|
void setupBoxes();
|
||||||
|
public:
|
||||||
|
AGOSEngine_PN(OSystem *system);
|
||||||
|
~AGOSEngine_PN();
|
||||||
|
|
||||||
|
virtual void setupGame();
|
||||||
|
virtual void setupOpcodes();
|
||||||
|
virtual void setupVideoOpcodes(VgaOpcodeProc *op);
|
||||||
|
|
||||||
|
virtual void executeOpcode(int opcode);
|
||||||
|
|
||||||
|
int actCallD(int n);
|
||||||
|
|
||||||
|
void opn_opcode00();
|
||||||
|
void opn_opcode01();
|
||||||
|
void opn_opcode02();
|
||||||
|
void opn_opcode03();
|
||||||
|
void opn_opcode04();
|
||||||
|
void opn_opcode05();
|
||||||
|
void opn_opcode06();
|
||||||
|
void opn_opcode07();
|
||||||
|
void opn_opcode08();
|
||||||
|
void opn_opcode09();
|
||||||
|
void opn_opcode10();
|
||||||
|
void opn_opcode11();
|
||||||
|
void opn_opcode12();
|
||||||
|
void opn_opcode13();
|
||||||
|
void opn_opcode14();
|
||||||
|
void opn_opcode15();
|
||||||
|
void opn_opcode16();
|
||||||
|
void opn_opcode17();
|
||||||
|
void opn_opcode18();
|
||||||
|
void opn_opcode19();
|
||||||
|
void opn_opcode20();
|
||||||
|
void opn_opcode21();
|
||||||
|
void opn_opcode22();
|
||||||
|
void opn_opcode23();
|
||||||
|
void opn_opcode24();
|
||||||
|
void opn_opcode25();
|
||||||
|
void opn_opcode26();
|
||||||
|
void opn_opcode27();
|
||||||
|
void opn_opcode28();
|
||||||
|
void opn_opcode29();
|
||||||
|
void opn_opcode30();
|
||||||
|
void opn_opcode31();
|
||||||
|
void opn_opcode32();
|
||||||
|
void opn_opcode33();
|
||||||
|
void opn_opcode34();
|
||||||
|
void opn_opcode35();
|
||||||
|
void opn_opcode36();
|
||||||
|
void opn_opcode37();
|
||||||
|
void opn_opcode38();
|
||||||
|
void opn_opcode39();
|
||||||
|
void opn_opcode40();
|
||||||
|
void opn_opcode41();
|
||||||
|
void opn_opcode42();
|
||||||
|
void opn_opcode43();
|
||||||
|
void opn_opcode44();
|
||||||
|
void opn_opcode45();
|
||||||
|
void opn_opcode46();
|
||||||
|
void opn_opcode47();
|
||||||
|
void opn_opcode48();
|
||||||
|
void opn_opcode49();
|
||||||
|
void opn_opcode50();
|
||||||
|
void opn_opcode51();
|
||||||
|
void opn_opcode52();
|
||||||
|
void opn_opcode53();
|
||||||
|
void opn_opcode54();
|
||||||
|
void opn_opcode55();
|
||||||
|
void opn_opcode56();
|
||||||
|
void opn_opcode57();
|
||||||
|
void opn_opcode62();
|
||||||
|
void opn_opcode63();
|
||||||
|
|
||||||
|
// Video Script Opcodes, Personal Nightmare
|
||||||
|
void vc36_pause();
|
||||||
|
|
||||||
|
stackframe *_stackbase;
|
||||||
|
|
||||||
|
byte *_dataBase, *_textBase;
|
||||||
|
uint32 _dataBaseSize, _textBaseSize;
|
||||||
|
|
||||||
|
HitArea _invHitAreas[45];
|
||||||
|
|
||||||
|
char _buffer[80];
|
||||||
|
char _inputline[61];
|
||||||
|
char _saveFile[20];
|
||||||
|
char _sb[80];
|
||||||
|
uint8 _wordcp[7];
|
||||||
|
|
||||||
|
const char *_mouseString, *_mouseString1;
|
||||||
|
char _objectName1[15], _objectName2[15];
|
||||||
|
char _inMessage[20];
|
||||||
|
char _placeMessage[15];
|
||||||
|
uint8 _inputReady;
|
||||||
|
uint8 _inputting;
|
||||||
|
uint16 _intputCounter, _inputMax;
|
||||||
|
uint16 _mousePrintFG;
|
||||||
|
HitArea *_dragStore;
|
||||||
|
uint8 _hitCalled;
|
||||||
|
|
||||||
|
uint32 _quickptr[16];
|
||||||
|
uint16 _quickshort[12];
|
||||||
|
|
||||||
|
bool _noScanFlag;
|
||||||
|
char _keyboardBuffer[61];
|
||||||
|
|
||||||
|
uint16 _objects;
|
||||||
|
int16 _objectCountS;
|
||||||
|
|
||||||
|
int16 _bp;
|
||||||
|
int _xofs;
|
||||||
|
int16 _havinit;
|
||||||
|
uint16 _seed;
|
||||||
|
|
||||||
|
char *_curwrdptr;
|
||||||
|
char *_inpp;
|
||||||
|
int _fnst;
|
||||||
|
int _procnum;
|
||||||
|
int _linct;
|
||||||
|
int _linembr;
|
||||||
|
uint8 *_linebase;
|
||||||
|
uint8 *_workptr;
|
||||||
|
jmp_buf *_cjmpbuff;
|
||||||
|
jmp_buf _loadfail;
|
||||||
|
|
||||||
|
uint16 getptr(uint32 pos);
|
||||||
|
uint32 getlong(uint32 pos);
|
||||||
|
|
||||||
|
virtual void loadGamePcFile();
|
||||||
|
|
||||||
|
int bitextract(uint32 ptr, int offs);
|
||||||
|
int doaction();
|
||||||
|
int doline(int needsave);
|
||||||
|
int setposition(int process, int line);
|
||||||
|
int varval();
|
||||||
|
|
||||||
|
char *getMessage(char *msg, uint16 num);
|
||||||
|
void getResponse(uint16 charNum, uint16 objNum, uint16 &msgNum1, uint16 &msgNum2);
|
||||||
|
void getObjectName(char *v, uint16 x);
|
||||||
|
|
||||||
|
void processor();
|
||||||
|
void setbitf(uint32 ptr, int offs, int val);
|
||||||
|
void setqptrs();
|
||||||
|
void writeval(uint8 *ptr, int val);
|
||||||
|
|
||||||
|
void addstack(int type);
|
||||||
|
void dumpstack();
|
||||||
|
void junkstack();
|
||||||
|
void popstack(int type);
|
||||||
|
void funccpy(int *store);
|
||||||
|
void funcentry(int *storestore, int procn);
|
||||||
|
|
||||||
|
int findentry();
|
||||||
|
int findset();
|
||||||
|
int gvwrd(uint8 *wptr, int mask);
|
||||||
|
int samewrd(uint8 *w1, uint8 *w2, int ln);
|
||||||
|
int wrdmatch(uint8 *word1, int mask1, uint8 *word2, int mask2);
|
||||||
|
|
||||||
|
bool testContainer(uint16 a);
|
||||||
|
bool testObvious(uint16 a);
|
||||||
|
bool testSeen(uint16 a);
|
||||||
|
|
||||||
|
bool ifObjectInInv(uint16 a);
|
||||||
|
int inventoryOn(int val);
|
||||||
|
int inventoryOff();
|
||||||
|
void mouseHit();
|
||||||
|
void execMouseHit(HitArea *ha);
|
||||||
|
void hitBox1(HitArea *ha);
|
||||||
|
void hitBox2(HitArea *ha);
|
||||||
|
void hitBox3(HitArea *ha);
|
||||||
|
void hitBox4(HitArea *ha);
|
||||||
|
void hitBox5(HitArea *ha);
|
||||||
|
void hitBox6(HitArea *ha);
|
||||||
|
void hitBox7(HitArea *ha);
|
||||||
|
void hitBox8(HitArea *ha);
|
||||||
|
void hitBox9(HitArea *ha);
|
||||||
|
void hitBox11(HitArea *ha);
|
||||||
|
|
||||||
|
void drawIconHitBar();
|
||||||
|
void iconPage();
|
||||||
|
void printIcon(HitArea *ha, uint8 i, uint8 r);
|
||||||
|
|
||||||
|
bool badload(int8 errorNum);
|
||||||
|
int loadfl(char *name);
|
||||||
|
int savfl(char *name);
|
||||||
|
void getFilename();
|
||||||
|
void sysftodb();
|
||||||
|
void dbtosysf();
|
||||||
|
|
||||||
|
uint32 ftext(uint32 base, int n);
|
||||||
|
char *unctok(char *c, int n);
|
||||||
|
void uncomstr(char *c, uint32 x);
|
||||||
|
void patok(int n);
|
||||||
|
void pcf(uint8 ch);
|
||||||
|
void pcl(const char *s);
|
||||||
|
void pmesd(int n);
|
||||||
|
void plocd(int n, int m);
|
||||||
|
void pobjd(int n, int m);
|
||||||
|
void ptext(uint32 tptr);
|
||||||
|
|
||||||
|
virtual void clearVideoWindow(uint16 windowNum, uint16 color);
|
||||||
|
virtual void setWindowImageEx(uint16 mode, uint16 vga_res);
|
||||||
|
|
||||||
|
virtual bool ifObjectHere(uint16 val);
|
||||||
|
virtual bool ifObjectAt(uint16 a, uint16 b);
|
||||||
|
virtual bool ifObjectState(uint16 a, int16 b);
|
||||||
|
|
||||||
|
virtual void boxController(uint x, uint y, uint mode);
|
||||||
|
virtual void timerProc();
|
||||||
|
|
||||||
|
void addChar(uint8 chr);
|
||||||
|
void clearInputLine();
|
||||||
|
void handleKeyboard();
|
||||||
|
virtual void handleMouseMoved();
|
||||||
|
void interact(char *buffer, uint8 size);
|
||||||
|
|
||||||
|
virtual bool processSpecialKeys();
|
||||||
|
protected:
|
||||||
|
typedef void (AGOSEngine_PN::*OpcodeProcPN) ();
|
||||||
|
struct OpcodeEntryPN {
|
||||||
|
OpcodeProcPN proc;
|
||||||
|
const char *desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
const OpcodeEntryPN *_opcodesPN;
|
||||||
|
};
|
||||||
|
|
||||||
class AGOSEngine_Elvira1 : public AGOSEngine {
|
class AGOSEngine_Elvira1 : public AGOSEngine {
|
||||||
public:
|
public:
|
||||||
AGOSEngine_Elvira1(OSystem *system);
|
AGOSEngine_Elvira1(OSystem *system);
|
||||||
|
@ -1322,6 +1603,10 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
const OpcodeEntryElvira1 *_opcodesElvira1;
|
const OpcodeEntryElvira1 *_opcodesElvira1;
|
||||||
|
|
||||||
|
virtual void drawIcon(WindowBlock *window, uint icon, uint x, uint y);
|
||||||
|
|
||||||
|
virtual char *genSaveName(int slot);
|
||||||
};
|
};
|
||||||
|
|
||||||
class AGOSEngine_Elvira2 : public AGOSEngine_Elvira1 {
|
class AGOSEngine_Elvira2 : public AGOSEngine_Elvira1 {
|
||||||
|
|
|
@ -1767,6 +1767,107 @@ static const byte english_elvira1Font[] = {
|
||||||
0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x00,
|
0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const byte english_pnFont[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00,
|
||||||
|
0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x24, 0x7E, 0x24, 0x24, 0x7E, 0x24, 0x00,
|
||||||
|
0x00, 0x08, 0x3E, 0x28, 0x3E, 0x0A, 0x3E, 0x08,
|
||||||
|
0x00, 0x62, 0x64, 0x08, 0x10, 0x26, 0x46, 0x00,
|
||||||
|
0x00, 0x10, 0x28, 0x10, 0x2A, 0x44, 0x3A, 0x00,
|
||||||
|
0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x00,
|
||||||
|
0x00, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00,
|
||||||
|
0x00, 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, 0x00,
|
||||||
|
0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
|
||||||
|
0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00,
|
||||||
|
0x00, 0x3C, 0x46, 0x4A, 0x52, 0x62, 0x3C, 0x00,
|
||||||
|
0x00, 0x18, 0x28, 0x08, 0x08, 0x08, 0x3E, 0x00,
|
||||||
|
0x00, 0x3C, 0x42, 0x02, 0x3C, 0x40, 0x7E, 0x00,
|
||||||
|
0x00, 0x3C, 0x42, 0x0C, 0x02, 0x42, 0x3C, 0x00,
|
||||||
|
0x00, 0x08, 0x18, 0x28, 0x48, 0x7E, 0x08, 0x00,
|
||||||
|
0x00, 0x7E, 0x40, 0x7C, 0x02, 0x42, 0x3C, 0x00,
|
||||||
|
0x00, 0x3C, 0x40, 0x7C, 0x42, 0x42, 0x3C, 0x00,
|
||||||
|
0x00, 0x7E, 0x02, 0x04, 0x08, 0x10, 0x10, 0x00,
|
||||||
|
0x00, 0x3C, 0x42, 0x3C, 0x42, 0x42, 0x3C, 0x00,
|
||||||
|
0x00, 0x3C, 0x42, 0x42, 0x3E, 0x02, 0x3C, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00,
|
||||||
|
0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20,
|
||||||
|
0x00, 0x00, 0x04, 0x08, 0x10, 0x08, 0x04, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x10, 0x08, 0x04, 0x08, 0x10, 0x00,
|
||||||
|
0x00, 0x3C, 0x42, 0x04, 0x08, 0x00, 0x08, 0x00,
|
||||||
|
0x00, 0x3C, 0x4A, 0x56, 0x5E, 0x40, 0x3C, 0x00,
|
||||||
|
0x00, 0x3C, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x00,
|
||||||
|
0x00, 0x7C, 0x42, 0x7C, 0x42, 0x42, 0x7C, 0x00,
|
||||||
|
0x00, 0x3C, 0x42, 0x40, 0x40, 0x42, 0x3C, 0x00,
|
||||||
|
0x00, 0x78, 0x44, 0x42, 0x42, 0x44, 0x78, 0x00,
|
||||||
|
0x00, 0x7E, 0x40, 0x7C, 0x40, 0x40, 0x7E, 0x00,
|
||||||
|
0x00, 0x7E, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x00,
|
||||||
|
0x00, 0x3C, 0x42, 0x40, 0x4E, 0x42, 0x3C, 0x00,
|
||||||
|
0x00, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00,
|
||||||
|
0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00,
|
||||||
|
0x00, 0x02, 0x02, 0x02, 0x42, 0x42, 0x3C, 0x00,
|
||||||
|
0x00, 0x44, 0x48, 0x70, 0x48, 0x44, 0x42, 0x00,
|
||||||
|
0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7E, 0x00,
|
||||||
|
0x00, 0x42, 0x66, 0x5A, 0x42, 0x42, 0x42, 0x00,
|
||||||
|
0x00, 0x42, 0x62, 0x52, 0x4A, 0x46, 0x42, 0x00,
|
||||||
|
0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00,
|
||||||
|
0x00, 0x7C, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x00,
|
||||||
|
0x00, 0x3C, 0x42, 0x42, 0x52, 0x4A, 0x3C, 0x00,
|
||||||
|
0x00, 0x7C, 0x42, 0x42, 0x7C, 0x44, 0x42, 0x00,
|
||||||
|
0x00, 0x3C, 0x40, 0x3C, 0x02, 0x42, 0x3C, 0x00,
|
||||||
|
0x00, 0xFE, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,
|
||||||
|
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00,
|
||||||
|
0x00, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00,
|
||||||
|
0x00, 0x42, 0x42, 0x42, 0x42, 0x5A, 0x24, 0x00,
|
||||||
|
0x00, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x00,
|
||||||
|
0x00, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x00,
|
||||||
|
0x00, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x00,
|
||||||
|
0x00, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x0E, 0x00,
|
||||||
|
0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00,
|
||||||
|
0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00,
|
||||||
|
0x00, 0x10, 0x38, 0x54, 0x10, 0x10, 0x10, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
|
||||||
|
0x00, 0x1C, 0x22, 0x78, 0x20, 0x20, 0x7E, 0x00,
|
||||||
|
0x00, 0x00, 0x38, 0x04, 0x3C, 0x44, 0x3C, 0x00,
|
||||||
|
0x00, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x3C, 0x00,
|
||||||
|
0x00, 0x00, 0x1C, 0x20, 0x20, 0x20, 0x1C, 0x00,
|
||||||
|
0x00, 0x04, 0x04, 0x3C, 0x44, 0x44, 0x3C, 0x00,
|
||||||
|
0x00, 0x00, 0x38, 0x44, 0x78, 0x40, 0x3C, 0x00,
|
||||||
|
0x00, 0x0C, 0x10, 0x18, 0x10, 0x10, 0x10, 0x00,
|
||||||
|
0x00, 0x00, 0x3C, 0x44, 0x44, 0x3C, 0x04, 0x38,
|
||||||
|
0x00, 0x40, 0x40, 0x78, 0x44, 0x44, 0x44, 0x00,
|
||||||
|
0x00, 0x10, 0x00, 0x30, 0x10, 0x10, 0x38, 0x00,
|
||||||
|
0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x24, 0x18,
|
||||||
|
0x00, 0x20, 0x28, 0x30, 0x30, 0x28, 0x24, 0x00,
|
||||||
|
0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0C, 0x00,
|
||||||
|
0x00, 0x00, 0x68, 0x54, 0x54, 0x54, 0x54, 0x00,
|
||||||
|
0x00, 0x00, 0x78, 0x44, 0x44, 0x44, 0x44, 0x00,
|
||||||
|
0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00,
|
||||||
|
0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x40, 0x40,
|
||||||
|
0x00, 0x00, 0x3C, 0x44, 0x44, 0x3C, 0x04, 0x06,
|
||||||
|
0x00, 0x00, 0x1C, 0x20, 0x20, 0x20, 0x20, 0x00,
|
||||||
|
0x00, 0x00, 0x38, 0x40, 0x38, 0x04, 0x78, 0x00,
|
||||||
|
0x00, 0x10, 0x38, 0x10, 0x10, 0x10, 0x0C, 0x00,
|
||||||
|
0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00,
|
||||||
|
0x00, 0x00, 0x44, 0x44, 0x28, 0x28, 0x10, 0x00,
|
||||||
|
0x00, 0x00, 0x44, 0x54, 0x54, 0x54, 0x28, 0x00,
|
||||||
|
0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00,
|
||||||
|
0x00, 0x00, 0x44, 0x44, 0x44, 0x3C, 0x04, 0x38,
|
||||||
|
0x00, 0x00, 0x7C, 0x08, 0x10, 0x20, 0x7C, 0x00,
|
||||||
|
0x00, 0x0E, 0x08, 0x30, 0x08, 0x08, 0x0E, 0x00,
|
||||||
|
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
|
||||||
|
0x00, 0x70, 0x10, 0x0C, 0x10, 0x10, 0x70, 0x00,
|
||||||
|
0x00, 0x14, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x3C, 0x42, 0x99, 0xA1, 0xA1, 0x99, 0x42, 0x3C,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
|
void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
|
||||||
const byte *src;
|
const byte *src;
|
||||||
byte color, *dst;
|
byte color, *dst;
|
||||||
|
@ -1851,6 +1952,12 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
|
||||||
w = 6;
|
w = 6;
|
||||||
|
|
||||||
src = english_elvira1Font + (chr - 32) * 8;
|
src = english_elvira1Font + (chr - 32) * 8;
|
||||||
|
} else {
|
||||||
|
dst = (byte *)screen->pixels + y * _dxSurfacePitch + x + window->textColumnOffset;
|
||||||
|
h = 8;
|
||||||
|
w = 8;
|
||||||
|
|
||||||
|
src = english_pnFont + (chr - 32) * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
color = window->textColor;
|
color = window->textColor;
|
||||||
|
|
|
@ -610,13 +610,21 @@ void AGOSEngine::windowNewLine(WindowBlock *window) {
|
||||||
window->textColumnOffset = (getGameType() == GType_ELVIRA2) ? 4 : 0;
|
window->textColumnOffset = (getGameType() == GType_ELVIRA2) ? 4 : 0;
|
||||||
window->textLength = 0;
|
window->textLength = 0;
|
||||||
|
|
||||||
if (window->textRow == window->height) {
|
if (getGameType() == GType_PN) {
|
||||||
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 ||
|
window->textRow++;
|
||||||
getGameType() == GType_WW) {
|
if (window->textRow == window->height) {
|
||||||
windowScroll(window);
|
windowScroll(window);
|
||||||
|
window->textRow--;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
window->textRow++;
|
if (window->textRow == window->height) {
|
||||||
|
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 ||
|
||||||
|
getGameType() == GType_WW) {
|
||||||
|
windowScroll(window);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
window->textRow++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -474,6 +474,71 @@ get_out:
|
||||||
_litBoxFlag = 0;
|
_litBoxFlag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::handleMouseMoved() {
|
||||||
|
if (_mouseHideCount) {
|
||||||
|
CursorMan.showMouse(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CursorMan.showMouse(true);
|
||||||
|
_mouse = _eventMan->getMousePos();
|
||||||
|
|
||||||
|
if (_leftClick == true) {
|
||||||
|
_leftClick = false;
|
||||||
|
if (_dragFlag != 0) {
|
||||||
|
_hitCalled = 4;
|
||||||
|
} else if (_lockWord & 0x10) {
|
||||||
|
if (_oneClick != 0) {
|
||||||
|
_hitCalled = 2;
|
||||||
|
_oneClick = 0;
|
||||||
|
} else {
|
||||||
|
_oneClick++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_hitCalled = 1;
|
||||||
|
}
|
||||||
|
_mouseDown = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_rightClick == true) {
|
||||||
|
_rightClick = false;
|
||||||
|
if (_hitCalled == 0)
|
||||||
|
_hitCalled = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_mouse != _mouseOld)
|
||||||
|
_needHitAreaRecalc++;
|
||||||
|
|
||||||
|
if (_leftButton != 0) {
|
||||||
|
if (_mouseDown <= 20) {
|
||||||
|
_mouseDown++;
|
||||||
|
if (_mouseDown > 20) {
|
||||||
|
if (_lockWord & 0x10) {
|
||||||
|
if (_oneClick == 0)
|
||||||
|
_hitCalled = 3;
|
||||||
|
} else {
|
||||||
|
_hitCalled = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ((_lockWord & 0x10) && _oneClick != 0) {
|
||||||
|
_oneClick++;
|
||||||
|
if (_oneClick < 10) {
|
||||||
|
_hitCalled = 1;
|
||||||
|
_oneClick = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_wiped)
|
||||||
|
boxController(_mouse.x, _mouse.y, 0);
|
||||||
|
|
||||||
|
_mouseOld = _mouse;
|
||||||
|
drawMousePointer();
|
||||||
|
|
||||||
|
_needHitAreaRecalc = 0;
|
||||||
|
_litBoxFlag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void AGOSEngine::handleMouseMoved() {
|
void AGOSEngine::handleMouseMoved() {
|
||||||
uint x;
|
uint x;
|
||||||
|
|
||||||
|
@ -721,8 +786,15 @@ void AGOSEngine::drawMousePointer() {
|
||||||
} else {
|
} else {
|
||||||
const uint16 *src;
|
const uint16 *src;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
uint8 color;
|
||||||
|
|
||||||
const uint8 color = (getGameType() == GType_ELVIRA1) ? 15: 65;
|
if (getGameType() == GType_PN) {
|
||||||
|
color = (getPlatform() == Common::kPlatformPC) ? 15 : 14;
|
||||||
|
} else if (getGameType() == GType_ELVIRA1) {
|
||||||
|
color = 15;
|
||||||
|
} else {
|
||||||
|
color = 65;
|
||||||
|
}
|
||||||
memset(_mouseData, 0xFF, _maxCursorWidth * _maxCursorHeight);
|
memset(_mouseData, 0xFF, _maxCursorWidth * _maxCursorHeight);
|
||||||
|
|
||||||
if (getGameType() == GType_WW) {
|
if (getGameType() == GType_WW) {
|
||||||
|
|
|
@ -231,8 +231,10 @@ void AGOSEngine::dumpVideoScript(const byte *src, bool singeOpcode) {
|
||||||
strn = str = simon1_videoOpcodeNameTable[opcode];
|
strn = str = simon1_videoOpcodeNameTable[opcode];
|
||||||
} else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
|
} else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
|
||||||
strn = str = ww_videoOpcodeNameTable[opcode];
|
strn = str = ww_videoOpcodeNameTable[opcode];
|
||||||
} else {
|
} else if (getGameType() == GType_ELVIRA1) {
|
||||||
strn = str = elvira1_videoOpcodeNameTable[opcode];
|
strn = str = elvira1_videoOpcodeNameTable[opcode];
|
||||||
|
} else {
|
||||||
|
strn = str = pn_videoOpcodeNameTable[opcode];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strn == NULL) {
|
if (strn == NULL) {
|
||||||
|
@ -295,6 +297,24 @@ void AGOSEngine::dumpVgaScriptAlways(const byte *ptr, uint16 res, uint16 id) {
|
||||||
printf("; end\n");
|
printf("; end\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::dumpAllVgaFiles() {
|
||||||
|
uint8 start = (getGameType() == GType_PN) ? 0 : 2;
|
||||||
|
uint8 end = (getGameType() == GType_PN) ? 26 : 450;
|
||||||
|
|
||||||
|
for (int f = start; f < end; f++) {
|
||||||
|
uint16 zoneNum = (getGameType() == GType_PN) ? 0 : f;
|
||||||
|
loadZone(f, false);
|
||||||
|
|
||||||
|
VgaPointersEntry *vpe = &_vgaBufferPointers[zoneNum];
|
||||||
|
if (vpe->vgaFile1 != NULL) {
|
||||||
|
_curVgaFile1 = vpe->vgaFile1;
|
||||||
|
dumpVgaFile(_curVgaFile1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error("Complete");
|
||||||
|
}
|
||||||
|
|
||||||
void AGOSEngine_Feeble::dumpVgaFile(const byte *vga) {
|
void AGOSEngine_Feeble::dumpVgaFile(const byte *vga) {
|
||||||
const byte *pp;
|
const byte *pp;
|
||||||
const byte *p;
|
const byte *p;
|
||||||
|
|
|
@ -2324,6 +2324,79 @@ static const char *const puzzlepack_opcodeNameTable[256] = {
|
||||||
"BBBB|SET_COLOR",
|
"BBBB|SET_COLOR",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *const pn_videoOpcodeNameTable[] = {
|
||||||
|
/* 0 */
|
||||||
|
"x|RET",
|
||||||
|
"ddd|FADEOUT",
|
||||||
|
"d|CALL",
|
||||||
|
"ddddd|NEW_SPRITE",
|
||||||
|
/* 4 */
|
||||||
|
"ddd|FADEIN",
|
||||||
|
"vdj|IF_EQUAL",
|
||||||
|
"dj|IF_OBJECT_HERE",
|
||||||
|
"dj|IF_OBJECT_NOT_HERE",
|
||||||
|
/* 8 */
|
||||||
|
"ddj|IF_OBJECT_IS_AT",
|
||||||
|
"ddj|IF_OBJECT_STATE_IS",
|
||||||
|
"dddd|DRAW",
|
||||||
|
"d|ON_STOP",
|
||||||
|
/* 12 */
|
||||||
|
"|TEST_STOP",
|
||||||
|
"d|DELAY",
|
||||||
|
"d|SET_SPRITE_OFFSET_X",
|
||||||
|
"d|SET_SPRITE_OFFSET_Y",
|
||||||
|
/* 16 */
|
||||||
|
"|SYNC",
|
||||||
|
"d|WAIT_SYNC",
|
||||||
|
"d|WAIT_END",
|
||||||
|
"i|JUMP_REL",
|
||||||
|
/* 20 */
|
||||||
|
"|CHAIN_TO",
|
||||||
|
"dd|SET_REPEAT",
|
||||||
|
"i|END_REPEAT",
|
||||||
|
"d|SET_PALETTE",
|
||||||
|
/* 24 */
|
||||||
|
"d|SET_PRIORITY",
|
||||||
|
"diid|SET_SPRITE_XY",
|
||||||
|
"x|HALT_SPRITE",
|
||||||
|
"ddddd|SET_WINDOW",
|
||||||
|
/* 28 */
|
||||||
|
"|RESET",
|
||||||
|
"dddd|PLAY_SOUND",
|
||||||
|
"|STOP_ALL_SOUNDS",
|
||||||
|
"d|SET_FRAME_RATE",
|
||||||
|
/* 32 */
|
||||||
|
"d|SET_WINDOW",
|
||||||
|
"|SAVE_SCREEN",
|
||||||
|
"|MOUSE_ON",
|
||||||
|
"|MOUSE_OFF",
|
||||||
|
/* 36 */
|
||||||
|
"|PAUSE",
|
||||||
|
"d|VC_37",
|
||||||
|
"dd|CLEAR_WINDOW",
|
||||||
|
"d|SET_VOLUME",
|
||||||
|
/* 40 */
|
||||||
|
"dd|SET_WINDOW_IMAGE",
|
||||||
|
"dd|POKE_PALETTE",
|
||||||
|
"|VC_42",
|
||||||
|
"|VC_43",
|
||||||
|
/* 44 */
|
||||||
|
"d|ENABLE_BOX",
|
||||||
|
"d|DISABLE_BOX",
|
||||||
|
"d|MAX_BOX",
|
||||||
|
"dd|VC_47",
|
||||||
|
/* 48 */
|
||||||
|
"dd|SPEC_EFFECT",
|
||||||
|
"|VC_49",
|
||||||
|
"ddddddddd|SET_BOX",
|
||||||
|
"v|IF_VAR_NOT_ZERO",
|
||||||
|
/* 52 */
|
||||||
|
"vd|SET_VAR",
|
||||||
|
"vd|ADD_VAR",
|
||||||
|
"vd|SUB_VAR",
|
||||||
|
"|SCAN_FLAGS",
|
||||||
|
};
|
||||||
|
|
||||||
const char *const elvira1_videoOpcodeNameTable[] = {
|
const char *const elvira1_videoOpcodeNameTable[] = {
|
||||||
/* 0 */
|
/* 0 */
|
||||||
"x|RET",
|
"x|RET",
|
||||||
|
|
|
@ -65,6 +65,7 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const PlainGameDescriptor simonGames[] = {
|
static const PlainGameDescriptor simonGames[] = {
|
||||||
|
{"pn", "Personal Nightmare"},
|
||||||
{"elvira1", "Elvira - Mistress of the Dark"},
|
{"elvira1", "Elvira - Mistress of the Dark"},
|
||||||
{"elvira2", "Elvira II - The Jaws of Cerberus"},
|
{"elvira2", "Elvira II - The Jaws of Cerberus"},
|
||||||
{"waxworks", "Waxworks"},
|
{"waxworks", "Waxworks"},
|
||||||
|
@ -132,6 +133,9 @@ bool AgosMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGame
|
||||||
bool res = true;
|
bool res = true;
|
||||||
|
|
||||||
switch (gd->gameType) {
|
switch (gd->gameType) {
|
||||||
|
case AGOS::GType_PN:
|
||||||
|
*engine = new AGOS::AGOSEngine_PN(syst);
|
||||||
|
break;
|
||||||
case AGOS::GType_ELVIRA1:
|
case AGOS::GType_ELVIRA1:
|
||||||
*engine = new AGOS::AGOSEngine_Elvira1(syst);
|
*engine = new AGOS::AGOSEngine_Elvira1(syst);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -26,6 +26,93 @@
|
||||||
namespace AGOS {
|
namespace AGOS {
|
||||||
|
|
||||||
static const AGOSGameDescription gameDescriptions[] = {
|
static const AGOSGameDescription gameDescriptions[] = {
|
||||||
|
// Personal Nightmare 1.1 - English Amiga
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"pn",
|
||||||
|
"Floppy",
|
||||||
|
|
||||||
|
{
|
||||||
|
{ "icon.tmp", GAME_ICONFILE, "cd94091218ac2c46918fd3c0cbd81d5e", -1},
|
||||||
|
{ "night.dbm", GAME_BASEFILE, "712c445d8e938956403a759978eab01b", -1},
|
||||||
|
{ "night.txt", GAME_TEXTFILE, "52630ad100f473a2cdc7c699536d6730", -1},
|
||||||
|
{ NULL, 0, NULL, 0}
|
||||||
|
},
|
||||||
|
Common::EN_ANY,
|
||||||
|
Common::kPlatformAmiga,
|
||||||
|
ADGF_NO_FLAGS
|
||||||
|
},
|
||||||
|
|
||||||
|
GType_PN,
|
||||||
|
GID_PN,
|
||||||
|
GF_OLD_BUNDLE | GF_CRUNCHED | GF_PLANAR
|
||||||
|
},
|
||||||
|
|
||||||
|
// Personal Nightmare - English Atari ST Floppy Demo
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"pn",
|
||||||
|
"Demo",
|
||||||
|
|
||||||
|
{
|
||||||
|
{ "01.IN", 0, "23a4c8c4c9ac460fee7281080b5274e3", 756},
|
||||||
|
{ "02.IN", 0, "31be87808826538f0c0caebd5fedd48f", 73100},
|
||||||
|
{ "03.IN", 0, "0e125f3df4e4b800936ebdcc8dc96060", 101664},
|
||||||
|
{ NULL, 0, NULL, 0}
|
||||||
|
},
|
||||||
|
Common::EN_ANY,
|
||||||
|
Common::kPlatformAtariST,
|
||||||
|
ADGF_DEMO
|
||||||
|
},
|
||||||
|
|
||||||
|
GType_PN,
|
||||||
|
GID_PN,
|
||||||
|
GF_OLD_BUNDLE | GF_CRUNCHED | GF_PLANAR | GF_DEMO
|
||||||
|
},
|
||||||
|
|
||||||
|
// Personal Nightmare 1.1 - English AtariST Floppy
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"pn",
|
||||||
|
"Floppy",
|
||||||
|
|
||||||
|
{
|
||||||
|
{ "night.dbm", GAME_BASEFILE, "712c445d8e938956403a759978eab01b", -1},
|
||||||
|
{ "night.txt", GAME_TEXTFILE, "52630ad100f473a2cdc7c699536d6730", -1},
|
||||||
|
{ NULL, 0, NULL, 0}
|
||||||
|
},
|
||||||
|
Common::EN_ANY,
|
||||||
|
Common::kPlatformAtariST,
|
||||||
|
ADGF_NO_FLAGS
|
||||||
|
},
|
||||||
|
|
||||||
|
GType_PN,
|
||||||
|
GID_PN,
|
||||||
|
GF_OLD_BUNDLE | GF_CRUNCHED | GF_PLANAR
|
||||||
|
},
|
||||||
|
|
||||||
|
// Personal Nightmare 1.1c - English DOS Floppy
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"pn",
|
||||||
|
"Floppy",
|
||||||
|
|
||||||
|
{
|
||||||
|
{ "icon.out", GAME_ICONFILE, "40d8347c3154bfa8b642d6860a4b9481", -1},
|
||||||
|
{ "night.dbm", GAME_BASEFILE, "177311ae059243f6a2740e950585d786", -1},
|
||||||
|
{ "night.txt", GAME_TEXTFILE, "861fc1fa0864eef585f5865dee52e325", -1},
|
||||||
|
{ NULL, 0, NULL, 0}
|
||||||
|
},
|
||||||
|
Common::EN_ANY,
|
||||||
|
Common::kPlatformPC,
|
||||||
|
ADGF_NO_FLAGS
|
||||||
|
},
|
||||||
|
|
||||||
|
GType_PN,
|
||||||
|
GID_PN,
|
||||||
|
GF_OLD_BUNDLE | GF_CRUNCHED | GF_PLANAR
|
||||||
|
},
|
||||||
|
|
||||||
// Elvira 1 - English Amiga Floppy Demo
|
// Elvira 1 - English Amiga Floppy Demo
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|
|
@ -185,14 +185,13 @@ void AGOSEngine::restartAnimation() {
|
||||||
if (!(_lockWord & 0x10))
|
if (!(_lockWord & 0x10))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_window4Flag = 2;
|
if (getGameType() != GType_PN) {
|
||||||
|
_window4Flag = 2;
|
||||||
setMoveRect(0, 0, 224, 127);
|
setMoveRect(0, 0, 224, 127);
|
||||||
displayScreen();
|
displayScreen();
|
||||||
|
}
|
||||||
|
|
||||||
_lockWord &= ~0x10;
|
_lockWord &= ~0x10;
|
||||||
|
|
||||||
// Check picture queue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine::addVgaEvent(uint16 num, uint8 type, const byte *codePtr, uint16 curSprite, uint16 curZoneNum) {
|
void AGOSEngine::addVgaEvent(uint16 num, uint8 type, const byte *codePtr, uint16 curSprite, uint16 curZoneNum) {
|
||||||
|
@ -520,6 +519,9 @@ void AGOSEngine::delay(uint amount) {
|
||||||
setBitFlag(92, false);
|
setBitFlag(92, false);
|
||||||
_rightButtonDown++;
|
_rightButtonDown++;
|
||||||
break;
|
break;
|
||||||
|
case Common::EVENT_RBUTTONUP:
|
||||||
|
_rightClick = true;
|
||||||
|
break;
|
||||||
case Common::EVENT_RTL:
|
case Common::EVENT_RTL:
|
||||||
case Common::EVENT_QUIT:
|
case Common::EVENT_QUIT:
|
||||||
return;
|
return;
|
||||||
|
@ -611,6 +613,45 @@ void AGOSEngine_Feeble::timerProc() {
|
||||||
_lockWord &= ~2;
|
_lockWord &= ~2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::timerProc() {
|
||||||
|
if (_lockWord & 0x80E9 || _lockWord & 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_syncCount++;
|
||||||
|
|
||||||
|
_lockWord |= 2;
|
||||||
|
|
||||||
|
_sound->handleSound();
|
||||||
|
handleMouseMoved();
|
||||||
|
handleKeyboard();
|
||||||
|
|
||||||
|
if (!(_lockWord & 0x10)) {
|
||||||
|
if (_sampleWait) {
|
||||||
|
_vgaCurSpriteId = 0xFFFF;
|
||||||
|
vc15_sync();
|
||||||
|
_sampleWait = false;
|
||||||
|
}
|
||||||
|
if (_sampleEnd) {
|
||||||
|
_vgaCurSpriteId = 0xFFFE;
|
||||||
|
vc15_sync();
|
||||||
|
_sampleEnd = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
processVgaEvents();
|
||||||
|
processVgaEvents();
|
||||||
|
_cepeFlag ^= 1;
|
||||||
|
if (!_cepeFlag)
|
||||||
|
processVgaEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_displayScreen) {
|
||||||
|
displayScreen();
|
||||||
|
_displayScreen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lockWord &= ~2;
|
||||||
|
}
|
||||||
|
|
||||||
void AGOSEngine::timerProc() {
|
void AGOSEngine::timerProc() {
|
||||||
if (_lockWord & 0x80E9 || _lockWord & 2)
|
if (_lockWord & 0x80E9 || _lockWord & 2)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -928,6 +928,12 @@ void AGOSEngine::drawImage(VC10_state *state) {
|
||||||
|
|
||||||
_window4Flag = 1;
|
_window4Flag = 1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
state->surf_addr = (byte *)screen->pixels;
|
||||||
|
state->surf_pitch = _screenWidth;
|
||||||
|
|
||||||
|
xoffs = (vlut[0] * 2 + state->x) * 8;
|
||||||
|
yoffs = vlut[1] + state->y;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->surf_addr += xoffs + yoffs * state->surf_pitch;
|
state->surf_addr += xoffs + yoffs * state->surf_pitch;
|
||||||
|
@ -1057,7 +1063,7 @@ void AGOSEngine::animate(uint16 windowNum, uint16 zoneNum, uint16 vgaSpriteId, i
|
||||||
vsp->y = y;
|
vsp->y = y;
|
||||||
vsp->x = x;
|
vsp->x = x;
|
||||||
vsp->image = 0;
|
vsp->image = 0;
|
||||||
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW)
|
if (getGameType() == GType_PN || getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW)
|
||||||
vsp->palette = 0;
|
vsp->palette = 0;
|
||||||
else
|
else
|
||||||
vsp->palette = palette;
|
vsp->palette = palette;
|
||||||
|
@ -1168,7 +1174,7 @@ void AGOSEngine::setImage(uint16 vgaSpriteId, bool vgaScript) {
|
||||||
uint16 count;
|
uint16 count;
|
||||||
const byte *vc_ptr_org;
|
const byte *vc_ptr_org;
|
||||||
|
|
||||||
zoneNum = vgaSpriteId / 100;
|
zoneNum = (getGameType() == GType_PN) ? 0 : vgaSpriteId / 100;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
vpe = &_vgaBufferPointers[zoneNum];
|
vpe = &_vgaBufferPointers[zoneNum];
|
||||||
|
@ -1185,6 +1191,7 @@ void AGOSEngine::setImage(uint16 vgaSpriteId, bool vgaScript) {
|
||||||
_noOverWrite = 0xFFFF;
|
_noOverWrite = 0xFFFF;
|
||||||
} else {
|
} else {
|
||||||
_curSfxFile = vpe->sfxFile;
|
_curSfxFile = vpe->sfxFile;
|
||||||
|
_curSfxFileSize = vpe->sfxFileEnd - vpe->sfxFile;
|
||||||
_zoneNumber = zoneNum;
|
_zoneNumber = zoneNum;
|
||||||
|
|
||||||
if (vpe->vgaFile1 != NULL)
|
if (vpe->vgaFile1 != NULL)
|
||||||
|
@ -1234,8 +1241,17 @@ void AGOSEngine::setImage(uint16 vgaSpriteId, bool vgaScript) {
|
||||||
}
|
}
|
||||||
assert(READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == vgaSpriteId);
|
assert(READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == vgaSpriteId);
|
||||||
|
|
||||||
if (!vgaScript)
|
if (!vgaScript) {
|
||||||
clearVideoWindow(_windowNum, READ_BE_UINT16(&((ImageHeader_WW *) b)->color));
|
uint16 color = READ_BE_UINT16(&((ImageHeader_WW *) b)->color);
|
||||||
|
if (getGameType() == GType_PN) {
|
||||||
|
if (color & 0x80)
|
||||||
|
_wiped = true;
|
||||||
|
else if (_wiped == true)
|
||||||
|
restoreMenu();
|
||||||
|
color &= 0xFF7F;
|
||||||
|
}
|
||||||
|
clearVideoWindow(_windowNum, color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dumpVgaScripts) {
|
if (_dumpVgaScripts) {
|
||||||
|
@ -1262,6 +1278,14 @@ void AGOSEngine::setImage(uint16 vgaSpriteId, bool vgaScript) {
|
||||||
_vcPtr = vc_ptr_org;
|
_vcPtr = vc_ptr_org;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::setWindowImageEx(uint16 mode, uint16 vga_res) {
|
||||||
|
if (!_initMouse) {
|
||||||
|
_initMouse = 1;
|
||||||
|
vc33_setMouseOn();
|
||||||
|
}
|
||||||
|
setWindowImage(mode, vga_res);
|
||||||
|
}
|
||||||
|
|
||||||
void AGOSEngine::setWindowImageEx(uint16 mode, uint16 vgaSpriteId) {
|
void AGOSEngine::setWindowImageEx(uint16 mode, uint16 vgaSpriteId) {
|
||||||
_window3Flag = 0;
|
_window3Flag = 0;
|
||||||
|
|
||||||
|
@ -1299,7 +1323,7 @@ void AGOSEngine::setWindowImageEx(uint16 mode, uint16 vgaSpriteId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId) {
|
void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCase) {
|
||||||
uint16 updateWindow;
|
uint16 updateWindow;
|
||||||
|
|
||||||
_windowNum = updateWindow = mode;
|
_windowNum = updateWindow = mode;
|
||||||
|
@ -1307,7 +1331,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId) {
|
||||||
|
|
||||||
if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
||||||
vc27_resetSprite();
|
vc27_resetSprite();
|
||||||
} else {
|
} else if (!specialCase) {
|
||||||
VgaTimerEntry *vte = _vgaTimerList;
|
VgaTimerEntry *vte = _vgaTimerList;
|
||||||
while (vte->type != ANIMATE_INT)
|
while (vte->type != ANIMATE_INT)
|
||||||
vte++;
|
vte++;
|
||||||
|
@ -1331,7 +1355,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setImage(vgaSpriteId);
|
setImage(vgaSpriteId, specialCase);
|
||||||
|
|
||||||
if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
if (getGameType() == GType_FF || getGameType() == GType_PP) {
|
||||||
fillBackGroundFromBack();
|
fillBackGroundFromBack();
|
||||||
|
@ -1423,6 +1447,9 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId) {
|
||||||
src = _window4BackScn;
|
src = _window4BackScn;
|
||||||
srcWidth = _videoWindows[18] * 16;
|
srcWidth = _videoWindows[18] * 16;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth;
|
||||||
|
srcWidth = _screenWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
_boxStarHeight = height;
|
_boxStarHeight = height;
|
||||||
|
@ -1433,7 +1460,14 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId) {
|
||||||
src += srcWidth;
|
src += srcWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getGameType() == GType_ELVIRA1 && updateWindow == 3 && _bottomPalette) {
|
if (getGameType() == GType_PN && !_wiped && !specialCase) {
|
||||||
|
uint8 color = (getPlatform() == Common::kPlatformPC) ? 7 : 15;
|
||||||
|
dst = (byte *)screen->pixels + 48;
|
||||||
|
memset(dst, color, 224);
|
||||||
|
|
||||||
|
dst = (byte *)screen->pixels + 132 * _screenWidth + 48;
|
||||||
|
memset(dst, color, 224);
|
||||||
|
} else if (getGameType() == GType_ELVIRA1 && updateWindow == 3 && _bottomPalette) {
|
||||||
dst = (byte *)screen->pixels + 133 * _screenWidth;
|
dst = (byte *)screen->pixels + 133 * _screenWidth;
|
||||||
int size = 67 * _screenWidth;
|
int size = 67 * _screenWidth;
|
||||||
|
|
||||||
|
@ -1449,4 +1483,26 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId) {
|
||||||
_lockWord &= ~0x20;
|
_lockWord &= ~0x20;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Personal Nightmare specific
|
||||||
|
void AGOSEngine::drawEdging() {
|
||||||
|
byte *dst;
|
||||||
|
uint8 color = (getPlatform() == Common::kPlatformPC) ? 7 : 15;
|
||||||
|
|
||||||
|
Graphics::Surface *screen = _system->lockScreen();
|
||||||
|
|
||||||
|
dst = (byte *)screen->pixels + 136 * _screenWidth;
|
||||||
|
uint8 len = 52;
|
||||||
|
|
||||||
|
while (len--) {
|
||||||
|
dst[0] = color;
|
||||||
|
dst[319] = color;
|
||||||
|
dst += _screenWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst = (byte *)screen->pixels + 187 * _screenWidth;
|
||||||
|
memset(dst, color, _screenWidth);
|
||||||
|
|
||||||
|
_system->unlockScreen();
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace AGOS
|
} // End of namespace AGOS
|
||||||
|
|
|
@ -302,7 +302,7 @@ void AGOSEngine_Elvira2::drawIcon(WindowBlock *window, uint icon, uint x, uint y
|
||||||
_lockWord &= ~0x8000;
|
_lockWord &= ~0x8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
|
void AGOSEngine_Elvira1::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
|
||||||
byte *dst;
|
byte *dst;
|
||||||
byte *src;
|
byte *src;
|
||||||
|
|
||||||
|
@ -329,6 +329,43 @@ void AGOSEngine::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
|
||||||
_lockWord &= ~0x8000;
|
_lockWord &= ~0x8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::drawIcon(WindowBlock *window, uint icon, uint x, uint y) {
|
||||||
|
byte *dst;
|
||||||
|
byte *src;
|
||||||
|
|
||||||
|
_lockWord |= 0x8000;
|
||||||
|
|
||||||
|
Graphics::Surface *screen = _system->lockScreen();
|
||||||
|
dst = (byte *)screen->pixels + y * _dxSurfacePitch + x * 8;
|
||||||
|
src = _iconFilePtr + icon * 146;
|
||||||
|
|
||||||
|
if (icon == 0xFF) {
|
||||||
|
// Draw Blank Icon
|
||||||
|
for (int yp = 0; yp < 24; yp++) {
|
||||||
|
memset(dst, 0, 24);
|
||||||
|
dst += _dxSurfacePitch;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint8 palette[4];
|
||||||
|
palette[0] = *src >> 4;
|
||||||
|
palette[1] = *src++ & 0xf;
|
||||||
|
palette[2] = *src >> 4;
|
||||||
|
palette[3] = *src++ & 0xf;
|
||||||
|
for (int yp = 0; yp < 24; ++yp, src += 6) {
|
||||||
|
// Get bit-set representing the 24 pixels for the line
|
||||||
|
uint32 v1 = (READ_BE_UINT16(src) << 8) | *(src + 4);
|
||||||
|
uint32 v2 = (READ_BE_UINT16(src + 2) << 8) | *(src + 5);
|
||||||
|
for (int xp = 0; xp < 24; ++xp, v1 >>= 1, v2 >>= 1) {
|
||||||
|
dst[yp * _screenWidth + (23 - xp)] = palette[((v1 & 1) << 1) | (v2 & 1)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_system->unlockScreen();
|
||||||
|
|
||||||
|
_lockWord &= ~0x8000;
|
||||||
|
}
|
||||||
|
|
||||||
void AGOSEngine_Feeble::drawIconArray(uint num, Item *itemRef, int line, int classMask) {
|
void AGOSEngine_Feeble::drawIconArray(uint num, Item *itemRef, int line, int classMask) {
|
||||||
Item *item_ptr_org = itemRef;
|
Item *item_ptr_org = itemRef;
|
||||||
WindowBlock *window;
|
WindowBlock *window;
|
||||||
|
@ -923,7 +960,7 @@ void AGOSEngine::drawArrow(uint16 x, uint16 y, int8 dir) {
|
||||||
|
|
||||||
void AGOSEngine_Simon1::removeArrows(WindowBlock *window, uint num) {
|
void AGOSEngine_Simon1::removeArrows(WindowBlock *window, uint num) {
|
||||||
if (getGameType() == GType_SIMON1) {
|
if (getGameType() == GType_SIMON1) {
|
||||||
restoreBlock(200, 320, 146, 304);
|
restoreBlock(304, 146, 320, 200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -941,7 +978,7 @@ void AGOSEngine::removeArrows(WindowBlock *window, uint num) {
|
||||||
if (num != 2) {
|
if (num != 2) {
|
||||||
uint y = window->height * 4 + window->y - 19;
|
uint y = window->height * 4 + window->y - 19;
|
||||||
uint x = window->width + window->x;
|
uint x = window->width + window->x;
|
||||||
restoreBlock(y + 38, x + 16, y, x);
|
restoreBlock(x, y, x + 16, y + 38);
|
||||||
} else {
|
} else {
|
||||||
colorBlock(window, 240, 151, 16, 38);
|
colorBlock(window, 240, 151, 16, 38);
|
||||||
}
|
}
|
||||||
|
@ -984,4 +1021,94 @@ void AGOSEngine::removeIconArray(uint num) {
|
||||||
_fcsData2[num] = 0;
|
_fcsData2[num] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const byte hitBarData[12 * 7] = {
|
||||||
|
0x3C, 0x00, 0x80, 0x00, 0x88, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0xD8, 0x00, 0x00, 0x04, 0x48, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x89, 0x8E, 0x00, 0xA8, 0x86, 0x10, 0x04, 0x08, 0x21, 0x88, 0x00,
|
||||||
|
0x38, 0x50, 0x84, 0x00, 0x89, 0x49, 0x28, 0x04, 0x08, 0x52, 0x14, 0x00,
|
||||||
|
0x20, 0x20, 0x84, 0x00, 0x89, 0x48, 0x38, 0x04, 0x08, 0x53, 0x9C, 0x00,
|
||||||
|
0x20, 0x50, 0x84, 0x00, 0x89, 0x48, 0x20, 0x04, 0x48, 0x50, 0x90, 0x00,
|
||||||
|
0x3C, 0x89, 0xC3, 0x00, 0x88, 0x88, 0x18, 0x03, 0x86, 0x23, 0x0C, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
// Personal Nightmare specific
|
||||||
|
void AGOSEngine_PN::drawIconHitBar() {
|
||||||
|
Graphics::Surface *screen = _system->lockScreen();
|
||||||
|
byte *dst = (byte *)screen->pixels + 3 * _dxSurfacePitch + 6 * 8;
|
||||||
|
const byte *src = hitBarData;
|
||||||
|
uint8 color = (getPlatform() == Common::kPlatformPC) ? 7 : 15;
|
||||||
|
|
||||||
|
for (int h = 0; h < 7; h++) {
|
||||||
|
for (int w = 0; w < 12; w++) {
|
||||||
|
int8 b = *src++;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if (b < 0) {
|
||||||
|
dst[w * 8 + i] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
b <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst += _dxSurfacePitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
_system->unlockScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::iconPage() {
|
||||||
|
_objectCountS = -1;
|
||||||
|
|
||||||
|
mouseOff();
|
||||||
|
|
||||||
|
uint8 objRoom = getptr(_quickptr[12] + _variableArray[210] * _quickshort[5] + 20);
|
||||||
|
uint8 iconNum = getptr(_quickptr[0] + objRoom * _quickshort[0] + 4);
|
||||||
|
|
||||||
|
drawIcon(NULL, iconNum, 6, 12);
|
||||||
|
|
||||||
|
HitArea *ha = _invHitAreas + 5;
|
||||||
|
for (uint8 r = 0; r < 5; r++) {
|
||||||
|
for (uint8 i = 0; i < 7; i++) {
|
||||||
|
printIcon(ha, i, r);
|
||||||
|
ha++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseOn();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AGOSEngine_PN::ifObjectInInv(uint16 a) {
|
||||||
|
return _variableArray[210] == getptr(_quickptr[11] + a * _quickshort[4] + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AGOSEngine_PN::testContainer(uint16 a) {
|
||||||
|
return bitextract(_quickptr[1] + a * _quickshort[1], 0) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AGOSEngine_PN::testObvious(uint16 a) {
|
||||||
|
return bitextract(_quickptr[1] + a * _quickshort[1], 4) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AGOSEngine_PN::testSeen(uint16 a) {
|
||||||
|
return bitextract(_quickptr[1] + a * _quickshort[1], 3) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::printIcon(HitArea *ha, uint8 i, uint8 r) {
|
||||||
|
if (_objects == _objectCountS) {
|
||||||
|
ha->flags |= kOBFBoxDisabled;
|
||||||
|
drawIcon(NULL, 0xFF, 12 + i * 3, 12 + 24 * r);
|
||||||
|
} else {
|
||||||
|
_objectCountS++;
|
||||||
|
if (!ifObjectInInv(_objectCountS) || !testObvious(_objectCountS)) {
|
||||||
|
printIcon(ha, i, r);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
uint8 iconNum = getptr(_quickptr[0] + _objectCountS * _quickshort[0] + 4);
|
||||||
|
drawIcon(NULL, iconNum, 12 + i * 3, 12 + 24 * r);
|
||||||
|
|
||||||
|
ha->msg1 = _objectCountS | 0x8000;
|
||||||
|
ha->flags &= ~kOBFBoxDisabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace AGOS
|
} // End of namespace AGOS
|
||||||
|
|
|
@ -606,6 +606,129 @@ bool AGOSEngine::processSpecialKeys() {
|
||||||
return verbCode;
|
return verbCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Personal Nightmare specific
|
||||||
|
void AGOSEngine_PN::clearInputLine() {
|
||||||
|
_inputting = 0;
|
||||||
|
_inputReady = 0;
|
||||||
|
clearWindow(_windowArray[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::handleKeyboard() {
|
||||||
|
if (!_inputReady)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_hitCalled != 0) {
|
||||||
|
mouseHit();
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 chr = -1;
|
||||||
|
if (_mouseString) {
|
||||||
|
const char *strPtr = _mouseString;
|
||||||
|
while (*strPtr != 0 && *strPtr != 13)
|
||||||
|
addChar(*strPtr++);
|
||||||
|
_mouseString = 0;
|
||||||
|
|
||||||
|
chr = *strPtr;
|
||||||
|
if (chr == 13) {
|
||||||
|
addChar(13);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_mouseString1 && chr != 13) {
|
||||||
|
const char *strPtr = _mouseString1;
|
||||||
|
while (*strPtr != 13)
|
||||||
|
addChar(*strPtr++);
|
||||||
|
_mouseString1 = 0;
|
||||||
|
|
||||||
|
chr = *strPtr;
|
||||||
|
if (chr == 13) {
|
||||||
|
addChar(13);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chr == -1) {
|
||||||
|
chr = _keyPressed.ascii;
|
||||||
|
if (chr == 8 || chr == 13) {
|
||||||
|
addChar(chr);
|
||||||
|
} else if (!(_lockWord & 0x10)) {
|
||||||
|
if (chr >= 32)
|
||||||
|
addChar(chr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chr == 13) {
|
||||||
|
_mouseString = 0;
|
||||||
|
_mouseString1 = 0;
|
||||||
|
_mousePrintFG = 0;
|
||||||
|
_inputReady = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_keyPressed.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::interact(char *buffer, uint8 size) {
|
||||||
|
if (!_inputting) {
|
||||||
|
memset(_keyboardBuffer, 0, sizeof(_keyboardBuffer));
|
||||||
|
_intputCounter = 0;
|
||||||
|
_inputMax = size;
|
||||||
|
_inputWindow = _windowArray[_curWindow];
|
||||||
|
windowPutChar(_inputWindow, 128);
|
||||||
|
_inputting = 1;
|
||||||
|
_inputReady = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!shouldQuit() && _inputReady) {
|
||||||
|
if (!_noScanFlag && _scanFlag) {
|
||||||
|
buffer[0] = 1;
|
||||||
|
buffer[1] = 0;
|
||||||
|
_scanFlag = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_inputReady) {
|
||||||
|
memcpy(buffer, _keyboardBuffer, size);
|
||||||
|
_inputting = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::addChar(uint8 chr) {
|
||||||
|
if (chr == 13) {
|
||||||
|
_keyboardBuffer[_intputCounter++] = chr;
|
||||||
|
userGameBackSpace(_inputWindow, 8);
|
||||||
|
windowPutChar(_inputWindow, 13);
|
||||||
|
} else if (chr == 8 && _intputCounter) {
|
||||||
|
userGameBackSpace(_inputWindow, 8);
|
||||||
|
userGameBackSpace(_inputWindow, 8);
|
||||||
|
windowPutChar(_inputWindow, 128);
|
||||||
|
|
||||||
|
_keyboardBuffer[--_intputCounter] = 0;
|
||||||
|
} else if (chr >= 32 && _intputCounter < _inputMax) {
|
||||||
|
_keyboardBuffer[_intputCounter++] = chr;
|
||||||
|
|
||||||
|
userGameBackSpace(_inputWindow, 8);
|
||||||
|
windowPutChar(_inputWindow, chr);
|
||||||
|
windowPutChar(_inputWindow, 128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AGOSEngine_PN::processSpecialKeys() {
|
||||||
|
if (shouldQuit())
|
||||||
|
_exitCutscene = true;
|
||||||
|
|
||||||
|
switch (_keyPressed.keycode) {
|
||||||
|
case Common::KEYCODE_ESCAPE:
|
||||||
|
_exitCutscene = true;
|
||||||
|
break;
|
||||||
|
case Common::KEYCODE_PAUSE:
|
||||||
|
pause();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_keyPressed.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // End of namespace AGOS
|
} // End of namespace AGOS
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -214,6 +214,22 @@ enum BoxFlags {
|
||||||
kBFBoxItem = 0x80
|
kBFBoxItem = 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum OldBoxFlags_PN {
|
||||||
|
kOBFObject = 0x1,
|
||||||
|
kOBFExit = 0x2,
|
||||||
|
kOBFDraggable = 0x4,
|
||||||
|
kOBFUseEmptyLine = 0x8,
|
||||||
|
kOBFBoxDisabled = 0x10,
|
||||||
|
kOBFInventoryBox = 0x20,
|
||||||
|
kOBFRoomBox = 0x40,
|
||||||
|
kOBFMoreBox = 0x80,
|
||||||
|
kOBFNoShowName = 0x100,
|
||||||
|
kOBFUseMessageList = 0x400,
|
||||||
|
// ScummVM specific
|
||||||
|
kOBFBoxSelected = 0x800,
|
||||||
|
kOBFInvertTouch = 0x1000
|
||||||
|
};
|
||||||
|
|
||||||
enum SubObjectFlags {
|
enum SubObjectFlags {
|
||||||
kOFText = 0x1,
|
kOFText = 0x1,
|
||||||
kOFSize = 0x2,
|
kOFSize = 0x2,
|
||||||
|
@ -251,11 +267,13 @@ enum GameFileTypes {
|
||||||
GAME_TBLFILE = 1 << 7,
|
GAME_TBLFILE = 1 << 7,
|
||||||
GAME_XTBLFILE = 1 << 8,
|
GAME_XTBLFILE = 1 << 8,
|
||||||
GAME_RESTFILE = 1 << 9,
|
GAME_RESTFILE = 1 << 9,
|
||||||
|
GAME_TEXTFILE = 1 << 10,
|
||||||
|
|
||||||
GAME_GFXIDXFILE = 1 << 10
|
GAME_GFXIDXFILE = 1 << 11
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GameIds {
|
enum GameIds {
|
||||||
|
GID_PN,
|
||||||
GID_ELVIRA1,
|
GID_ELVIRA1,
|
||||||
GID_ELVIRA2,
|
GID_ELVIRA2,
|
||||||
GID_WAXWORKS,
|
GID_WAXWORKS,
|
||||||
|
|
|
@ -53,6 +53,27 @@ void AGOSEngine::loadMenuFile() {
|
||||||
in.close();
|
in.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Personal Nightmare specific
|
||||||
|
void AGOSEngine::restoreMenu() {
|
||||||
|
_wiped = 0;
|
||||||
|
|
||||||
|
_lockWord |= 0x80;
|
||||||
|
|
||||||
|
clearVideoWindow(3, 0);
|
||||||
|
|
||||||
|
uint16 oldWindowNum = _windowNum;
|
||||||
|
|
||||||
|
setWindowImage(1, 1);
|
||||||
|
setWindowImage(2, 2);
|
||||||
|
|
||||||
|
drawEdging();
|
||||||
|
|
||||||
|
_windowNum = oldWindowNum;
|
||||||
|
|
||||||
|
_lockWord |= 0x20;
|
||||||
|
_lockWord &= ~0x80;
|
||||||
|
}
|
||||||
|
|
||||||
// Elvira 1 specific
|
// Elvira 1 specific
|
||||||
void AGOSEngine::drawMenuStrip(uint windowNum, uint menuNum) {
|
void AGOSEngine::drawMenuStrip(uint windowNum, uint menuNum) {
|
||||||
WindowBlock *window = _windowArray[windowNum % 8];
|
WindowBlock *window = _windowArray[windowNum % 8];
|
||||||
|
|
|
@ -20,6 +20,7 @@ MODULE_OBJS := \
|
||||||
midi.o \
|
midi.o \
|
||||||
midiparser_s1d.o \
|
midiparser_s1d.o \
|
||||||
oracle.o \
|
oracle.o \
|
||||||
|
pn.o \
|
||||||
res.o \
|
res.o \
|
||||||
res_ami.o \
|
res_ami.o \
|
||||||
res_snd.o \
|
res_snd.o \
|
||||||
|
@ -28,6 +29,7 @@ MODULE_OBJS := \
|
||||||
script.o \
|
script.o \
|
||||||
script_e1.o \
|
script_e1.o \
|
||||||
script_e2.o \
|
script_e2.o \
|
||||||
|
script_pn.o \
|
||||||
script_ww.o \
|
script_ww.o \
|
||||||
script_s1.o \
|
script_s1.o \
|
||||||
script_s2.o \
|
script_s2.o \
|
||||||
|
@ -39,6 +41,7 @@ MODULE_OBJS := \
|
||||||
verb.o \
|
verb.o \
|
||||||
vga.o \
|
vga.o \
|
||||||
vga_e2.o \
|
vga_e2.o \
|
||||||
|
vga_pn.o \
|
||||||
vga_ww.o \
|
vga_ww.o \
|
||||||
vga_s1.o \
|
vga_s1.o \
|
||||||
vga_s2.o \
|
vga_s2.o \
|
||||||
|
|
293
engines/agos/pn.cpp
Normal file
293
engines/agos/pn.cpp
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
/* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/config-manager.h"
|
||||||
|
|
||||||
|
#include "agos/intern.h"
|
||||||
|
#include "agos/agos.h"
|
||||||
|
|
||||||
|
namespace AGOS {
|
||||||
|
|
||||||
|
AGOSEngine_PN::AGOSEngine_PN(OSystem *system)
|
||||||
|
: AGOSEngine(system) {
|
||||||
|
|
||||||
|
_dataBase = 0;
|
||||||
|
_dataBaseSize = 0;
|
||||||
|
_textBase = 0;
|
||||||
|
_textBaseSize = 0;
|
||||||
|
|
||||||
|
memset(_buffer, 0, sizeof(_buffer));
|
||||||
|
memset(_inputline, 0, sizeof(_inputline));
|
||||||
|
memset(_saveFile, 0, sizeof(_saveFile));
|
||||||
|
memset(_sb, 0, sizeof(_sb));
|
||||||
|
memset(_wordcp, 0, sizeof(_wordcp));
|
||||||
|
|
||||||
|
memset(_objectName1, 0, sizeof(_objectName1));
|
||||||
|
memset(_objectName2, 0, sizeof(_objectName2));
|
||||||
|
|
||||||
|
_dragStore = 0;
|
||||||
|
_hitCalled = 0;
|
||||||
|
_inputReady = 0;
|
||||||
|
_inputting = 0;
|
||||||
|
_intputCounter = 0;
|
||||||
|
_inputMax = 0;
|
||||||
|
_mousePrintFG = 0;
|
||||||
|
_mouseString = 0;
|
||||||
|
_mouseString1 = 0;
|
||||||
|
memset(_inMessage, 0, sizeof(_inMessage));
|
||||||
|
memset(_placeMessage, 0, sizeof(_placeMessage));
|
||||||
|
|
||||||
|
memset(_quickptr, 0, sizeof(_quickptr));
|
||||||
|
memset(_quickshort, 0, sizeof(_quickshort));
|
||||||
|
|
||||||
|
_noScanFlag = false;
|
||||||
|
memset(_keyboardBuffer, 0, sizeof(_keyboardBuffer));
|
||||||
|
|
||||||
|
_objects = 0;
|
||||||
|
_objectCountS = 0;
|
||||||
|
|
||||||
|
_bp = 0;
|
||||||
|
_xofs = 0;
|
||||||
|
_havinit = 0;
|
||||||
|
_seed = 0;
|
||||||
|
|
||||||
|
_curwrdptr = 0;
|
||||||
|
_inpp = 0;
|
||||||
|
_fnst = 0;
|
||||||
|
_linembr = 0;
|
||||||
|
_linct = 0;
|
||||||
|
_procnum = 0;
|
||||||
|
|
||||||
|
_linebase = 0;
|
||||||
|
_workptr = 0;
|
||||||
|
|
||||||
|
_cjmpbuff = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AGOSEngine_PN::~AGOSEngine_PN() {
|
||||||
|
free(_dataBase);
|
||||||
|
free(_textBase);
|
||||||
|
|
||||||
|
free(_cjmpbuff);
|
||||||
|
free(_stackbase);
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte egaPalette[48] = {
|
||||||
|
0, 0, 0,
|
||||||
|
0, 0, 170,
|
||||||
|
0, 170, 0,
|
||||||
|
0, 170, 170,
|
||||||
|
170, 0, 0,
|
||||||
|
170, 0, 170,
|
||||||
|
170, 85, 0,
|
||||||
|
170, 170, 170,
|
||||||
|
85, 85, 85,
|
||||||
|
85, 85, 255,
|
||||||
|
85, 255, 85,
|
||||||
|
85, 255, 255,
|
||||||
|
255, 85, 85,
|
||||||
|
255, 85, 255,
|
||||||
|
255, 255, 85,
|
||||||
|
255, 255, 255
|
||||||
|
};
|
||||||
|
|
||||||
|
Common::Error AGOSEngine_PN::go() {
|
||||||
|
loadGamePcFile();
|
||||||
|
|
||||||
|
if (getFileName(GAME_ICONFILE) != NULL) {
|
||||||
|
loadIconFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupBoxes();
|
||||||
|
|
||||||
|
vc34_setMouseOff();
|
||||||
|
|
||||||
|
addVgaEvent(_frameCount, ANIMATE_INT, NULL, 0, 0);
|
||||||
|
|
||||||
|
if (getPlatform() == Common::kPlatformPC) {
|
||||||
|
// Set EGA Palette
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
_displayPalette[i * 4 + 0] = egaPalette[i * 3 + 0];
|
||||||
|
_displayPalette[i * 4 + 1] = egaPalette[i * 3 + 1];
|
||||||
|
_displayPalette[i * 4 + 2] = egaPalette[i * 3 + 2];
|
||||||
|
_displayPalette[i * 4 + 3] = 0;
|
||||||
|
}
|
||||||
|
_paletteFlag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_inputWindow = _windowArray[2] = openWindow(0, 192, 40, 1, 1, 0, 15);
|
||||||
|
_textWindow = _windowArray[0] = openWindow(1, 136, 38, 6, 1, 0, 15);
|
||||||
|
|
||||||
|
if (getFeatures() & GF_DEMO) {
|
||||||
|
demoSeq();
|
||||||
|
} else {
|
||||||
|
introSeq();
|
||||||
|
processor();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Common::kNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::demoSeq() {
|
||||||
|
while (!shouldQuit()) {
|
||||||
|
loadZone(0);
|
||||||
|
setWindowImage(3, 0);
|
||||||
|
while (!shouldQuit() && _variableArray[228] != 1)
|
||||||
|
delay(1);
|
||||||
|
|
||||||
|
loadZone(1);
|
||||||
|
setWindowImage(0, 0);
|
||||||
|
while (!shouldQuit() && _variableArray[228] != 2)
|
||||||
|
delay(1);
|
||||||
|
|
||||||
|
loadZone(2);
|
||||||
|
setWindowImage(0, 0);
|
||||||
|
while (!shouldQuit() && _variableArray[228] != 3)
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::introSeq() {
|
||||||
|
loadZone(25); // Zone 'I'
|
||||||
|
setWindowImage(3, 0);
|
||||||
|
|
||||||
|
_exitCutscene = false;
|
||||||
|
while (!shouldQuit() && !_exitCutscene && _variableArray[228] != 1) {
|
||||||
|
processSpecialKeys();
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setWindowImage(3, 3);
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
loadZone(27); // Zone 'K'
|
||||||
|
setWindowImage(3, 0);
|
||||||
|
|
||||||
|
_exitCutscene = false;
|
||||||
|
while (!shouldQuit() && !_exitCutscene && _variableArray[228] != 2) {
|
||||||
|
processSpecialKeys();
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::setupBoxes() {
|
||||||
|
_hitAreaList = _invHitAreas;
|
||||||
|
// Inventory box
|
||||||
|
defineBox( 0, 11, 68, 16, 26, 25, 0, kOBFDraggable | kOBFUseEmptyLine | kOBFInventoryBox | kOBFNoShowName);
|
||||||
|
// Room Box
|
||||||
|
defineBox( 1, 11, 103, 16, 26, 26, 0, kOBFDraggable | kOBFUseEmptyLine | kOBFRoomBox | kOBFNoShowName);
|
||||||
|
// Exit box
|
||||||
|
defineBox( 2, 48, 2, 8, 28, 27, 0, kOBFUseEmptyLine | kOBFNoShowName);
|
||||||
|
// More box
|
||||||
|
defineBox( 3, 80, 2, 8, 26, 28, 0, kOBFUseEmptyLine | kOBFMoreBox | kOBFNoShowName);
|
||||||
|
// Close box
|
||||||
|
defineBox( 4, 110, 2, 8, 28, 29, 0, kOBFUseEmptyLine | kOBFNoShowName);
|
||||||
|
|
||||||
|
// Icon boxes
|
||||||
|
uint8 num = 5;
|
||||||
|
for (uint8 r = 0; r < 5; r++) {
|
||||||
|
for (uint8 i = 0; i < 7; i++) {
|
||||||
|
defineBox(num, 96 + i * 24, 12 + r * 24, 24, 24, 0, 3, kOBFObject | kOBFDraggable);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark the end of inventory boxes
|
||||||
|
HitArea *ha = _hitAreaList + num;
|
||||||
|
ha->id = 0xFFFF;
|
||||||
|
|
||||||
|
_hitAreaList = _hitAreas;
|
||||||
|
defineBox( 0, 0, 0, 200, 320, 0, 0, kOBFBoxDisabled | kOBFNoShowName);
|
||||||
|
defineBox( 1, 273, 4, 5, 45, 1, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox( 2, 273, 12, 5, 45, 2, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox( 3, 273, 20, 5, 45, 3, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox( 4, 273, 28, 5, 45, 4, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox( 5, 273, 36, 5, 45, 5, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox( 6, 273, 44, 5, 45, 6, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox( 7, 273, 52, 5, 45, 7, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox( 8, 273, 60, 5, 45, 8, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox( 9, 273, 68, 5, 45, 9, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox(10, 273, 76, 5, 45, 10, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox(11, 273, 84, 5, 45, 11, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox(12, 273, 92, 5, 45, 12, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox(13, 273, 100, 5, 45, 13, 0, kOBFUseEmptyLine | kOBFBoxDisabled | kOBFNoShowName);
|
||||||
|
defineBox(14, 273, 107, 5, 45, 14, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox(15, 273, 115, 5, 45, 15, 0, kOBFUseEmptyLine | kOBFNoShowName | kOBFInvertTouch);
|
||||||
|
defineBox(16, 273, 123, 5, 45, 16, 0, kOBFUseEmptyLine | kOBFBoxDisabled | kOBFNoShowName);
|
||||||
|
defineBox(17, 20, 5, 7, 7, 17, 0, kOBFUseEmptyLine | kOBFNoShowName);
|
||||||
|
defineBox(18, 28, 11, 7, 13, 18, 0, kOBFUseEmptyLine | kOBFNoShowName);
|
||||||
|
defineBox(19, 36, 21, 7, 7, 19, 0, kOBFUseEmptyLine | kOBFNoShowName);
|
||||||
|
defineBox(20, 27, 31, 7, 13, 20, 0, kOBFUseEmptyLine | kOBFNoShowName);
|
||||||
|
defineBox(21, 20, 37, 7, 7, 21, 0, kOBFUseEmptyLine | kOBFNoShowName);
|
||||||
|
defineBox(22, 5, 31, 7, 13, 22, 0, kOBFUseEmptyLine | kOBFNoShowName);
|
||||||
|
defineBox(23, 4, 21, 7, 7, 23, 0, kOBFUseEmptyLine | kOBFNoShowName);
|
||||||
|
defineBox(24, 5, 11, 7, 13, 24, 0, kOBFUseEmptyLine | kOBFNoShowName);
|
||||||
|
defineBox(25, 11, 68, 16, 26, 25, 0, kOBFDraggable | kOBFUseEmptyLine | kOBFInventoryBox | kOBFNoShowName);
|
||||||
|
defineBox(26, 11, 103, 16, 26, 26, 0, kOBFDraggable | kOBFUseEmptyLine | kOBFRoomBox | kOBFNoShowName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::processor() {
|
||||||
|
int q;
|
||||||
|
|
||||||
|
setqptrs();
|
||||||
|
q = setjmp(_loadfail);
|
||||||
|
|
||||||
|
_variableArray[6] = 0;
|
||||||
|
|
||||||
|
if (getPlatform() == Common::kPlatformAtariST) {
|
||||||
|
_variableArray[21] = 2;
|
||||||
|
} else if (getPlatform() == Common::kPlatformAmiga) {
|
||||||
|
_variableArray[21] = 0;
|
||||||
|
} else {
|
||||||
|
_variableArray[21] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_variableArray[16] = _quickshort[6];
|
||||||
|
_variableArray[17] = _quickshort[7];
|
||||||
|
_variableArray[19] = getptr(55L);
|
||||||
|
setposition(q, 0);
|
||||||
|
doline(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::setqptrs() {
|
||||||
|
int a = 0;
|
||||||
|
|
||||||
|
while (a < 11) {
|
||||||
|
_quickptr[a] = getlong(3L * a);
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
_quickptr[11] = getlong(58L);
|
||||||
|
_quickptr[12] = getlong(61L);
|
||||||
|
_quickshort[0] = getptr(35L);
|
||||||
|
_quickshort[1] = getptr(37L);
|
||||||
|
_quickshort[2] = getptr(39L);
|
||||||
|
_quickshort[3] = getptr(41L);
|
||||||
|
_quickshort[4] = getptr(43L);
|
||||||
|
_quickshort[5] = getptr(45L);
|
||||||
|
_quickshort[6] = getptr(51L);
|
||||||
|
_quickshort[7] = getptr(53L);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End of namespace AGOS
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
|
#include "common/util.h"
|
||||||
|
|
||||||
#include "agos/agos.h"
|
#include "agos/agos.h"
|
||||||
#include "agos/intern.h"
|
#include "agos/intern.h"
|
||||||
|
@ -149,6 +150,46 @@ int AGOSEngine::allocGamePcVars(Common::SeekableReadStream *in) {
|
||||||
return itemArrayInited;
|
return itemArrayInited;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::loadGamePcFile() {
|
||||||
|
Common::File in;
|
||||||
|
|
||||||
|
if (getFileName(GAME_BASEFILE) != NULL) {
|
||||||
|
// Read dataBase
|
||||||
|
in.open(getFileName(GAME_BASEFILE));
|
||||||
|
if (in.isOpen() == false) {
|
||||||
|
error("loadGamePcFile: Can't load database file '%s'", getFileName(GAME_BASEFILE));
|
||||||
|
}
|
||||||
|
|
||||||
|
_dataBaseSize = in.size();
|
||||||
|
_dataBase = (byte *)malloc(_dataBaseSize);
|
||||||
|
if (_dataBase == NULL)
|
||||||
|
error("loadGamePcFile: Out of memory for dataBase");
|
||||||
|
in.read(_dataBase, _dataBaseSize);
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
if (_dataBase[31] != 0)
|
||||||
|
error("Later version of system requested");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getFileName(GAME_TEXTFILE) != NULL) {
|
||||||
|
// Read textBase
|
||||||
|
in.open(getFileName(GAME_TEXTFILE));
|
||||||
|
if (in.isOpen() == false) {
|
||||||
|
error("loadGamePcFile: Can't load textbase file '%s'", getFileName(GAME_TEXTFILE));
|
||||||
|
}
|
||||||
|
|
||||||
|
_textBaseSize = in.size();
|
||||||
|
_textBase = (byte *)malloc(_textBaseSize);
|
||||||
|
if (_textBase == NULL)
|
||||||
|
error("loadGamePcFile: Out of memory for textBase");
|
||||||
|
in.read(_textBase, _textBaseSize);
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
if (_textBase[getlong(30L)] != 128)
|
||||||
|
error("Unknown compression format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AGOSEngine::loadGamePcFile() {
|
void AGOSEngine::loadGamePcFile() {
|
||||||
Common::File in;
|
Common::File in;
|
||||||
int fileSize;
|
int fileSize;
|
||||||
|
@ -646,6 +687,96 @@ bool AGOSEngine::decrunchFile(byte *src, byte *dst, uint32 size) {
|
||||||
#undef SD_TYPE_LITERAL
|
#undef SD_TYPE_LITERAL
|
||||||
#undef SD_TYPE_MATCH
|
#undef SD_TYPE_MATCH
|
||||||
|
|
||||||
|
static bool getBit(Common::Stack<uint32> &dataList, uint32 &srcVal) {
|
||||||
|
bool result = srcVal & 1;
|
||||||
|
srcVal >>= 1;
|
||||||
|
if (srcVal == 0) {
|
||||||
|
srcVal = dataList.pop();
|
||||||
|
|
||||||
|
result = srcVal & 1;
|
||||||
|
srcVal = (srcVal >> 1) | 0x80000000L;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32 copyBits(Common::Stack<uint32> &dataList, uint32 &srcVal, int numBits) {
|
||||||
|
uint32 destVal = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < numBits; ++i) {
|
||||||
|
bool f = getBit(dataList, srcVal);
|
||||||
|
destVal = (destVal << 1) | (f ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return destVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void transferLoop(uint8 *dataOut, int &outIndex, uint32 destVal, int max) {
|
||||||
|
assert(outIndex > max - 1);
|
||||||
|
byte *pDest = dataOut + outIndex;
|
||||||
|
|
||||||
|
for (int i = 0; (i <= max) && (outIndex > 0) ; ++i) {
|
||||||
|
pDest = dataOut + --outIndex;
|
||||||
|
*pDest = pDest[destVal];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::decompressPN(Common::Stack<uint32> &dataList, uint8 *&dataOut, int &dataOutSize) {
|
||||||
|
// Set up the output data area
|
||||||
|
dataOutSize = dataList.pop();
|
||||||
|
dataOut = new uint8[dataOutSize];
|
||||||
|
int outIndex = dataOutSize;
|
||||||
|
|
||||||
|
// Decompression routine
|
||||||
|
uint32 srcVal = dataList.pop();
|
||||||
|
uint32 destVal;
|
||||||
|
|
||||||
|
while (outIndex > 0) {
|
||||||
|
uint32 numBits = 0;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (getBit(dataList, srcVal)) {
|
||||||
|
destVal = copyBits(dataList, srcVal, 2);
|
||||||
|
|
||||||
|
if (destVal < 2) {
|
||||||
|
count = destVal + 2;
|
||||||
|
destVal = copyBits(dataList, srcVal, destVal + 9);
|
||||||
|
transferLoop(dataOut, outIndex, destVal, count);
|
||||||
|
continue;
|
||||||
|
} else if (destVal != 3) {
|
||||||
|
count = copyBits(dataList, srcVal, 8);
|
||||||
|
destVal = copyBits(dataList, srcVal, 8);
|
||||||
|
transferLoop(dataOut, outIndex, destVal, count);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
numBits = 8;
|
||||||
|
count = 8;
|
||||||
|
}
|
||||||
|
} else if (getBit(dataList, srcVal)) {
|
||||||
|
destVal = copyBits(dataList, srcVal, 8);
|
||||||
|
transferLoop(dataOut, outIndex, destVal, 1);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
numBits = 3;
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
destVal = copyBits(dataList, srcVal, numBits);
|
||||||
|
count += destVal;
|
||||||
|
|
||||||
|
// Loop through extracting specified number of bytes
|
||||||
|
for (int i = 0; i <= count; ++i) {
|
||||||
|
// Shift 8 bits from the source to the destination
|
||||||
|
for (int bitCtr = 0; bitCtr < 8; ++bitCtr) {
|
||||||
|
bool flag = getBit(dataList, srcVal);
|
||||||
|
destVal = (destVal << 1) | (flag ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataOut[--outIndex] = destVal & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AGOSEngine::loadVGABeardFile(uint16 id) {
|
void AGOSEngine::loadVGABeardFile(uint16 id) {
|
||||||
uint32 offs, size;
|
uint32 offs, size;
|
||||||
|
|
||||||
|
@ -690,7 +821,7 @@ void AGOSEngine::loadVGABeardFile(uint16 id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine::loadVGAVideoFile(uint16 id, uint8 type) {
|
void AGOSEngine::loadVGAVideoFile(uint16 id, uint8 type, bool useError) {
|
||||||
File in;
|
File in;
|
||||||
char filename[15];
|
char filename[15];
|
||||||
byte *dst;
|
byte *dst;
|
||||||
|
@ -729,12 +860,16 @@ void AGOSEngine::loadVGAVideoFile(uint16 id, uint8 type) {
|
||||||
sprintf(filename, "%c%d.out", 48 + id, type);
|
sprintf(filename, "%c%d.out", 48 + id, type);
|
||||||
} else if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2) {
|
} else if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2) {
|
||||||
sprintf(filename, "%.2d%d.pkd", id, type);
|
sprintf(filename, "%.2d%d.pkd", id, type);
|
||||||
|
} else if (getGameType() == GType_PN) {
|
||||||
|
sprintf(filename, "%c%d.in", id + 48, type);
|
||||||
} else {
|
} else {
|
||||||
sprintf(filename, "%.3d%d.pkd", id, type);
|
sprintf(filename, "%.3d%d.pkd", id, type);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
|
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
|
||||||
sprintf(filename, "%.2d%d.VGA", id, type);
|
sprintf(filename, "%.2d%d.VGA", id, type);
|
||||||
|
} else if (getGameType() == GType_PN) {
|
||||||
|
sprintf(filename, "%c%d.out", id + 48, type);
|
||||||
} else {
|
} else {
|
||||||
sprintf(filename, "%.3d%d.VGA", id, type);
|
sprintf(filename, "%.3d%d.VGA", id, type);
|
||||||
}
|
}
|
||||||
|
@ -742,19 +877,42 @@ void AGOSEngine::loadVGAVideoFile(uint16 id, uint8 type) {
|
||||||
|
|
||||||
in.open(filename);
|
in.open(filename);
|
||||||
if (in.isOpen() == false) {
|
if (in.isOpen() == false) {
|
||||||
error("loadVGAVideoFile: Can't load %s", filename);
|
if (useError)
|
||||||
|
error("loadVGAVideoFile: Can't load %s", filename);
|
||||||
|
|
||||||
|
_block = _blockEnd = NULL;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dstSize = srcSize = in.size();
|
dstSize = srcSize = in.size();
|
||||||
if (getFeatures() & GF_CRUNCHED) {
|
if (getGameType() == GType_PN && getPlatform() == Common::kPlatformPC && id == 17 && type == 2) {
|
||||||
byte *srcBuffer = (byte *)malloc(srcSize);
|
// The A2.out file isn't compressed in PC version of Personal Nightmare
|
||||||
if (in.read(srcBuffer, srcSize) != srcSize)
|
dst = allocBlock(dstSize + extraBuffer);
|
||||||
|
if (in.read(dst, dstSize) != dstSize)
|
||||||
error("loadVGAVideoFile: Read failed");
|
error("loadVGAVideoFile: Read failed");
|
||||||
|
} else if (getFeatures() & GF_CRUNCHED) {
|
||||||
|
if (getGameType() == GType_PN) {
|
||||||
|
Common::Stack<uint32> data;
|
||||||
|
byte *dataOut = 0;
|
||||||
|
int dataOutSize = 0;
|
||||||
|
|
||||||
dstSize = READ_BE_UINT32(srcBuffer + srcSize - 4);
|
for (uint i = 0; i < srcSize / 4; ++i)
|
||||||
dst = allocBlock (dstSize + extraBuffer);
|
data.push(in.readUint32BE());
|
||||||
decrunchFile(srcBuffer, dst, srcSize);
|
|
||||||
free(srcBuffer);
|
decompressPN(data, dataOut, dataOutSize);
|
||||||
|
dst = allocBlock (dataOutSize + extraBuffer);
|
||||||
|
memcpy(dst, dataOut, dataOutSize);
|
||||||
|
delete[] dataOut;
|
||||||
|
} else {
|
||||||
|
byte *srcBuffer = (byte *)malloc(srcSize);
|
||||||
|
if (in.read(srcBuffer, srcSize) != srcSize)
|
||||||
|
error("loadVGAVideoFile: Read failed");
|
||||||
|
|
||||||
|
dstSize = READ_BE_UINT32(srcBuffer + srcSize - 4);
|
||||||
|
dst = allocBlock (dstSize + extraBuffer);
|
||||||
|
decrunchFile(srcBuffer, dst, srcSize);
|
||||||
|
free(srcBuffer);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dst = allocBlock(dstSize + extraBuffer);
|
dst = allocBlock(dstSize + extraBuffer);
|
||||||
if (in.read(dst, dstSize) != dstSize)
|
if (in.read(dst, dstSize) != dstSize)
|
||||||
|
|
|
@ -92,7 +92,7 @@ static void bitplaneToChunkyText(uint16 *w, uint8 colorDepth, uint8 *&dst) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void convertCompressedImage(const byte *src, byte *dst, uint8 colorDepth, int height, int width) {
|
static void convertCompressedImage(const byte *src, byte *dst, uint8 colorDepth, int height, int width, bool horizontal = true) {
|
||||||
const byte *plane[kMaxColorDepth];
|
const byte *plane[kMaxColorDepth];
|
||||||
byte *uncptr[kMaxColorDepth];
|
byte *uncptr[kMaxColorDepth];
|
||||||
int length, i, j;
|
int length, i, j;
|
||||||
|
@ -119,10 +119,19 @@ static void convertCompressedImage(const byte *src, byte *dst, uint8 colorDepth,
|
||||||
|
|
||||||
uncbfroutptr = uncbfrout;
|
uncbfroutptr = uncbfrout;
|
||||||
const int chunkSize = colorDepth > 4 ? 16 : 8;
|
const int chunkSize = colorDepth > 4 ? 16 : 8;
|
||||||
for (i = 0; i < width / 16; ++i) {
|
if (horizontal) {
|
||||||
for (j = 0; j < height; ++j) {
|
for (j = 0; j < height; ++j) {
|
||||||
memcpy(dst + width * chunkSize / 16 * j + chunkSize * i, uncbfroutptr, chunkSize);
|
for (i = 0; i < width / 16; ++i) {
|
||||||
uncbfroutptr += chunkSize;
|
memcpy(dst + width * chunkSize / 16 * j + chunkSize * i, uncbfroutptr, chunkSize);
|
||||||
|
uncbfroutptr += chunkSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < width / 16; ++i) {
|
||||||
|
for (j = 0; j < height; ++j) {
|
||||||
|
memcpy(dst + width * chunkSize / 16 * j + chunkSize * i, uncbfroutptr, chunkSize);
|
||||||
|
uncbfroutptr += chunkSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +161,7 @@ byte *AGOSEngine::convertImage(VC10_state *state, bool compressed) {
|
||||||
byte *dst = _planarBuf;
|
byte *dst = _planarBuf;
|
||||||
|
|
||||||
if (compressed) {
|
if (compressed) {
|
||||||
convertCompressedImage(src, dst, colorDepth, height, width);
|
convertCompressedImage(src, dst, colorDepth, height, width, (getGameType() == GType_PN));
|
||||||
} else {
|
} else {
|
||||||
length = (width + 15) / 16 * height;
|
length = (width + 15) / 16 * height;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
|
|
|
@ -364,6 +364,8 @@ bool AGOSEngine::loadVGASoundFile(uint16 id, uint8 type) {
|
||||||
sprintf(filename, "%c%d.out", 48 + id, type);
|
sprintf(filename, "%c%d.out", 48 + id, type);
|
||||||
} else if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2) {
|
} else if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2) {
|
||||||
sprintf(filename, "%.2d%d.out", id, type);
|
sprintf(filename, "%.2d%d.out", id, type);
|
||||||
|
} else if (getGameType() == GType_PN) {
|
||||||
|
sprintf(filename, "%c%d.in", id + 48, type);
|
||||||
} else {
|
} else {
|
||||||
sprintf(filename, "%.3d%d.out", id, type);
|
sprintf(filename, "%.3d%d.out", id, type);
|
||||||
}
|
}
|
||||||
|
@ -375,6 +377,8 @@ bool AGOSEngine::loadVGASoundFile(uint16 id, uint8 type) {
|
||||||
sprintf(filename, "%.2d.SND", elvira1_soundTable[id]);
|
sprintf(filename, "%.2d.SND", elvira1_soundTable[id]);
|
||||||
} else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
|
} else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
|
||||||
sprintf(filename, "%.2d%d.VGA", id, type);
|
sprintf(filename, "%.2d%d.VGA", id, type);
|
||||||
|
} else if (getGameType() == GType_PN) {
|
||||||
|
sprintf(filename, "%c%d.out", id + 48, type);
|
||||||
} else {
|
} else {
|
||||||
sprintf(filename, "%.3d%d.VGA", id, type);
|
sprintf(filename, "%.3d%d.VGA", id, type);
|
||||||
}
|
}
|
||||||
|
@ -386,7 +390,19 @@ bool AGOSEngine::loadVGASoundFile(uint16 id, uint8 type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
dstSize = srcSize = in.size();
|
dstSize = srcSize = in.size();
|
||||||
if (getGameType() == GType_ELVIRA1 && getFeatures() & GF_DEMO) {
|
if (getGameType() == GType_PN) {
|
||||||
|
Common::Stack<uint32> data;
|
||||||
|
byte *dataOut = 0;
|
||||||
|
int dataOutSize = 0;
|
||||||
|
|
||||||
|
for (uint i = 0; i < srcSize / 4; ++i)
|
||||||
|
data.push(in.readUint32BE());
|
||||||
|
|
||||||
|
decompressPN(data, dataOut, dataOutSize);
|
||||||
|
dst = allocBlock (dataOutSize);
|
||||||
|
memcpy(dst, dataOut, dataOutSize);
|
||||||
|
delete[] dataOut;
|
||||||
|
} else if (getGameType() == GType_ELVIRA1 && getFeatures() & GF_DEMO) {
|
||||||
byte *srcBuffer = (byte *)malloc(srcSize);
|
byte *srcBuffer = (byte *)malloc(srcSize);
|
||||||
if (in.read(srcBuffer, srcSize) != srcSize)
|
if (in.read(srcBuffer, srcSize) != srcSize)
|
||||||
error("loadVGASoundFile: Read failed");
|
error("loadVGASoundFile: Read failed");
|
||||||
|
@ -457,39 +473,7 @@ void AGOSEngine::loadSoundFile(const char* filename) {
|
||||||
_sound->playSfxData(dst, 0, 0, 0);
|
_sound->playSfxData(dst, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine::loadSound(uint sound) {
|
void AGOSEngine::loadSound(uint16 sound, int16 pan, int16 vol, uint16 type) {
|
||||||
byte *dst;
|
|
||||||
uint32 offs, size;
|
|
||||||
|
|
||||||
if (_curSfxFile == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dst = _curSfxFile;
|
|
||||||
if (getGameType() == GType_WW) {
|
|
||||||
uint tmp = sound;
|
|
||||||
while (tmp--)
|
|
||||||
dst += READ_LE_UINT16(dst) + 4;
|
|
||||||
|
|
||||||
size = READ_LE_UINT16(dst);
|
|
||||||
offs = 4;
|
|
||||||
} else if (getGameType() == GType_ELVIRA2) {
|
|
||||||
while (READ_BE_UINT32(dst + 4) != sound)
|
|
||||||
dst += 12;
|
|
||||||
|
|
||||||
size = READ_BE_UINT32(dst);
|
|
||||||
offs = READ_BE_UINT32(dst + 8);
|
|
||||||
} else {
|
|
||||||
while (READ_BE_UINT16(dst + 6) != sound)
|
|
||||||
dst += 12;
|
|
||||||
|
|
||||||
size = READ_BE_UINT16(dst + 2);
|
|
||||||
offs = READ_BE_UINT32(dst + 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
_sound->playRawData(dst + offs, sound, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AGOSEngine::loadSound(uint sound, int pan, int vol, uint type) {
|
|
||||||
byte *dst;
|
byte *dst;
|
||||||
|
|
||||||
if (getGameId() == GID_DIMP) {
|
if (getGameId() == GID_DIMP) {
|
||||||
|
@ -532,12 +516,67 @@ void AGOSEngine::loadSound(uint sound, int pan, int vol, uint type) {
|
||||||
dst = _curSfxFile + READ_LE_UINT32(_curSfxFile + sound * 4);
|
dst = _curSfxFile + READ_LE_UINT32(_curSfxFile + sound * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == 3)
|
if (type == Sound::TYPE_AMBIENT)
|
||||||
_sound->playSfx5Data(dst, sound, pan, vol);
|
|
||||||
else if (type == 2)
|
|
||||||
_sound->playAmbientData(dst, sound, pan, vol);
|
_sound->playAmbientData(dst, sound, pan, vol);
|
||||||
else
|
else if (type == Sound::TYPE_SFX)
|
||||||
_sound->playSfxData(dst, sound, pan, vol);
|
_sound->playSfxData(dst, sound, pan, vol);
|
||||||
|
else if (type == Sound::TYPE_SFX5)
|
||||||
|
_sound->playSfx5Data(dst, sound, pan, vol);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::loadSound(uint16 sound, uint16 freq, uint16 flags) {
|
||||||
|
byte *dst;
|
||||||
|
uint32 offs, size = 0;
|
||||||
|
|
||||||
|
if (_curSfxFile == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dst = _curSfxFile;
|
||||||
|
if (getGameType() == GType_WW) {
|
||||||
|
uint tmp = sound;
|
||||||
|
while (tmp--) {
|
||||||
|
dst += READ_LE_UINT16(dst) + 4;
|
||||||
|
size += READ_LE_UINT16(dst) + 4;
|
||||||
|
|
||||||
|
if (size > _curSfxFileSize)
|
||||||
|
error("loadSound: Reading beyond EOF");
|
||||||
|
}
|
||||||
|
|
||||||
|
size = READ_LE_UINT16(dst);
|
||||||
|
offs = 4;
|
||||||
|
} else if (getGameType() == GType_ELVIRA2) {
|
||||||
|
while (READ_BE_UINT32(dst + 4) != sound) {
|
||||||
|
dst += 12;
|
||||||
|
size += 12;
|
||||||
|
|
||||||
|
if (size > _curSfxFileSize)
|
||||||
|
error("loadSound: Reading beyond EOF");
|
||||||
|
}
|
||||||
|
|
||||||
|
size = READ_BE_UINT32(dst);
|
||||||
|
offs = READ_BE_UINT32(dst + 8);
|
||||||
|
} else {
|
||||||
|
while (READ_BE_UINT16(dst + 6) != sound) {
|
||||||
|
dst += 12;
|
||||||
|
size += 12;
|
||||||
|
|
||||||
|
if (size > _curSfxFileSize)
|
||||||
|
error("loadSound: Reading beyond EOF");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
size = READ_BE_UINT16(dst + 2);
|
||||||
|
offs = READ_BE_UINT32(dst + 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Handle other sound flags and frequency
|
||||||
|
if (flags == 2 && _sound->isSfxActive()) {
|
||||||
|
_sound->queueSound(dst + offs, sound, size, 8000);
|
||||||
|
} else {
|
||||||
|
if (flags == 0)
|
||||||
|
_sound->stopSfx();
|
||||||
|
_sound->playRawData(dst + offs, sound, size, 8000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine::loadVoice(uint speechId) {
|
void AGOSEngine::loadVoice(uint speechId) {
|
||||||
|
|
|
@ -125,12 +125,21 @@ char *AGOSEngine_Elvira2::genSaveName(int slot) {
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *AGOSEngine::genSaveName(int slot) {
|
char *AGOSEngine_Elvira1::genSaveName(int slot) {
|
||||||
static char buf[20];
|
static char buf[20];
|
||||||
sprintf(buf, "elvira1.%.3d", slot);
|
sprintf(buf, "elvira1.%.3d", slot);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *AGOSEngine::genSaveName(int slot) {
|
||||||
|
static char buf[20];
|
||||||
|
if (getPlatform() == Common::kPlatformPC)
|
||||||
|
sprintf(buf, "pn-pc.%.3d", slot);
|
||||||
|
else
|
||||||
|
sprintf(buf, "pn.%.3d", slot);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
void AGOSEngine::quickLoadOrSave() {
|
void AGOSEngine::quickLoadOrSave() {
|
||||||
// Quick load & save is only supported complete version of Simon the Sorcerer 1/2
|
// Quick load & save is only supported complete version of Simon the Sorcerer 1/2
|
||||||
if (getGameType() == GType_PP || getGameType() == GType_FF ||
|
if (getGameType() == GType_PP || getGameType() == GType_FF ||
|
||||||
|
@ -1544,4 +1553,125 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Personal Nightmare specific
|
||||||
|
bool AGOSEngine_PN::badload(int8 errorNum) {
|
||||||
|
if (errorNum == -2)
|
||||||
|
return 0;
|
||||||
|
/* Load error recovery routine */
|
||||||
|
while (_stackbase != NULL) {
|
||||||
|
/* Clear any stack */
|
||||||
|
dumpstack();
|
||||||
|
}
|
||||||
|
/* Restart from process 1 */
|
||||||
|
longjmp(_loadfail, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::getFilename() {
|
||||||
|
_noScanFlag = 1;
|
||||||
|
clearInputLine();
|
||||||
|
|
||||||
|
memset(_saveFile, 0, sizeof(_saveFile));
|
||||||
|
while (!shouldQuit() && !strlen(_saveFile)) {
|
||||||
|
const char *msg = "File name : ";
|
||||||
|
pcf((unsigned char)'\n');
|
||||||
|
while (*msg)
|
||||||
|
pcf((unsigned char)*msg++);
|
||||||
|
|
||||||
|
interact(_saveFile, 8);
|
||||||
|
pcf((unsigned char)'\n');
|
||||||
|
_noScanFlag = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int AGOSEngine_PN::loadfl(char *name) {
|
||||||
|
Common::InSaveFile *f;
|
||||||
|
haltAnimation();
|
||||||
|
|
||||||
|
f = _saveFileMan->openForLoading(name);
|
||||||
|
if (f == NULL) {
|
||||||
|
restartAnimation();
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
f->read(_saveFile, 8);
|
||||||
|
|
||||||
|
if (f->readByte() != 41) {
|
||||||
|
restartAnimation();
|
||||||
|
delete f;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (f->readByte() != 33) {
|
||||||
|
restartAnimation();
|
||||||
|
delete f;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
// TODO: Make endian safe
|
||||||
|
if (!f->read(_dataBase + _quickptr[2], (int)(_quickptr[6] - _quickptr[2]))) {
|
||||||
|
restartAnimation();
|
||||||
|
delete f;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
delete f;
|
||||||
|
restartAnimation();
|
||||||
|
dbtosysf();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AGOSEngine_PN::savfl(char *name) {
|
||||||
|
Common::OutSaveFile *f;
|
||||||
|
sysftodb();
|
||||||
|
haltAnimation();
|
||||||
|
|
||||||
|
f = _saveFileMan->openForSaving(name);
|
||||||
|
if (f == NULL) {
|
||||||
|
restartAnimation();
|
||||||
|
|
||||||
|
const char *msg = "Couldn't save. ";
|
||||||
|
pcf((unsigned char)'\n');
|
||||||
|
while (*msg)
|
||||||
|
pcf((unsigned char)*msg++);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
f->write(_saveFile, 8);
|
||||||
|
|
||||||
|
f->writeByte(41);
|
||||||
|
f->writeByte(33);
|
||||||
|
// TODO: Make endian safe
|
||||||
|
if (!f->write(_dataBase + _quickptr[2], (int)(_quickptr[6] - _quickptr[2]))) {
|
||||||
|
delete f;
|
||||||
|
restartAnimation();
|
||||||
|
error("Couldn't save ");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
f->finalize();
|
||||||
|
delete f;
|
||||||
|
|
||||||
|
restartAnimation();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::sysftodb() {
|
||||||
|
uint32 pos = _quickptr[2];
|
||||||
|
int ct = 0;
|
||||||
|
|
||||||
|
while (ct < (getptr(49L) / 2)) {
|
||||||
|
_dataBase[pos] = (uint8)(_variableArray[ct] % 256);
|
||||||
|
_dataBase[pos + 1] = (uint8)(_variableArray[ct] / 256);
|
||||||
|
pos+=2;
|
||||||
|
ct++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::dbtosysf() {
|
||||||
|
uint32 pos = _quickptr[2];
|
||||||
|
int ct = 0;
|
||||||
|
|
||||||
|
while (ct < (getptr(49L) / 2)) {
|
||||||
|
_variableArray[ct] = _dataBase[pos] + 256 * _dataBase[pos + 1];
|
||||||
|
pos += 2;
|
||||||
|
ct++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace AGOS
|
} // End of namespace AGOS
|
||||||
|
|
|
@ -574,9 +574,7 @@ void AGOSEngine_Elvira2::oe2_ifExitLocked() {
|
||||||
void AGOSEngine_Elvira2::oe2_playEffect() {
|
void AGOSEngine_Elvira2::oe2_playEffect() {
|
||||||
// 174: play sound
|
// 174: play sound
|
||||||
uint soundId = getVarOrWord();
|
uint soundId = getVarOrWord();
|
||||||
loadSound(soundId);
|
loadSound(soundId, 0, 0);
|
||||||
|
|
||||||
debug(0, "oe2_playEffect: stub (%d)", soundId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine_Elvira2::oe2_getDollar2() {
|
void AGOSEngine_Elvira2::oe2_getDollar2() {
|
||||||
|
@ -636,7 +634,7 @@ void AGOSEngine_Elvira2::oe2_printMonsterDamage() {
|
||||||
void AGOSEngine_Elvira2::oe2_isAdjNoun() {
|
void AGOSEngine_Elvira2::oe2_isAdjNoun() {
|
||||||
// 179: item unk1 unk2 is
|
// 179: item unk1 unk2 is
|
||||||
Item *item = getNextItemPtr();
|
Item *item = getNextItemPtr();
|
||||||
int16 a = getNextWord(), b = getNextWord();
|
int16 a = getNextWord(), n = getNextWord();
|
||||||
|
|
||||||
if (getGameType() == GType_ELVIRA2) {
|
if (getGameType() == GType_ELVIRA2) {
|
||||||
// WORKAROUND bug #1745996: A NULL item can occur when
|
// WORKAROUND bug #1745996: A NULL item can occur when
|
||||||
|
@ -647,7 +645,7 @@ void AGOSEngine_Elvira2::oe2_isAdjNoun() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setScriptCondition(item->adjective == a && item->noun == b);
|
setScriptCondition(item->adjective == a && item->noun == n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine_Elvira2::oe2_b2Set() {
|
void AGOSEngine_Elvira2::oe2_b2Set() {
|
||||||
|
|
1109
engines/agos/script_pn.cpp
Normal file
1109
engines/agos/script_pn.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -389,6 +389,11 @@ Sound::Sound(AGOSEngine *vm, const GameSpecificSettings *gss, Audio::Mixer *mixe
|
||||||
|
|
||||||
_ambientPlaying = 0;
|
_ambientPlaying = 0;
|
||||||
|
|
||||||
|
_soundQueuePtr = 0;
|
||||||
|
_soundQueueNum = 0;
|
||||||
|
_soundQueueSize = 0;
|
||||||
|
_soundQueueFreq = 0;
|
||||||
|
|
||||||
if (_vm->getFeatures() & GF_TALKIE) {
|
if (_vm->getFeatures() & GF_TALKIE) {
|
||||||
loadVoiceFile(gss);
|
loadVoiceFile(gss);
|
||||||
|
|
||||||
|
@ -649,6 +654,10 @@ bool Sound::hasVoice() const {
|
||||||
return _hasVoiceFile;
|
return _hasVoiceFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Sound::isSfxActive() const {
|
||||||
|
return _mixer->isSoundHandleActive(_effectsHandle);
|
||||||
|
}
|
||||||
|
|
||||||
bool Sound::isVoiceActive() const {
|
bool Sound::isVoiceActive() const {
|
||||||
return _mixer->isSoundHandleActive(_voiceHandle);
|
return _mixer->isSoundHandleActive(_voiceHandle);
|
||||||
}
|
}
|
||||||
|
@ -660,6 +669,10 @@ void Sound::stopAllSfx() {
|
||||||
_ambientPlaying = 0;
|
_ambientPlaying = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sound::stopSfx() {
|
||||||
|
_mixer->stopHandle(_effectsHandle);
|
||||||
|
}
|
||||||
|
|
||||||
void Sound::stopVoice() {
|
void Sound::stopVoice() {
|
||||||
_mixer->stopHandle(_voiceHandle);
|
_mixer->stopHandle(_voiceHandle);
|
||||||
}
|
}
|
||||||
|
@ -686,8 +699,33 @@ void Sound::ambientPause(bool b) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Personal Nightmare specific
|
||||||
|
void Sound::handleSound() {
|
||||||
|
if (_soundQueuePtr && !isSfxActive()) {
|
||||||
|
playRawData(_soundQueuePtr, _soundQueueNum, _soundQueueSize, _soundQueueFreq);
|
||||||
|
|
||||||
|
_vm->_sampleWait = 1;
|
||||||
|
_vm->_sampleEnd = 1;
|
||||||
|
_soundQueuePtr = 0;
|
||||||
|
_soundQueueNum = 0;
|
||||||
|
_soundQueueSize = 0;
|
||||||
|
_soundQueueFreq = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sound::queueSound(byte *ptr, uint16 sound, uint32 size, uint16 freq) {
|
||||||
|
if (_effectsPaused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Only a single sound can be queued
|
||||||
|
_soundQueuePtr = ptr;
|
||||||
|
_soundQueueNum = sound;
|
||||||
|
_soundQueueSize = size;
|
||||||
|
_soundQueueFreq = freq;
|
||||||
|
}
|
||||||
|
|
||||||
// Elvira 1/2 and Waxworks specific
|
// Elvira 1/2 and Waxworks specific
|
||||||
void Sound::playRawData(byte *soundData, uint sound, uint size) {
|
void Sound::playRawData(byte *soundData, uint sound, uint size, uint freq) {
|
||||||
if (_effectsPaused)
|
if (_effectsPaused)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -695,9 +733,9 @@ void Sound::playRawData(byte *soundData, uint sound, uint size) {
|
||||||
memcpy(buffer, soundData, size);
|
memcpy(buffer, soundData, size);
|
||||||
|
|
||||||
if (_vm->getPlatform() == Common::kPlatformPC)
|
if (_vm->getPlatform() == Common::kPlatformPC)
|
||||||
_mixer->playRaw(Audio::Mixer::kSFXSoundType, &_effectsHandle, buffer, size, 8000, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_AUTOFREE);
|
_mixer->playRaw(Audio::Mixer::kSFXSoundType, &_effectsHandle, buffer, size, freq, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_AUTOFREE);
|
||||||
else
|
else
|
||||||
_mixer->playRaw(Audio::Mixer::kSFXSoundType, &_effectsHandle, buffer, size, 8000, Audio::Mixer::FLAG_AUTOFREE);
|
_mixer->playRaw(Audio::Mixer::kSFXSoundType, &_effectsHandle, buffer, size, freq, Audio::Mixer::FLAG_AUTOFREE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Feeble Files specific
|
// Feeble Files specific
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#ifndef AGOS_SOUND_H
|
#ifndef AGOS_SOUND_H
|
||||||
#define AGOS_SOUND_H
|
#define AGOS_SOUND_H
|
||||||
|
|
||||||
|
#include "sound/audiostream.h"
|
||||||
#include "sound/mixer.h"
|
#include "sound/mixer.h"
|
||||||
#include "agos/intern.h"
|
#include "agos/intern.h"
|
||||||
#include "common/str.h"
|
#include "common/str.h"
|
||||||
|
@ -60,12 +61,23 @@ private:
|
||||||
|
|
||||||
bool _hasEffectsFile;
|
bool _hasEffectsFile;
|
||||||
bool _hasVoiceFile;
|
bool _hasVoiceFile;
|
||||||
uint _ambientPlaying;
|
uint16 _ambientPlaying;
|
||||||
|
|
||||||
|
// Personal Nightmare specfic
|
||||||
|
byte *_soundQueuePtr;
|
||||||
|
uint16 _soundQueueNum;
|
||||||
|
uint32 _soundQueueSize;
|
||||||
|
uint16 _soundQueueFreq;
|
||||||
public:
|
public:
|
||||||
Sound(AGOSEngine *vm, const GameSpecificSettings *gss, Audio::Mixer *mixer);
|
Sound(AGOSEngine *vm, const GameSpecificSettings *gss, Audio::Mixer *mixer);
|
||||||
~Sound();
|
~Sound();
|
||||||
|
|
||||||
|
enum TypeFlags {
|
||||||
|
TYPE_AMBIENT = 1 << 0,
|
||||||
|
TYPE_SFX = 1 << 1,
|
||||||
|
TYPE_SFX5 = 1 << 2
|
||||||
|
};
|
||||||
|
|
||||||
void loadVoiceFile(const GameSpecificSettings *gss);
|
void loadVoiceFile(const GameSpecificSettings *gss);
|
||||||
void loadSfxFile(const GameSpecificSettings *gss);
|
void loadSfxFile(const GameSpecificSettings *gss);
|
||||||
|
|
||||||
|
@ -77,8 +89,12 @@ public:
|
||||||
void playEffects(uint sound);
|
void playEffects(uint sound);
|
||||||
void playAmbient(uint sound);
|
void playAmbient(uint sound);
|
||||||
|
|
||||||
|
// Personal Nightmare specfic
|
||||||
|
void handleSound();
|
||||||
|
void queueSound(byte *ptr, uint16 sound, uint32 size, uint16 freq);
|
||||||
|
|
||||||
// Elvira 1/2 and Waxworks specific
|
// Elvira 1/2 and Waxworks specific
|
||||||
void playRawData(byte *soundData, uint sound, uint size);
|
void playRawData(byte *soundData, uint sound, uint size, uint freq);
|
||||||
|
|
||||||
// Feeble Files specific
|
// Feeble Files specific
|
||||||
void playAmbientData(byte *soundData, uint sound, uint pan, uint vol);
|
void playAmbientData(byte *soundData, uint sound, uint pan, uint vol);
|
||||||
|
@ -89,8 +105,10 @@ public:
|
||||||
void switchVoiceFile(const GameSpecificSettings *gss, uint disc);
|
void switchVoiceFile(const GameSpecificSettings *gss, uint disc);
|
||||||
|
|
||||||
bool hasVoice() const;
|
bool hasVoice() const;
|
||||||
|
bool isSfxActive() const;
|
||||||
bool isVoiceActive() const;
|
bool isVoiceActive() const;
|
||||||
void stopAllSfx();
|
void stopAllSfx();
|
||||||
|
void stopSfx();
|
||||||
void stopSfx5();
|
void stopSfx5();
|
||||||
void stopVoice();
|
void stopVoice();
|
||||||
void stopAll();
|
void stopAll();
|
||||||
|
|
|
@ -910,4 +910,649 @@ void AGOSEngine_Waxworks::printBox() {
|
||||||
changeWindow(0);
|
changeWindow(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Personal Nightmare specific
|
||||||
|
|
||||||
|
uint32 AGOSEngine_PN::ftext(uint32 base, int n) {
|
||||||
|
uint32 b = base;
|
||||||
|
int ct = n;
|
||||||
|
while (ct) {
|
||||||
|
while(_textBase[b++]);
|
||||||
|
ct--;
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *AGOSEngine_PN::unctok(char *c, int n) {
|
||||||
|
int x;
|
||||||
|
uint8 *tokbase;
|
||||||
|
tokbase = _textBase + getlong(30);
|
||||||
|
x = n;
|
||||||
|
while (x-=(*tokbase++ > 127));
|
||||||
|
while (*tokbase < 128)
|
||||||
|
*c++=*tokbase++;
|
||||||
|
*c++ = *tokbase & 127;
|
||||||
|
*c = 0;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::uncomstr(char *c, uint32 x) {
|
||||||
|
if (x > _textBaseSize)
|
||||||
|
error("UNCOMSTR: TBASE over-run\n");
|
||||||
|
while (_textBase[x]) {
|
||||||
|
if (_textBase[x] < 244) {
|
||||||
|
c = unctok(c, _textBase[x]);
|
||||||
|
} else {
|
||||||
|
c = unctok(c, (_textBase[x] - 244) * 254 + _textBase[x + 1] - 1);
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
*c++ = 13;
|
||||||
|
*c = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *objectNames[30] = {
|
||||||
|
"\0",
|
||||||
|
"Take \0",
|
||||||
|
"Inventory\r",
|
||||||
|
"Open \0",
|
||||||
|
"Close \0",
|
||||||
|
"Lock \0",
|
||||||
|
"Unlock \0",
|
||||||
|
"Examine \0",
|
||||||
|
"Look in \0",
|
||||||
|
"Exits \r",
|
||||||
|
"Look\r",
|
||||||
|
"Wait\r",
|
||||||
|
"Pause\r",
|
||||||
|
"\0",
|
||||||
|
"Save\r",
|
||||||
|
"Restore\r",
|
||||||
|
"\0",
|
||||||
|
"N\r",
|
||||||
|
"NE\r",
|
||||||
|
"E\r",
|
||||||
|
"SE\r",
|
||||||
|
"S\r",
|
||||||
|
"SW\r",
|
||||||
|
"W\r",
|
||||||
|
"NW\r",
|
||||||
|
"INVENTORY\r",
|
||||||
|
"ROOM DESCRIPTION\r",
|
||||||
|
"x\r",
|
||||||
|
"MORE\r",
|
||||||
|
"CLOSE\r"
|
||||||
|
};
|
||||||
|
|
||||||
|
void AGOSEngine_PN::getObjectName(char *v, uint16 x) {
|
||||||
|
if (x & 0x8000) {
|
||||||
|
x &= ~0x8000;
|
||||||
|
if (x > getptr(51))
|
||||||
|
error("getObjectName: Object %d out of range", x);
|
||||||
|
uncomstr(v, ftext(getlong(27), x * _dataBase[47]));
|
||||||
|
} else {
|
||||||
|
assert(x < 30);
|
||||||
|
strcpy(v, objectNames[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::pcl(const char *s) {
|
||||||
|
strcat(_sb, s);
|
||||||
|
if (strchr(s, '\n') == 0) {
|
||||||
|
for (char *str = _sb; *str; str++)
|
||||||
|
windowPutChar(_windowArray[_curWindow], *str);
|
||||||
|
strcpy(_sb, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::pcf(uint8 ch) {
|
||||||
|
int ct = 0;
|
||||||
|
if (ch == '[')
|
||||||
|
ch = '\n';
|
||||||
|
if (ch == 0)
|
||||||
|
return; /* Trap any C EOS chrs */
|
||||||
|
if (ch == 255) {
|
||||||
|
_bp = 0;
|
||||||
|
_xofs = 0;
|
||||||
|
return; /* pcf(255) initialises the routine */
|
||||||
|
} /* pcf(254) flushes its working _buffer */
|
||||||
|
if (ch != 254) {
|
||||||
|
if ((ch != 32) || (_bp + _xofs != 50))
|
||||||
|
_buffer[_bp++] = ch;
|
||||||
|
}
|
||||||
|
if ((ch != 254) && (!isspace(ch)) && (_bp < 60))
|
||||||
|
return;
|
||||||
|
/* We know have a case of needing to print the text */
|
||||||
|
if (_bp + _xofs > 50) {
|
||||||
|
pcl("\n");
|
||||||
|
if (_buffer[0] == ' ')
|
||||||
|
ct = 1; /* Skip initial space */
|
||||||
|
/* Note ' ' will give a single start of line space */
|
||||||
|
_xofs = 0;
|
||||||
|
}
|
||||||
|
_buffer[_bp] = 0;
|
||||||
|
pcl(_buffer + ct);
|
||||||
|
_xofs += _bp;
|
||||||
|
_bp = 0;
|
||||||
|
if (ch == '\n')
|
||||||
|
_xofs = 0; /* At Newline! */
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::patok(int n) {
|
||||||
|
int x;
|
||||||
|
uint8 *tokbase;
|
||||||
|
tokbase = _textBase + getlong(30);
|
||||||
|
x = n;
|
||||||
|
while (x -= (*tokbase++ > 127));
|
||||||
|
while (*tokbase < 128)
|
||||||
|
pcf(*tokbase++);
|
||||||
|
pcf((uint8)(*tokbase & 127));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::pmesd(int n) {
|
||||||
|
ptext(ftext(getlong(24), n));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::plocd(int n, int m) {
|
||||||
|
if (n > getptr(53))
|
||||||
|
error("Location out of range");
|
||||||
|
ptext(ftext(getlong(21), n * _dataBase[48] + m));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::pobjd(int n, int m) {
|
||||||
|
if (n > getptr(51))
|
||||||
|
error("Object out of range");
|
||||||
|
ptext(ftext(getlong(27), n * _dataBase[47] + m));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::ptext(uint32 tptr) {
|
||||||
|
if (tptr > _textBaseSize)
|
||||||
|
error("ptext: attempt to print beyond end of TBASE\n");
|
||||||
|
|
||||||
|
while (_textBase[tptr]) {
|
||||||
|
if (_textBase[tptr] < 244) {
|
||||||
|
patok(_textBase[tptr++]);
|
||||||
|
} else {
|
||||||
|
patok((_textBase[tptr] - 244) * 254 + _textBase[tptr + 1] - 1);
|
||||||
|
tptr += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8 characters[11][80] = {
|
||||||
|
// PETERMASON
|
||||||
|
{
|
||||||
|
118, 225,
|
||||||
|
91, 118,
|
||||||
|
94, 124,
|
||||||
|
236, 161,
|
||||||
|
241, 166,
|
||||||
|
168, 4,
|
||||||
|
138, 46,
|
||||||
|
139, 46,
|
||||||
|
249, 50,
|
||||||
|
38, 56,
|
||||||
|
80, 59,
|
||||||
|
149, 69,
|
||||||
|
37, 77,
|
||||||
|
93, 93,
|
||||||
|
86, 95,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
58, 130,
|
||||||
|
62, 178,
|
||||||
|
83, 95,
|
||||||
|
0,
|
||||||
|
121, 58,
|
||||||
|
122, 59,
|
||||||
|
126, 60,
|
||||||
|
124, 61,
|
||||||
|
240, 62,
|
||||||
|
123, 63,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// JBLANDFORD
|
||||||
|
{
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// SBLANDFORD
|
||||||
|
{
|
||||||
|
120, 223,
|
||||||
|
94, 126,
|
||||||
|
112, 134,
|
||||||
|
45, 152,
|
||||||
|
241, 166,
|
||||||
|
168, 3,
|
||||||
|
150, 26,
|
||||||
|
220, 29,
|
||||||
|
138, 42,
|
||||||
|
139, 47,
|
||||||
|
249, 50,
|
||||||
|
38, 56,
|
||||||
|
230, 64,
|
||||||
|
37, 77,
|
||||||
|
93, 94,
|
||||||
|
86, 96,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
58, 129,
|
||||||
|
59, 112,
|
||||||
|
83, 96,
|
||||||
|
81, 106,
|
||||||
|
62, 169,
|
||||||
|
0,
|
||||||
|
121, 54,
|
||||||
|
122, 55,
|
||||||
|
119, 56,
|
||||||
|
118, 57,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// MRJONES
|
||||||
|
{
|
||||||
|
121, 218,
|
||||||
|
91, 118,
|
||||||
|
253, 121,
|
||||||
|
154, 138,
|
||||||
|
235, 173,
|
||||||
|
236, 161,
|
||||||
|
241, 165,
|
||||||
|
168, 0,
|
||||||
|
150, 21,
|
||||||
|
36, 33,
|
||||||
|
138, 42,
|
||||||
|
249, 50,
|
||||||
|
80, 60,
|
||||||
|
4, 60,
|
||||||
|
37, 78,
|
||||||
|
68, 33,
|
||||||
|
93, 92,
|
||||||
|
101, 109,
|
||||||
|
0,
|
||||||
|
36, 35,
|
||||||
|
68, 90,
|
||||||
|
0,
|
||||||
|
58, 128,
|
||||||
|
59, 111,
|
||||||
|
62, 182,
|
||||||
|
0,
|
||||||
|
122, 13,
|
||||||
|
126, 14,
|
||||||
|
124, 15,
|
||||||
|
240, 16,
|
||||||
|
120, 17,
|
||||||
|
119, 18,
|
||||||
|
118, 19,
|
||||||
|
52, 20,
|
||||||
|
125, 21,
|
||||||
|
127, 22,
|
||||||
|
123, 23,
|
||||||
|
117, 24,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// MRSJONES
|
||||||
|
{
|
||||||
|
122, 219,
|
||||||
|
91, 119,
|
||||||
|
253, 123,
|
||||||
|
112, 136,
|
||||||
|
154, 137,
|
||||||
|
95, 142,
|
||||||
|
45, 152,
|
||||||
|
109, 155,
|
||||||
|
235, 160,
|
||||||
|
168, 1,
|
||||||
|
151, 13,
|
||||||
|
145, 15,
|
||||||
|
150, 22,
|
||||||
|
220, 28,
|
||||||
|
36, 33,
|
||||||
|
138, 43,
|
||||||
|
13, 51,
|
||||||
|
80, 59,
|
||||||
|
230, 64,
|
||||||
|
149, 69,
|
||||||
|
86, 100,
|
||||||
|
0,
|
||||||
|
36, 36,
|
||||||
|
0,
|
||||||
|
58, 127,
|
||||||
|
62, 179,
|
||||||
|
83, 100,
|
||||||
|
81, 102,
|
||||||
|
0,
|
||||||
|
121, 25,
|
||||||
|
126, 26,
|
||||||
|
124, 27,
|
||||||
|
120, 28,
|
||||||
|
119, 29,
|
||||||
|
118, 30,
|
||||||
|
52, 31,
|
||||||
|
125, 32,
|
||||||
|
127, 33,
|
||||||
|
123, 34,
|
||||||
|
117, 35,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// MRROBERTS
|
||||||
|
{
|
||||||
|
123, 229,
|
||||||
|
91, 117,
|
||||||
|
253, 120,
|
||||||
|
94, 125,
|
||||||
|
112, 134,
|
||||||
|
109, 156,
|
||||||
|
235, 172,
|
||||||
|
236, 162,
|
||||||
|
241, 165,
|
||||||
|
168, 3,
|
||||||
|
36, 33,
|
||||||
|
249, 50,
|
||||||
|
38, 56,
|
||||||
|
80, 58,
|
||||||
|
37, 75,
|
||||||
|
34, 81,
|
||||||
|
68, 33,
|
||||||
|
101, 109,
|
||||||
|
0,
|
||||||
|
36, 40,
|
||||||
|
68, 88,
|
||||||
|
0,
|
||||||
|
59, 111,
|
||||||
|
62, 181,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// POSTMISTRESS
|
||||||
|
{
|
||||||
|
124, 221,
|
||||||
|
91, 119,
|
||||||
|
253, 122,
|
||||||
|
112, 136,
|
||||||
|
95, 142,
|
||||||
|
130, 149,
|
||||||
|
109, 155,
|
||||||
|
235, 176,
|
||||||
|
220, 29,
|
||||||
|
36, 33,
|
||||||
|
138, 43,
|
||||||
|
13, 51,
|
||||||
|
80, 57,
|
||||||
|
149, 68,
|
||||||
|
37, 73,
|
||||||
|
34, 33,
|
||||||
|
68, 33,
|
||||||
|
86, 100,
|
||||||
|
0,
|
||||||
|
36, 39,
|
||||||
|
34, 80,
|
||||||
|
68, 86,
|
||||||
|
0,
|
||||||
|
58, 130,
|
||||||
|
62, 181,
|
||||||
|
83, 100,
|
||||||
|
81, 103,
|
||||||
|
0,
|
||||||
|
121, 41,
|
||||||
|
122, 42,
|
||||||
|
126, 43,
|
||||||
|
240, 44,
|
||||||
|
120, 45,
|
||||||
|
119, 46,
|
||||||
|
118, 47,
|
||||||
|
52, 48,
|
||||||
|
123, 49,
|
||||||
|
83, 50,
|
||||||
|
117, 51,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// MWILLIAMS
|
||||||
|
{
|
||||||
|
125, 227,
|
||||||
|
94, 124,
|
||||||
|
95, 141,
|
||||||
|
241, 166,
|
||||||
|
168, 4,
|
||||||
|
150, 26,
|
||||||
|
38, 54,
|
||||||
|
4, 60,
|
||||||
|
230, 65,
|
||||||
|
149, 68,
|
||||||
|
37, 76,
|
||||||
|
101, 109,
|
||||||
|
0,
|
||||||
|
230, 63,
|
||||||
|
0,
|
||||||
|
59, 112,
|
||||||
|
62, 183,
|
||||||
|
0,
|
||||||
|
240, 71,
|
||||||
|
120, 72,
|
||||||
|
118, 73,
|
||||||
|
52, 74,
|
||||||
|
117, 75,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// TONY
|
||||||
|
{
|
||||||
|
126, 220,
|
||||||
|
95, 143,
|
||||||
|
130, 149,
|
||||||
|
45, 153,
|
||||||
|
109, 154,
|
||||||
|
235, 158,
|
||||||
|
241, 166,
|
||||||
|
168, 2,
|
||||||
|
145, 15,
|
||||||
|
150, 24,
|
||||||
|
220, 20,
|
||||||
|
36, 20,
|
||||||
|
4, 60,
|
||||||
|
37, 79,
|
||||||
|
86, 97,
|
||||||
|
0,
|
||||||
|
150, 23,
|
||||||
|
220, 27,
|
||||||
|
36, 34,
|
||||||
|
0,
|
||||||
|
83, 97,
|
||||||
|
0,
|
||||||
|
121, 36,
|
||||||
|
122, 37,
|
||||||
|
124, 38,
|
||||||
|
240, 39,
|
||||||
|
52, 40,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// PIG
|
||||||
|
{
|
||||||
|
127, 228,
|
||||||
|
112, 133,
|
||||||
|
45, 153,
|
||||||
|
235, 157,
|
||||||
|
236, 163,
|
||||||
|
241, 165,
|
||||||
|
36, 33,
|
||||||
|
80, 58,
|
||||||
|
34, 81,
|
||||||
|
68, 33,
|
||||||
|
86, 98,
|
||||||
|
0,
|
||||||
|
36, 37,
|
||||||
|
68, 90,
|
||||||
|
0,
|
||||||
|
62, 184,
|
||||||
|
83, 98,
|
||||||
|
0,
|
||||||
|
121, 76,
|
||||||
|
122, 77,
|
||||||
|
126, 78,
|
||||||
|
124, 79,
|
||||||
|
240, 80,
|
||||||
|
120, 81,
|
||||||
|
118, 82,
|
||||||
|
52, 83,
|
||||||
|
125, 84,
|
||||||
|
123, 85,
|
||||||
|
83, 86,
|
||||||
|
117, 87,
|
||||||
|
0
|
||||||
|
},
|
||||||
|
// JUDY
|
||||||
|
{
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
240, 52,
|
||||||
|
117, 53,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void AGOSEngine_PN::getResponse(uint16 charNum, uint16 objNum, uint16 &msgNum1, uint16 &msgNum2) {
|
||||||
|
const uint8 *ptr;
|
||||||
|
uint16 num;
|
||||||
|
|
||||||
|
msgNum1 = 0;
|
||||||
|
msgNum2 = 0;
|
||||||
|
|
||||||
|
if (charNum == 83)
|
||||||
|
charNum += 45;
|
||||||
|
|
||||||
|
if (charNum < 118 || charNum > 128) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = characters[charNum - 118];
|
||||||
|
|
||||||
|
while ((num = *ptr++) != 0) {
|
||||||
|
if (num == objNum) {
|
||||||
|
msgNum1 = *ptr++;
|
||||||
|
msgNum1 += 400;
|
||||||
|
|
||||||
|
while ((num = *ptr++) != 0)
|
||||||
|
ptr++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((num = *ptr++) != 0) {
|
||||||
|
if (num == objNum) {
|
||||||
|
msgNum2 = *ptr++;
|
||||||
|
msgNum2 += 400;
|
||||||
|
|
||||||
|
if (msgNum1 == 569)
|
||||||
|
msgNum1 += 400;
|
||||||
|
if (msgNum2 == 0)
|
||||||
|
msgNum2 = msgNum1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objNum >= 200)
|
||||||
|
msgNum1 = 0;
|
||||||
|
|
||||||
|
objNum -= 200;
|
||||||
|
while ((num = *ptr++) != 0) {
|
||||||
|
if (num == objNum) {
|
||||||
|
msgNum1 = *ptr++;
|
||||||
|
msgNum1 += 400;
|
||||||
|
|
||||||
|
if (msgNum1 == 569)
|
||||||
|
msgNum1 += 400;
|
||||||
|
if (msgNum2 == 0)
|
||||||
|
msgNum2 = msgNum1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
objNum += 200;
|
||||||
|
while ((num = *ptr++) != 0) {
|
||||||
|
if (num == objNum) {
|
||||||
|
msgNum1 = *ptr++;
|
||||||
|
msgNum1 += 200;
|
||||||
|
|
||||||
|
if (msgNum1 == 569)
|
||||||
|
msgNum1 += 400;
|
||||||
|
if (msgNum2 == 0)
|
||||||
|
msgNum2 = msgNum1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msgNum1 == 569)
|
||||||
|
msgNum1 += 400;
|
||||||
|
if (msgNum2 == 0)
|
||||||
|
msgNum2 = msgNum1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *AGOSEngine_PN::getMessage(char *msg, uint16 num) {
|
||||||
|
char *origPtr, *strPtr2, *strPtr1 = msg;
|
||||||
|
uint8 count;
|
||||||
|
|
||||||
|
getObjectName(strPtr1, num);
|
||||||
|
if (!(num & 0x8000)) {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strPtr1[0] == 0x41 || strPtr1[0] == 0x61) {
|
||||||
|
if (strPtr1[1] != 0x20)
|
||||||
|
strPtr1 += 2;
|
||||||
|
} else if (strPtr1[0] == 0x54 || strPtr1[0] == 0x74) {
|
||||||
|
if (strPtr1[1] == 0x68 &&
|
||||||
|
strPtr1[2] == 0x65 &&
|
||||||
|
strPtr1[3] == 0x20)
|
||||||
|
strPtr1 += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
origPtr = strPtr1;
|
||||||
|
while (strPtr1[0] != 13)
|
||||||
|
strPtr1++;
|
||||||
|
|
||||||
|
strPtr1[0] = 32;
|
||||||
|
strPtr1[1] = 13;
|
||||||
|
strPtr1[2] = 0;
|
||||||
|
|
||||||
|
if (_lockWord & 0x10) {
|
||||||
|
strPtr1 = origPtr;
|
||||||
|
count = 6;
|
||||||
|
while (strPtr1[0] != 0) {
|
||||||
|
if (strPtr1[0] == 32) {
|
||||||
|
count = 6;
|
||||||
|
} else {
|
||||||
|
count--;
|
||||||
|
if (count == 0) {
|
||||||
|
char *tmpPtr = strPtr1;
|
||||||
|
strPtr2 = strPtr1;
|
||||||
|
|
||||||
|
while (strPtr2[0] != 0 && strPtr2[0] != 32)
|
||||||
|
strPtr2++;
|
||||||
|
|
||||||
|
while (strPtr2[0] != 0) {
|
||||||
|
strPtr1[0] = strPtr2[0];
|
||||||
|
strPtr2++;
|
||||||
|
strPtr1++;
|
||||||
|
}
|
||||||
|
|
||||||
|
strPtr1[0] = strPtr2[0];
|
||||||
|
strPtr2++;
|
||||||
|
strPtr1++;
|
||||||
|
|
||||||
|
strPtr1 = tmpPtr;
|
||||||
|
count = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strPtr1++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return origPtr;
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace AGOS
|
} // End of namespace AGOS
|
||||||
|
|
|
@ -496,6 +496,18 @@ bool AGOSEngine::isBoxDead(uint hitarea) {
|
||||||
return (ha->flags & kBFBoxDead) == 0;
|
return (ha->flags & kBFBoxDead) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::defineBox(uint16 id, uint16 x, uint16 y, uint16 height, uint16 width, uint16 msg1, uint16 msg2, uint16 flags) {
|
||||||
|
HitArea *ha = _hitAreaList + id;
|
||||||
|
ha->x = x;
|
||||||
|
ha->y = y;
|
||||||
|
ha->width = width;
|
||||||
|
ha->height = height;
|
||||||
|
ha->msg1 = msg1;
|
||||||
|
ha->msg2 = msg2;
|
||||||
|
ha->flags = flags;
|
||||||
|
ha->id = ha->priority = id;
|
||||||
|
}
|
||||||
|
|
||||||
void AGOSEngine::defineBox(int id, int x, int y, int width, int height, int flags, int verb, Item *itemPtr) {
|
void AGOSEngine::defineBox(int id, int x, int y, int width, int height, int flags, int verb, Item *itemPtr) {
|
||||||
HitArea *ha;
|
HitArea *ha;
|
||||||
undefineBox(id);
|
undefineBox(id);
|
||||||
|
@ -985,6 +997,18 @@ void AGOSEngine::invertBox(HitArea *ha, byte a, byte b, byte c, byte d) {
|
||||||
color ^= 2;
|
color ^= 2;
|
||||||
src[i] = color;
|
src[i] = color;
|
||||||
}
|
}
|
||||||
|
} else if (getGameType() == GType_PN) {
|
||||||
|
if (getPlatform() == Common::kPlatformPC) {
|
||||||
|
if (color != 15) {
|
||||||
|
color ^= 7;
|
||||||
|
src[i] = color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (color != 14) {
|
||||||
|
color ^= 15;
|
||||||
|
src[i] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (a >= color && b < color) {
|
if (a >= color && b < color) {
|
||||||
if (c >= color)
|
if (c >= color)
|
||||||
|
@ -1003,4 +1027,263 @@ void AGOSEngine::invertBox(HitArea *ha, byte a, byte b, byte c, byte d) {
|
||||||
_lockWord &= ~0x8000;
|
_lockWord &= ~0x8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Personal Nightmare specific
|
||||||
|
void AGOSEngine_PN::boxController(uint x, uint y, uint mode) {
|
||||||
|
HitArea *best_ha;
|
||||||
|
HitArea *ha = _hitAreaList;
|
||||||
|
|
||||||
|
best_ha = NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!(ha->flags & kOBFBoxDisabled)) {
|
||||||
|
if (x >= ha->x && y >= ha->y && x - ha->x < ha->width && y - ha->y < ha->height &&
|
||||||
|
best_ha == NULL) {
|
||||||
|
best_ha = ha;
|
||||||
|
} else {
|
||||||
|
if (ha->flags & kOBFBoxSelected) {
|
||||||
|
hitarea_leave(ha , true);
|
||||||
|
ha->flags &= ~kOBFBoxSelected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ha->flags &= ~kOBFBoxSelected;
|
||||||
|
}
|
||||||
|
} while (ha++, ha->id != 0xFFFF);
|
||||||
|
|
||||||
|
if (mode != 0) {
|
||||||
|
_lastHitArea = best_ha;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (best_ha == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (best_ha->flags & kOBFInvertTouch && !(best_ha->flags & kOBFBoxSelected)) {
|
||||||
|
hitarea_leave(best_ha, false);
|
||||||
|
best_ha->flags |= kOBFBoxSelected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::mouseHit() {
|
||||||
|
if (_hitCalled == 5) {
|
||||||
|
execMouseHit(NULL);
|
||||||
|
} else {
|
||||||
|
boxController(_mouse.x, _mouse.y, 1);
|
||||||
|
if (_hitCalled == 4 || _lastHitArea != 0) {
|
||||||
|
execMouseHit(_lastHitArea);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_hitCalled = 0;
|
||||||
|
_oneClick = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::execMouseHit(HitArea *ha) {
|
||||||
|
if (_hitCalled == 1) {
|
||||||
|
if (ha->flags & kOBFUseMessageList)
|
||||||
|
hitBox11(ha);
|
||||||
|
else if (ha->flags & kOBFMoreBox)
|
||||||
|
hitBox9(ha);
|
||||||
|
else if (ha->flags & kOBFExit)
|
||||||
|
hitBox7(ha);
|
||||||
|
else if (ha->flags & kOBFUseEmptyLine)
|
||||||
|
hitBox2(ha);
|
||||||
|
else
|
||||||
|
hitBox1(ha);
|
||||||
|
} else if (_hitCalled == 2) {
|
||||||
|
if (ha->flags & (kOBFObject | kOBFInventoryBox | kOBFRoomBox))
|
||||||
|
hitBox3(ha);
|
||||||
|
else if (ha->flags & kOBFUseMessageList)
|
||||||
|
hitBox11(ha);
|
||||||
|
else if (ha->flags & kOBFMoreBox)
|
||||||
|
hitBox9(ha);
|
||||||
|
else if (ha->flags & kOBFExit)
|
||||||
|
hitBox7(ha);
|
||||||
|
else if (ha->flags & kOBFUseEmptyLine)
|
||||||
|
hitBox2(ha);
|
||||||
|
else
|
||||||
|
hitBox1(ha);
|
||||||
|
} else if (_hitCalled == 3) {
|
||||||
|
if ((ha->flags & kOBFDraggable) && _dragFlag == 0) {
|
||||||
|
_dragFlag = 1;
|
||||||
|
_dragStore = ha;
|
||||||
|
_needHitAreaRecalc++;
|
||||||
|
}
|
||||||
|
} else if (_hitCalled == 4) {
|
||||||
|
_dragFlag = 0;
|
||||||
|
_hitCalled = 0;
|
||||||
|
_oneClick = 0;
|
||||||
|
_mouseDown = 0;
|
||||||
|
_needHitAreaRecalc++;
|
||||||
|
if (ha != 0) {
|
||||||
|
if (ha->flags & kOBFInventoryBox)
|
||||||
|
hitBox5(ha);
|
||||||
|
else if (ha->flags & kOBFRoomBox)
|
||||||
|
hitBox6(ha);
|
||||||
|
} else if (_lockWord & 10) {
|
||||||
|
hitBox8(ha);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_hitCalled = 0;
|
||||||
|
if (_mouseString == 0) {
|
||||||
|
_mouseString = (const char *)"\r";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::hitBox1(HitArea *ha) {
|
||||||
|
if (_mouseString)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_mouseString = getMessage(_objectName1, ha->msg1);
|
||||||
|
if (_intputCounter) {
|
||||||
|
char *msgPtr = getMessage(_objectName1, ha->msg1);
|
||||||
|
while (*msgPtr != 13)
|
||||||
|
msgPtr++;
|
||||||
|
*msgPtr = 0;
|
||||||
|
} else if (!(ha->flags & kOBFNoShowName)) {
|
||||||
|
_mousePrintFG++;
|
||||||
|
_mouseString1 = _mouseString;
|
||||||
|
_mouseString = (const char*)"showname \0";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::hitBox2(HitArea *ha) {
|
||||||
|
if (!_intputCounter)
|
||||||
|
hitBox1(ha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::hitBox3(HitArea *ha) {
|
||||||
|
if (!_intputCounter)
|
||||||
|
hitBox4(ha);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::hitBox4(HitArea *ha) {
|
||||||
|
if (_mouseString)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint16 num = ha->msg1 & ~0x8000;
|
||||||
|
if ((_lockWord & 0x10) && !(ha->flags & (kOBFInventoryBox | kOBFRoomBox)) &&
|
||||||
|
!testContainer(num)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_mouseString = getMessage(_objectName2, ha->msg2);
|
||||||
|
_mouseString1 = getMessage(_objectName1, ha->msg1);
|
||||||
|
_mousePrintFG++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::hitBox5(HitArea *ha) {
|
||||||
|
if (_intputCounter || _mouseString)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_dragStore && (_dragStore->flags & kOBFInventoryBox))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_mousePrintFG++;
|
||||||
|
_mouseString = (const char *)"take \0";
|
||||||
|
_mouseString1 = getMessage(_objectName1, _dragStore->msg1);
|
||||||
|
|
||||||
|
if (_dragStore->flags & kOBFRoomBox)
|
||||||
|
_mouseString1 = (const char *)"all\r";
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::hitBox6(HitArea *ha) {
|
||||||
|
if (_intputCounter || _mouseString)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_dragStore->flags & kOBFRoomBox)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_mousePrintFG++;
|
||||||
|
_mouseString = (const char *)"drop \0";
|
||||||
|
_mouseString1 = getMessage(_objectName1, _dragStore->msg1);
|
||||||
|
|
||||||
|
if (_dragStore->flags & kOBFInventoryBox)
|
||||||
|
_mouseString1 = (const char *)"all\r";
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::hitBox7(HitArea *ha) {
|
||||||
|
if (_intputCounter) {
|
||||||
|
if (!(ha->flags & kOBFUseEmptyLine)) {
|
||||||
|
hitBox1(ha);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_mouseString)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_mousePrintFG++;
|
||||||
|
_mouseString1 = getMessage(_objectName1, ha->msg1);
|
||||||
|
|
||||||
|
uint16 num = ha->msg1 & ~0x8000;
|
||||||
|
uint16 state = getptr(_quickptr[0] + num * _quickshort[0] + 2);
|
||||||
|
if (state == 3) {
|
||||||
|
_mouseString = (const char *)"unlock \0";
|
||||||
|
} else if (state == 2) {
|
||||||
|
_mouseString = (const char *)"open \0";
|
||||||
|
} else {
|
||||||
|
_mouseString = (const char *)"go through \0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::hitBox8(HitArea *ha) {
|
||||||
|
char *msgPtr;
|
||||||
|
|
||||||
|
if (_intputCounter || _mouseString)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ha == 0 || _dragStore == ha)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint16 num = ha->msg1 & ~0x8000;
|
||||||
|
if (!testSeen(num))
|
||||||
|
return;
|
||||||
|
|
||||||
|
msgPtr = getMessage(_objectName1, ha->msg1);
|
||||||
|
sprintf(_inMessage, " in %s", msgPtr);
|
||||||
|
_mouseString1 = _inMessage;
|
||||||
|
|
||||||
|
msgPtr = getMessage(_objectName1, _dragStore->msg1);
|
||||||
|
|
||||||
|
char *tmpPtr = _placeMessage;
|
||||||
|
while (*msgPtr != 0) {
|
||||||
|
if (*msgPtr != 13)
|
||||||
|
*tmpPtr++ = *msgPtr;
|
||||||
|
msgPtr++;
|
||||||
|
}
|
||||||
|
*tmpPtr = 0;
|
||||||
|
|
||||||
|
sprintf(_placeMessage, " in %s", _placeMessage);
|
||||||
|
_mouseString = _placeMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::hitBox9(HitArea *ha) {
|
||||||
|
if (_objectCountS == _objects) {
|
||||||
|
_objectCountS = -1;
|
||||||
|
}
|
||||||
|
iconPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *messageList[9] = {
|
||||||
|
"North\r",
|
||||||
|
"East\r",
|
||||||
|
"South\r",
|
||||||
|
"West\r",
|
||||||
|
"Up\r",
|
||||||
|
"Down\r",
|
||||||
|
"Push grey button\r",
|
||||||
|
"Push red button\r",
|
||||||
|
"Go under car\r"
|
||||||
|
};
|
||||||
|
|
||||||
|
void AGOSEngine_PN::hitBox11(HitArea *ha) {
|
||||||
|
if (_intputCounter || _mouseString)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_mouseString = messageList[ha->msg1];
|
||||||
|
_mousePrintFG++;
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace AGOS
|
} // End of namespace AGOS
|
||||||
|
|
|
@ -133,6 +133,7 @@ void AGOSEngine::setupVgaOpcodes() {
|
||||||
memset(_vga_opcode_table, 0, sizeof(_vga_opcode_table));
|
memset(_vga_opcode_table, 0, sizeof(_vga_opcode_table));
|
||||||
|
|
||||||
switch (getGameType()) {
|
switch (getGameType()) {
|
||||||
|
case GType_PN:
|
||||||
case GType_ELVIRA1:
|
case GType_ELVIRA1:
|
||||||
case GType_ELVIRA2:
|
case GType_ELVIRA2:
|
||||||
case GType_WW:
|
case GType_WW:
|
||||||
|
@ -176,6 +177,27 @@ void AGOSEngine::runVgaScript() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AGOSEngine_PN::ifObjectHere(uint16 a) {
|
||||||
|
if (getFeatures() & GF_DEMO)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return _variableArray[39] == getptr(_quickptr[11] + a * _quickshort[4] + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AGOSEngine_PN::ifObjectAt(uint16 a, uint16 b) {
|
||||||
|
if (getFeatures() & GF_DEMO)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return b == getptr(_quickptr[11] + a * _quickshort[4] + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AGOSEngine_PN::ifObjectState(uint16 a, int16 b) {
|
||||||
|
if (getFeatures() & GF_DEMO)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return b == getptr(_quickptr[0] + a * _quickshort[0] + 2);
|
||||||
|
}
|
||||||
|
|
||||||
bool AGOSEngine::ifObjectHere(uint16 a) {
|
bool AGOSEngine::ifObjectHere(uint16 a) {
|
||||||
Item *item;
|
Item *item;
|
||||||
|
|
||||||
|
@ -256,7 +278,7 @@ void AGOSEngine::setBitFlag(uint bit, bool value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int AGOSEngine::vcReadVarOrWord() {
|
int AGOSEngine::vcReadVarOrWord() {
|
||||||
if (getGameType() == GType_ELVIRA1) {
|
if (getGameType() == GType_PN || getGameType() == GType_ELVIRA1) {
|
||||||
return vcReadNextWord();
|
return vcReadNextWord();
|
||||||
} else {
|
} else {
|
||||||
int16 var = vcReadNextWord();
|
int16 var = vcReadNextWord();
|
||||||
|
@ -289,6 +311,17 @@ void AGOSEngine::vcWriteVar(uint var, int16 value) {
|
||||||
|
|
||||||
void AGOSEngine::vcSkipNextInstruction() {
|
void AGOSEngine::vcSkipNextInstruction() {
|
||||||
|
|
||||||
|
static const byte opcodeParamLenPN[] = {
|
||||||
|
0, 6, 2, 10, 6, 4, 2, 2,
|
||||||
|
4, 4, 8, 2, 0, 2, 2, 2,
|
||||||
|
0, 2, 2, 2, 0, 4, 2, 2,
|
||||||
|
2, 8, 0, 10, 0, 8, 0, 2,
|
||||||
|
2, 0, 0, 0, 0, 2, 4, 2,
|
||||||
|
4, 4, 0, 0, 2, 2, 2, 4,
|
||||||
|
4, 0, 18, 2, 4, 4, 4, 0,
|
||||||
|
4
|
||||||
|
};
|
||||||
|
|
||||||
static const byte opcodeParamLenElvira1[] = {
|
static const byte opcodeParamLenElvira1[] = {
|
||||||
0, 6, 2, 10, 6, 4, 2, 2,
|
0, 6, 2, 10, 6, 4, 2, 2,
|
||||||
4, 4, 8, 2, 0, 2, 2, 2,
|
4, 4, 8, 2, 0, 2, 2, 2,
|
||||||
|
@ -362,9 +395,12 @@ void AGOSEngine::vcSkipNextInstruction() {
|
||||||
} else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
|
} else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
|
||||||
opcode = vcReadNextWord();
|
opcode = vcReadNextWord();
|
||||||
_vcPtr += opcodeParamLenWW[opcode];
|
_vcPtr += opcodeParamLenWW[opcode];
|
||||||
} else {
|
} else if (getGameType() == GType_ELVIRA1) {
|
||||||
opcode = vcReadNextWord();
|
opcode = vcReadNextWord();
|
||||||
_vcPtr += opcodeParamLenElvira1[opcode];
|
_vcPtr += opcodeParamLenElvira1[opcode];
|
||||||
|
} else {
|
||||||
|
opcode = vcReadNextWord();
|
||||||
|
_vcPtr += opcodeParamLenPN[opcode];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dumpVgaOpcodes)
|
if (_dumpVgaOpcodes)
|
||||||
|
@ -411,7 +447,7 @@ void AGOSEngine::vc3_loadSprite() {
|
||||||
vgaSpriteId = vcReadNextWord();
|
vgaSpriteId = vcReadNextWord();
|
||||||
} else {
|
} else {
|
||||||
vgaSpriteId = vcReadNextWord();
|
vgaSpriteId = vcReadNextWord();
|
||||||
zoneNum = vgaSpriteId / 100;
|
zoneNum = (getGameType() == GType_PN) ? 0 : vgaSpriteId / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
x = vcReadNextWord();
|
x = vcReadNextWord();
|
||||||
|
@ -444,8 +480,9 @@ void AGOSEngine::vc5_ifEqual() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine::vc6_ifObjectHere() {
|
void AGOSEngine::vc6_ifObjectHere() {
|
||||||
if (!ifObjectHere(vcReadNextWord()))
|
if (!ifObjectHere(vcReadNextWord())) {
|
||||||
vcSkipNextInstruction();
|
vcSkipNextInstruction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine::vc7_ifObjectNotHere() {
|
void AGOSEngine::vc7_ifObjectNotHere() {
|
||||||
|
@ -610,7 +647,7 @@ void AGOSEngine::drawImage_init(int16 image, uint16 palette, int16 x, int16 y, u
|
||||||
if (state.image < 0)
|
if (state.image < 0)
|
||||||
state.image = vcReadVar(-state.image);
|
state.image = vcReadVar(-state.image);
|
||||||
|
|
||||||
state.palette = palette * 16;
|
state.palette = (getGameType() == GType_PN) ? 0 : palette * 16;
|
||||||
state.paletteMod = 0;
|
state.paletteMod = 0;
|
||||||
|
|
||||||
state.x = x - _scrollX;
|
state.x = x - _scrollX;
|
||||||
|
@ -645,7 +682,11 @@ void AGOSEngine::drawImage_init(int16 image, uint16 palette, int16 x, int16 y, u
|
||||||
state.y_skip = 0; /* rows to skip = bl */
|
state.y_skip = 0; /* rows to skip = bl */
|
||||||
|
|
||||||
if (getFeatures() & GF_PLANAR) {
|
if (getFeatures() & GF_PLANAR) {
|
||||||
state.srcPtr = convertImage(&state, ((flags & 0x80) != 0));
|
if (getGameType() == GType_PN) {
|
||||||
|
state.srcPtr = convertImage(&state, ((state.flags & (kDFCompressed | kDFCompressedFlip)) != 0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
state.srcPtr = convertImage(&state, ((flags & 0x80) != 0));
|
||||||
|
|
||||||
// converted planar clip is already uncompressed
|
// converted planar clip is already uncompressed
|
||||||
if (state.flags & kDFCompressedFlip) {
|
if (state.flags & kDFCompressedFlip) {
|
||||||
|
@ -691,6 +732,36 @@ void AGOSEngine::drawImage_init(int16 image, uint16 palette, int16 x, int16 y, u
|
||||||
drawImage(&state);
|
drawImage(&state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::checkOnStopTable() {
|
||||||
|
VgaSleepStruct *vfs = _onStopTable, *vfs_tmp;
|
||||||
|
while (vfs->ident != 0) {
|
||||||
|
if (vfs->ident == _vgaCurSpriteId) {
|
||||||
|
VgaSprite *vsp = findCurSprite();
|
||||||
|
animate(vsp->windowNum, vsp->zoneNum, vfs->id, vsp->x, vsp->y, vsp->palette, true);
|
||||||
|
vfs_tmp = vfs;
|
||||||
|
do {
|
||||||
|
memcpy(vfs_tmp, vfs_tmp + 1, sizeof(VgaSleepStruct));
|
||||||
|
vfs_tmp++;
|
||||||
|
} while (vfs_tmp->ident != 0);
|
||||||
|
} else {
|
||||||
|
vfs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::vc11_onStop() {
|
||||||
|
uint16 id = vcReadNextWord();
|
||||||
|
|
||||||
|
VgaSleepStruct *vfs = _onStopTable;
|
||||||
|
while (vfs->ident)
|
||||||
|
vfs++;
|
||||||
|
|
||||||
|
vfs->ident = _vgaCurSpriteId;
|
||||||
|
vfs->codePtr = _vcPtr;
|
||||||
|
vfs->id = id;
|
||||||
|
vfs->zoneNum = _vgaCurZoneNum;
|
||||||
|
}
|
||||||
|
|
||||||
void AGOSEngine::vc12_delay() {
|
void AGOSEngine::vc12_delay() {
|
||||||
uint16 num;
|
uint16 num;
|
||||||
|
|
||||||
|
@ -728,7 +799,13 @@ void AGOSEngine::vc14_addToSpriteY() {
|
||||||
|
|
||||||
void AGOSEngine::vc15_sync() {
|
void AGOSEngine::vc15_sync() {
|
||||||
VgaSleepStruct *vfs = _waitSyncTable, *vfs_tmp;
|
VgaSleepStruct *vfs = _waitSyncTable, *vfs_tmp;
|
||||||
uint16 id = vcReadNextWord();
|
uint16 id;
|
||||||
|
|
||||||
|
if (getGameType() == GType_PN)
|
||||||
|
id = _vgaCurSpriteId;
|
||||||
|
else
|
||||||
|
id = vcReadNextWord();
|
||||||
|
|
||||||
while (vfs->ident != 0) {
|
while (vfs->ident != 0) {
|
||||||
if (vfs->ident == id) {
|
if (vfs->ident == id) {
|
||||||
addVgaEvent(_vgaBaseDelay, ANIMATE_EVENT, vfs->codePtr, vfs->id, vfs->zoneNum);
|
addVgaEvent(_vgaBaseDelay, ANIMATE_EVENT, vfs->codePtr, vfs->id, vfs->zoneNum);
|
||||||
|
@ -779,12 +856,13 @@ void AGOSEngine::checkWaitEndTable() {
|
||||||
|
|
||||||
void AGOSEngine::vc17_waitEnd() {
|
void AGOSEngine::vc17_waitEnd() {
|
||||||
uint16 id = vcReadNextWord();
|
uint16 id = vcReadNextWord();
|
||||||
|
uint16 zoneNum = (getGameType() == GType_PN) ? 0 : id / 100;
|
||||||
|
|
||||||
VgaSleepStruct *vfs = _waitEndTable;
|
VgaSleepStruct *vfs = _waitEndTable;
|
||||||
while (vfs->ident)
|
while (vfs->ident)
|
||||||
vfs++;
|
vfs++;
|
||||||
|
|
||||||
if (isSpriteLoaded(id, id / 100)) {
|
if (isSpriteLoaded(id, zoneNum)) {
|
||||||
vfs->ident = id;
|
vfs->ident = id;
|
||||||
vfs->codePtr = _vcPtr;
|
vfs->codePtr = _vcPtr;
|
||||||
vfs->id = _vgaCurSpriteId;
|
vfs->id = _vgaCurSpriteId;
|
||||||
|
@ -867,12 +945,21 @@ void AGOSEngine::vc22_setPaletteOld() {
|
||||||
|
|
||||||
b = vcReadNextWord();
|
b = vcReadNextWord();
|
||||||
|
|
||||||
|
// PC version of Personal Nightmare uses standard EGA palette
|
||||||
|
if (getGameType() == GType_PN && getPlatform() == Common::kPlatformPC)
|
||||||
|
return;
|
||||||
|
|
||||||
num = 16;
|
num = 16;
|
||||||
|
|
||||||
palptr = _displayPalette;
|
palptr = _displayPalette;
|
||||||
_bottomPalette = 1;
|
_bottomPalette = 1;
|
||||||
|
|
||||||
if (getGameType() == GType_ELVIRA1) {
|
if (getGameType() == GType_PN) {
|
||||||
|
if (b > 128) {
|
||||||
|
b-= 128;
|
||||||
|
palptr = _displayPalette + 64;
|
||||||
|
}
|
||||||
|
} else if (getGameType() == GType_ELVIRA1) {
|
||||||
if (b >= 1000) {
|
if (b >= 1000) {
|
||||||
b -= 1000;
|
b -= 1000;
|
||||||
_bottomPalette = 0;
|
_bottomPalette = 0;
|
||||||
|
@ -990,6 +1077,7 @@ void AGOSEngine::vc24_setSpriteXY() {
|
||||||
|
|
||||||
void AGOSEngine::vc25_halt_sprite() {
|
void AGOSEngine::vc25_halt_sprite() {
|
||||||
checkWaitEndTable();
|
checkWaitEndTable();
|
||||||
|
checkOnStopTable();
|
||||||
|
|
||||||
VgaSprite *vsp = findCurSprite();
|
VgaSprite *vsp = findCurSprite();
|
||||||
while (vsp->id != 0) {
|
while (vsp->id != 0) {
|
||||||
|
@ -1046,6 +1134,12 @@ void AGOSEngine::vc27_resetSprite() {
|
||||||
vfs++;
|
vfs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vfs = _onStopTable;
|
||||||
|
while (vfs->ident) {
|
||||||
|
vfs->ident = 0;
|
||||||
|
vfs++;
|
||||||
|
}
|
||||||
|
|
||||||
vte = _vgaTimerList;
|
vte = _vgaTimerList;
|
||||||
while (vte->delay) {
|
while (vte->delay) {
|
||||||
// Skip the animateSprites event in earlier games
|
// Skip the animateSprites event in earlier games
|
||||||
|
@ -1082,13 +1176,12 @@ void AGOSEngine::vc27_resetSprite() {
|
||||||
|
|
||||||
void AGOSEngine::vc28_playSFX() {
|
void AGOSEngine::vc28_playSFX() {
|
||||||
uint16 sound = vcReadNextWord();
|
uint16 sound = vcReadNextWord();
|
||||||
uint16 channels = vcReadNextWord();
|
uint16 chans = vcReadNextWord();
|
||||||
uint16 frequency = vcReadNextWord();
|
uint16 freq = vcReadNextWord();
|
||||||
uint16 flags = vcReadNextWord();
|
uint16 flags = vcReadNextWord();
|
||||||
|
debug(0, "vc28_playSFX: (sound %d, channels %d, frequency %d, flags %d)", sound, chans, freq, flags);
|
||||||
|
|
||||||
loadSound(sound);
|
loadSound(sound, freq, flags);
|
||||||
|
|
||||||
debug(0, "vc28_playSFX: (%d, %d, %d, %d)", sound, channels, frequency, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine::vc29_stopAllSounds() {
|
void AGOSEngine::vc29_stopAllSounds() {
|
||||||
|
@ -1154,8 +1247,23 @@ void AGOSEngine::clearVideoBackGround(uint16 num, uint16 color) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AGOSEngine_PN::clearVideoWindow(uint16 num, uint16 color) {
|
||||||
|
const uint16 *vlut = &_videoWindows[num * 4];
|
||||||
|
uint16 xoffs = vlut[0] * 16;
|
||||||
|
uint16 yoffs = vlut[1];
|
||||||
|
|
||||||
|
Graphics::Surface *screen = _system->lockScreen();
|
||||||
|
byte *dst = (byte *)screen->pixels + xoffs + yoffs * screen->pitch;
|
||||||
|
for (uint h = 0; h < vlut[3]; h++) {
|
||||||
|
memset(dst, color, vlut[2] * 16);
|
||||||
|
dst += screen->pitch;
|
||||||
|
}
|
||||||
|
_system->unlockScreen();
|
||||||
|
}
|
||||||
|
|
||||||
void AGOSEngine_Simon2::clearVideoWindow(uint16 num, uint16 color) {
|
void AGOSEngine_Simon2::clearVideoWindow(uint16 num, uint16 color) {
|
||||||
const uint16 *vlut = &_videoWindows[num * 4];
|
const uint16 *vlut = &_videoWindows[num * 4];
|
||||||
|
|
||||||
uint16 xoffs = vlut[0] * 16;
|
uint16 xoffs = vlut[0] * 16;
|
||||||
uint16 yoffs = vlut[1];
|
uint16 yoffs = vlut[1];
|
||||||
uint16 dstWidth = _videoWindows[18] * 16;
|
uint16 dstWidth = _videoWindows[18] * 16;
|
||||||
|
@ -1243,6 +1351,10 @@ void AGOSEngine::vc37_pokePalette() {
|
||||||
uint16 offs = vcReadNextWord();
|
uint16 offs = vcReadNextWord();
|
||||||
uint16 color = vcReadNextWord();
|
uint16 color = vcReadNextWord();
|
||||||
|
|
||||||
|
// PC version of Personal Nightmare uses standard EGA palette
|
||||||
|
if (getGameType() == GType_PN && getPlatform() == Common::kPlatformPC)
|
||||||
|
return;
|
||||||
|
|
||||||
byte *palptr = _displayPalette + offs * 4;
|
byte *palptr = _displayPalette + offs * 4;
|
||||||
palptr[0] = ((color & 0xf00) >> 8) * 32;
|
palptr[0] = ((color & 0xf00) >> 8) * 32;
|
||||||
palptr[1] = ((color & 0x0f0) >> 4) * 32;
|
palptr[1] = ((color & 0x0f0) >> 4) * 32;
|
||||||
|
|
|
@ -183,9 +183,9 @@ void AGOSEngine::vc52_playSound() {
|
||||||
int16 vol = vcReadNextWord();
|
int16 vol = vcReadNextWord();
|
||||||
|
|
||||||
if (ambient)
|
if (ambient)
|
||||||
loadSound(sound, pan, vol, 2);
|
loadSound(sound, pan, vol, Sound::TYPE_AMBIENT);
|
||||||
else
|
else
|
||||||
loadSound(sound, pan, vol, 1);
|
loadSound(sound, pan, vol, Sound::TYPE_SFX);
|
||||||
} else if (getGameType() == GType_SIMON2) {
|
} else if (getGameType() == GType_SIMON2) {
|
||||||
if (ambient)
|
if (ambient)
|
||||||
_sound->playAmbient(sound);
|
_sound->playAmbient(sound);
|
||||||
|
@ -196,7 +196,7 @@ void AGOSEngine::vc52_playSound() {
|
||||||
} else if (getGameId() == GID_SIMON1DOS) {
|
} else if (getGameId() == GID_SIMON1DOS) {
|
||||||
playSting(sound);
|
playSting(sound);
|
||||||
} else {
|
} else {
|
||||||
loadSound(sound);
|
loadSound(sound, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,7 @@ void AGOSEngine::vc83_playSoundLoop() {
|
||||||
int16 vol = vcReadNextWord();
|
int16 vol = vcReadNextWord();
|
||||||
int16 pan = vcReadNextWord();
|
int16 pan = vcReadNextWord();
|
||||||
|
|
||||||
loadSound(sound, pan, vol, 3);
|
loadSound(sound, pan, vol, Sound::TYPE_SFX5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine::vc84_stopSoundLoop() {
|
void AGOSEngine::vc84_stopSoundLoop() {
|
||||||
|
|
188
engines/agos/vga_pn.cpp
Normal file
188
engines/agos/vga_pn.cpp
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
/* ScummVM - Graphic Adventure Engine
|
||||||
|
*
|
||||||
|
* ScummVM is the legal property of its developers, whose names
|
||||||
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||||
|
* file distributed with this source distribution.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Video script opcodes for Simon1/Simon2
|
||||||
|
|
||||||
|
|
||||||
|
#include "agos/agos.h"
|
||||||
|
#include "agos/intern.h"
|
||||||
|
#include "agos/vga.h"
|
||||||
|
|
||||||
|
#include "common/system.h"
|
||||||
|
|
||||||
|
#include "graphics/surface.h"
|
||||||
|
|
||||||
|
namespace AGOS {
|
||||||
|
|
||||||
|
void AGOSEngine_PN::setupVideoOpcodes(VgaOpcodeProc *op) {
|
||||||
|
op[1] = &AGOSEngine::vc1_fadeOut;
|
||||||
|
op[2] = &AGOSEngine::vc2_call;
|
||||||
|
op[3] = &AGOSEngine::vc3_loadSprite;
|
||||||
|
op[4] = &AGOSEngine::vc4_fadeIn;
|
||||||
|
op[5] = &AGOSEngine::vc5_ifEqual;
|
||||||
|
op[6] = &AGOSEngine::vc6_ifObjectHere;
|
||||||
|
op[7] = &AGOSEngine::vc7_ifObjectNotHere;
|
||||||
|
op[8] = &AGOSEngine::vc8_ifObjectIsAt;
|
||||||
|
op[9] = &AGOSEngine::vc9_ifObjectStateIs;
|
||||||
|
op[10] = &AGOSEngine::vc10_draw;
|
||||||
|
op[11] = &AGOSEngine::vc11_onStop;
|
||||||
|
op[13] = &AGOSEngine::vc12_delay;
|
||||||
|
op[14] = &AGOSEngine::vc13_addToSpriteX;
|
||||||
|
op[15] = &AGOSEngine::vc14_addToSpriteY;
|
||||||
|
op[16] = &AGOSEngine::vc15_sync;
|
||||||
|
op[17] = &AGOSEngine::vc16_waitSync;
|
||||||
|
op[18] = &AGOSEngine::vc17_waitEnd;
|
||||||
|
op[19] = &AGOSEngine::vc18_jump;
|
||||||
|
op[20] = &AGOSEngine::vc19_loop;
|
||||||
|
op[21] = &AGOSEngine::vc20_setRepeat;
|
||||||
|
op[22] = &AGOSEngine::vc21_endRepeat;
|
||||||
|
op[23] = &AGOSEngine::vc22_setPaletteOld;
|
||||||
|
op[24] = &AGOSEngine::vc23_setPriority;
|
||||||
|
op[25] = &AGOSEngine::vc24_setSpriteXY;
|
||||||
|
op[26] = &AGOSEngine::vc25_halt_sprite;
|
||||||
|
op[27] = &AGOSEngine::vc26_setSubWindow;
|
||||||
|
op[28] = &AGOSEngine::vc27_resetSprite;
|
||||||
|
op[29] = &AGOSEngine::vc28_playSFX;
|
||||||
|
op[30] = &AGOSEngine::vc29_stopAllSounds;
|
||||||
|
op[31] = &AGOSEngine::vc30_setFrameRate;
|
||||||
|
op[32] = &AGOSEngine::vc31_setWindow;
|
||||||
|
op[33] = &AGOSEngine::vc32_saveScreen;
|
||||||
|
op[34] = &AGOSEngine::vc33_setMouseOn;
|
||||||
|
op[35] = &AGOSEngine::vc34_setMouseOff;
|
||||||
|
op[36] = &AGOSEngine::vc36_pause;
|
||||||
|
op[38] = &AGOSEngine::vc35_clearWindow;
|
||||||
|
op[39] = &AGOSEngine::vc39_volume;
|
||||||
|
op[40] = &AGOSEngine::vc36_setWindowImage;
|
||||||
|
op[41] = &AGOSEngine::vc37_pokePalette;
|
||||||
|
op[44] = &AGOSEngine::vc44_enableBox;
|
||||||
|
op[45] = &AGOSEngine::vc45_disableBox;
|
||||||
|
op[46] = &AGOSEngine::vc46_maxBox;
|
||||||
|
op[48] = &AGOSEngine::vc48_specialEffect;
|
||||||
|
op[50] = &AGOSEngine::vc50_setBox;
|
||||||
|
op[51] = &AGOSEngine::vc38_ifVarNotZero;
|
||||||
|
op[52] = &AGOSEngine::vc39_setVar;
|
||||||
|
op[53] = &AGOSEngine::vc40_scrollRight;
|
||||||
|
op[54] = &AGOSEngine::vc41_scrollLeft;
|
||||||
|
op[55] = &AGOSEngine::vc55_scanFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::vc36_pause() {
|
||||||
|
const char *message1 = "Press any key to continue";
|
||||||
|
bool oldWiped = _wiped;
|
||||||
|
_wiped = 0;
|
||||||
|
|
||||||
|
_lockWord |= 8;
|
||||||
|
|
||||||
|
windowPutChar(_windowArray[2], 13);
|
||||||
|
|
||||||
|
for (; *message1; message1++)
|
||||||
|
windowPutChar(_windowArray[2], *message1);
|
||||||
|
|
||||||
|
while (!shouldQuit()) {
|
||||||
|
if (_keyPressed.ascii != 0)
|
||||||
|
break;
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
_keyPressed.reset();
|
||||||
|
|
||||||
|
windowPutChar(_windowArray[2], 13);
|
||||||
|
windowPutChar(_windowArray[2], 128);
|
||||||
|
_wiped = oldWiped;
|
||||||
|
|
||||||
|
_lockWord &= ~8;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::vc39_volume() {
|
||||||
|
_vcPtr += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::vc44_enableBox() {
|
||||||
|
HitArea *ha = _hitAreas + vcReadNextWord();
|
||||||
|
ha->flags &= ~kOBFBoxDisabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::vc45_disableBox() {
|
||||||
|
HitArea *ha = _hitAreas + vcReadNextWord();
|
||||||
|
ha->flags |= kOBFBoxDisabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::vc46_maxBox() {
|
||||||
|
HitArea *ha = _hitAreas + vcReadNextWord();
|
||||||
|
ha->id = 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::vc48_specialEffect() {
|
||||||
|
uint16 num = vcReadNextWord();
|
||||||
|
vcReadNextWord();
|
||||||
|
|
||||||
|
if (getPlatform() == Common::kPlatformPC) {
|
||||||
|
if (num == 1) {
|
||||||
|
Graphics::Surface *screen = _system->lockScreen();
|
||||||
|
byte *dst = (byte *)screen->pixels;
|
||||||
|
|
||||||
|
for (uint h = 0; h < _screenHeight; h++) {
|
||||||
|
for (uint w = 0; w < _screenWidth; w++) {
|
||||||
|
if (dst[w] == 15)
|
||||||
|
dst[w] = 4;
|
||||||
|
}
|
||||||
|
dst += _screenWidth;
|
||||||
|
}
|
||||||
|
_system->unlockScreen();
|
||||||
|
} else if (num == 2) {
|
||||||
|
const char *str = "There are gurgling noises from the sink.";
|
||||||
|
for (; *str; str++)
|
||||||
|
windowPutChar(_textWindow, *str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::vc50_setBox() {
|
||||||
|
uint16 id, x, y, w, h, msg1, msg2, flags;
|
||||||
|
const uint16 *vlut;
|
||||||
|
|
||||||
|
id = vcReadNextWord();
|
||||||
|
vlut = &_videoWindows[vcReadNextWord() * 4];
|
||||||
|
x = vlut[0] * 16 + vcReadNextWord();
|
||||||
|
y = vlut[1] + vcReadNextWord();
|
||||||
|
h = vcReadNextWord();
|
||||||
|
w = vcReadNextWord();
|
||||||
|
msg1 = vcReadNextWord();
|
||||||
|
msg2 = vcReadNextWord();
|
||||||
|
flags = vcReadNextWord();
|
||||||
|
|
||||||
|
// Compressed string
|
||||||
|
if (!(flags & kOBFUseMessageList)) {
|
||||||
|
msg1 += 0x8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineBox(id, x, y, h, w, msg1, msg2, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AGOSEngine::vc55_scanFlag() {
|
||||||
|
_scanFlag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End of namespace AGOS
|
|
@ -71,10 +71,12 @@ WindowBlock *AGOSEngine::openWindow(uint x, uint y, uint w, uint h, uint flags,
|
||||||
// Characters are 6 pixels
|
// Characters are 6 pixels
|
||||||
if (getGameType() == GType_ELVIRA2)
|
if (getGameType() == GType_ELVIRA2)
|
||||||
window->textMaxLength = (window->width * 8 - 4) / 6;
|
window->textMaxLength = (window->width * 8 - 4) / 6;
|
||||||
|
else if (getGameType() == GType_PN)
|
||||||
|
window->textMaxLength = window->width * 8 / 6 + 1;
|
||||||
else
|
else
|
||||||
window->textMaxLength = window->width * 8 / 6;
|
window->textMaxLength = window->width * 8 / 6;
|
||||||
|
|
||||||
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW)
|
if (getGameType() == GType_PN || getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW)
|
||||||
clearWindow(window);
|
clearWindow(window);
|
||||||
|
|
||||||
if (getGameType() == GType_SIMON1 && getPlatform() == Common::kPlatformAmiga && window->fillColor == 225)
|
if (getGameType() == GType_SIMON1 && getPlatform() == Common::kPlatformAmiga && window->fillColor == 225)
|
||||||
|
@ -202,9 +204,9 @@ void AGOSEngine::restoreWindow(WindowBlock *window) {
|
||||||
_restoreWindow6 = 0;
|
_restoreWindow6 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreBlock(window->y + window->height * 8, (window->x + window->width) * 8, window->y, window->x * 8);
|
restoreBlock(window->x * 8, window->y, (window->x + window->width) * 8, window->y + window->height * 8);
|
||||||
} else if (getGameType() == GType_SIMON1) {
|
} else if (getGameType() == GType_SIMON1) {
|
||||||
restoreBlock(window->y + window->height * 8 + ((window == _windowArray[2]) ? 1 : 0), (window->x + window->width) * 8, window->y, window->x * 8);
|
restoreBlock(window->x * 8, window->y, (window->x + window->width) * 8, window->y + window->height * 8 + ((window == _windowArray[2]) ? 1 : 0));
|
||||||
} else {
|
} else {
|
||||||
uint16 x = window->x;
|
uint16 x = window->x;
|
||||||
uint16 w = window->width;
|
uint16 w = window->width;
|
||||||
|
@ -220,13 +222,13 @@ void AGOSEngine::restoreWindow(WindowBlock *window) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreBlock(window->y + window->height * 8, (x + w) * 8, window->y, x * 8);
|
restoreBlock(x * 8, window->y, (x + w) * 8, window->y + window->height * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
_lockWord &= ~0x8000;
|
_lockWord &= ~0x8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine::restoreBlock(uint16 h, uint16 w, uint16 y, uint16 x) {
|
void AGOSEngine::restoreBlock(uint16 x, uint16 y, uint16 w, uint16 h) {
|
||||||
byte *dst, *src;
|
byte *dst, *src;
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
|
@ -266,7 +268,7 @@ void AGOSEngine::setTextColor(uint color) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AGOSEngine::sendWindow(uint a) {
|
void AGOSEngine::sendWindow(uint a) {
|
||||||
if (_textWindow != _windowArray[0]) {
|
if (getGameType() == GType_PN || _textWindow != _windowArray[0]) {
|
||||||
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
|
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
|
||||||
if (!(_textWindow->flags & 1)) {
|
if (!(_textWindow->flags & 1)) {
|
||||||
haltAnimation();
|
haltAnimation();
|
||||||
|
|
|
@ -63,29 +63,34 @@ static const uint8 zoneTable[160] = {
|
||||||
2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
|
2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
void AGOSEngine::loadZone(uint16 zoneNum) {
|
void AGOSEngine::loadZone(uint16 zoneNum, bool useError) {
|
||||||
VgaPointersEntry *vpe;
|
VgaPointersEntry *vpe;
|
||||||
|
|
||||||
CHECK_BOUNDS(zoneNum, _vgaBufferPointers);
|
CHECK_BOUNDS(zoneNum, _vgaBufferPointers);
|
||||||
|
|
||||||
vpe = _vgaBufferPointers + zoneNum;
|
if (getGameType() == GType_PN) {
|
||||||
if (vpe->vgaFile1 != NULL)
|
// Only a single zone is used in Personal Nightmare
|
||||||
return;
|
vpe = _vgaBufferPointers;
|
||||||
|
vc27_resetSprite();
|
||||||
|
} else {
|
||||||
|
vpe = _vgaBufferPointers + zoneNum;
|
||||||
|
if (vpe->vgaFile1 != NULL)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Loading order is important
|
// Loading order is important due to resource managment
|
||||||
// due to resource managment
|
|
||||||
|
|
||||||
if (getPlatform() == Common::kPlatformAmiga && getGameType() == GType_WW &&
|
if (getPlatform() == Common::kPlatformAmiga && getGameType() == GType_WW &&
|
||||||
zoneTable[zoneNum] == 3) {
|
zoneTable[zoneNum] == 3) {
|
||||||
uint8 num = (zoneNum >= 85) ? 94 : 18;
|
uint8 num = (zoneNum >= 85) ? 94 : 18;
|
||||||
loadVGAVideoFile(num, 2);
|
loadVGAVideoFile(num, 2, useError);
|
||||||
} else {
|
} else {
|
||||||
loadVGAVideoFile(zoneNum, 2);
|
loadVGAVideoFile(zoneNum, 2, useError);
|
||||||
}
|
}
|
||||||
vpe->vgaFile2 = _block;
|
vpe->vgaFile2 = _block;
|
||||||
vpe->vgaFile2End = _blockEnd;
|
vpe->vgaFile2End = _blockEnd;
|
||||||
|
|
||||||
loadVGAVideoFile(zoneNum, 1);
|
loadVGAVideoFile(zoneNum, 1, useError);
|
||||||
vpe->vgaFile1 = _block;
|
vpe->vgaFile1 = _block;
|
||||||
vpe->vgaFile1End = _blockEnd;
|
vpe->vgaFile1End = _blockEnd;
|
||||||
|
|
||||||
|
|
|
@ -498,6 +498,7 @@ begin_credits("Credits");
|
||||||
|
|
||||||
begin_section("AGOS");
|
begin_section("AGOS");
|
||||||
add_person("Torbjörn Andersson", "eriktorbjorn", "");
|
add_person("Torbjörn Andersson", "eriktorbjorn", "");
|
||||||
|
add_person("Paul Gilbert", "dreammaster", "");
|
||||||
add_person("Travis Howell", "Kirben", "");
|
add_person("Travis Howell", "Kirben", "");
|
||||||
end_section();
|
end_section();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue