[Scummvm-cvs-logs] SF.net SVN: scummvm:[39216] scummvm/trunk
Kirben at users.sourceforge.net
Kirben at users.sourceforge.net
Sun Mar 8 09:45:21 CET 2009
Revision: 39216
http://scummvm.svn.sourceforge.net/scummvm/?rev=39216&view=rev
Author: Kirben
Date: 2009-03-08 08:45:21 +0000 (Sun, 08 Mar 2009)
Log Message:
-----------
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.
Modified Paths:
--------------
scummvm/trunk/engines/agos/agos.cpp
scummvm/trunk/engines/agos/agos.h
scummvm/trunk/engines/agos/charset-fontdata.cpp
scummvm/trunk/engines/agos/charset.cpp
scummvm/trunk/engines/agos/cursor.cpp
scummvm/trunk/engines/agos/debug.cpp
scummvm/trunk/engines/agos/debug.h
scummvm/trunk/engines/agos/detection.cpp
scummvm/trunk/engines/agos/detection_tables.h
scummvm/trunk/engines/agos/event.cpp
scummvm/trunk/engines/agos/gfx.cpp
scummvm/trunk/engines/agos/icons.cpp
scummvm/trunk/engines/agos/input.cpp
scummvm/trunk/engines/agos/intern.h
scummvm/trunk/engines/agos/menus.cpp
scummvm/trunk/engines/agos/module.mk
scummvm/trunk/engines/agos/res.cpp
scummvm/trunk/engines/agos/res_ami.cpp
scummvm/trunk/engines/agos/res_snd.cpp
scummvm/trunk/engines/agos/saveload.cpp
scummvm/trunk/engines/agos/script_e2.cpp
scummvm/trunk/engines/agos/sound.cpp
scummvm/trunk/engines/agos/sound.h
scummvm/trunk/engines/agos/string.cpp
scummvm/trunk/engines/agos/verb.cpp
scummvm/trunk/engines/agos/vga.cpp
scummvm/trunk/engines/agos/vga_e2.cpp
scummvm/trunk/engines/agos/vga_ff.cpp
scummvm/trunk/engines/agos/window.cpp
scummvm/trunk/engines/agos/zones.cpp
scummvm/trunk/tools/credits.pl
Added Paths:
-----------
scummvm/trunk/engines/agos/pn.cpp
scummvm/trunk/engines/agos/script_pn.cpp
scummvm/trunk/engines/agos/vga_pn.cpp
Modified: scummvm/trunk/engines/agos/agos.cpp
===================================================================
--- scummvm/trunk/engines/agos/agos.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/agos.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -182,6 +182,7 @@
_lastVgaTick = 0;
_marks = 0;
+ _scanFlag = false;
_scriptVar2 = 0;
_runScriptReturn1 = 0;
@@ -288,11 +289,14 @@
_firstTimeStruct = 0;
_pendingDeleteTimeEvent = 0;
+ _initMouse = 0;
_leftButtonDown = 0;
+ _mouseDown = 0;
_rightButtonDown = 0;
_clickOnly = 0;
+ _oneClick = 0;
_leftClick = 0;
- _oneClick = 0;
+ _rightClick = 0;
_noRightClick = false;
_leftButton = 0;
@@ -321,11 +325,14 @@
_soundFileId = 0;
_lastMusicPlayed = 0;
_nextMusicToPlay = 0;
+ _sampleEnd = 0;
+ _sampleWait = 0;
_showPreposition = 0;
_showMessageFlag = 0;
_newDirtyClip = false;
+ _wiped = false;
_copyScnFlag = 0;
_vgaSpriteChanged = 0;
@@ -341,6 +348,7 @@
_curVgaFile1 = 0;
_curVgaFile2 = 0;
_curSfxFile = 0;
+ _curSfxFileSize = 0;
_syncCount = 0;
@@ -683,6 +691,14 @@
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() {
gss = &puzzlepack_settings;
_numVideoOpcodes = 85;
@@ -836,6 +852,18 @@
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() {
allocItemHeap();
allocTablesHeap();
@@ -870,6 +898,8 @@
for (int i = 0; i < 20; i++) {
if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
_videoWindows[i] = initialVideoWindows_Simon[i];
+ } else if (getGameType() == GType_PN) {
+ _videoWindows[i] = initialVideoWindows_PN[i];
} else {
_videoWindows[i] = initialVideoWindows_Common[i];
}
@@ -965,7 +995,7 @@
while (_pause && !shouldQuit()) {
delay(1);
- if (_keyPressed.keycode == Common::KEYCODE_p)
+ if (_keyPressed.keycode == Common::KEYCODE_PAUSE)
pauseEngine(false);
}
}
@@ -1037,7 +1067,6 @@
return _system->getMillis() / 1000;
}
-
void AGOSEngine::syncSoundSettings() {
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
Modified: scummvm/trunk/engines/agos/agos.h
===================================================================
--- scummvm/trunk/engines/agos/agos.h 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/agos.h 2009-03-08 08:45:21 UTC (rev 39216)
@@ -31,6 +31,7 @@
#include "common/array.h"
#include "common/keyboard.h"
#include "common/rect.h"
+#include "common/stack.h"
#include "common/util.h"
#include "agos/animation.h"
@@ -38,6 +39,9 @@
#include "agos/sound.h"
#include "agos/vga.h"
+// TODO: Replace with more portable code
+#include <setjmp.h>
+
namespace AGOS {
/* Enable and set to zone number number to dump */
@@ -72,6 +76,9 @@
Item *itemPtr;
uint16 verb;
uint16 priority;
+
+ // Personal Nightmare specific
+ uint16 msg1, msg2;
HitArea() { memset(this, 0, sizeof(*this)); }
};
@@ -127,6 +134,7 @@
};
enum SIMONGameType {
+ GType_PN = 0,
GType_ELVIRA1 = 1,
GType_ELVIRA2 = 2,
GType_WW = 3,
@@ -167,7 +175,7 @@
// Engine APIs
Common::Error init();
- Common::Error go();
+ virtual Common::Error go();
virtual Common::Error run() {
Common::Error err;
err = init();
@@ -282,6 +290,7 @@
uint32 _lastVgaTick;
uint16 _marks;
+ bool _scanFlag;
bool _scriptVar2;
bool _runScriptReturn1;
@@ -346,7 +355,7 @@
int16 _scriptAdj1, _scriptAdj2;
uint16 _curWindow;
- WindowBlock *_textWindow;
+ WindowBlock *_inputWindow, *_textWindow;
Item *_subjectItem, *_objectItem;
Item *_currentPlayer;
@@ -387,6 +396,7 @@
TimeEvent *_firstTimeStruct, *_pendingDeleteTimeEvent;
+ bool _initMouse;
Common::Point _mouse;
Common::Point _mouseOld;
@@ -401,8 +411,10 @@
byte _leftButtonDown;
byte _leftButton, _leftButtonCount, _leftButtonOld;
+ byte _mouseDown;
byte _rightButtonDown;
- bool _clickOnly, _leftClick, _oneClick;
+ bool _clickOnly, _oneClick;
+ bool _leftClick, _rightClick;
bool _noRightClick;
Item *_dummyItem1;
@@ -429,11 +441,11 @@
uint16 _soundFileId;
int16 _lastMusicPlayed;
int16 _nextMusicToPlay;
-
bool _showPreposition;
bool _showMessageFlag;
bool _newDirtyClip;
+ bool _wiped;
uint16 _copyScnFlag, _vgaSpriteChanged;
byte *_block, *_blockEnd;
@@ -443,7 +455,6 @@
byte *_curVgaFile1;
byte *_curVgaFile2;
- byte *_curSfxFile;
uint16 _syncCount;
@@ -503,10 +514,12 @@
byte _stringReturnBuffer[2][180];
HitArea _hitAreas[250];
+ HitArea *_hitAreaList;
AnimTable _screenAnim1[90];
VgaPointersEntry _vgaBufferPointers[450];
VgaSprite _vgaSprites[200];
+ VgaSleepStruct _onStopTable[60];
VgaSleepStruct _waitEndTable[60];
VgaSleepStruct _waitSyncTable[60];
@@ -585,6 +598,10 @@
AGOSEngine(OSystem *syst);
virtual ~AGOSEngine();
+ byte *_curSfxFile;
+ uint32 _curSfxFileSize;
+ uint16 _sampleEnd, _sampleWait;
+
protected:
virtual uint16 to16Wrapper(uint value);
virtual uint16 readUint16Wrapper(const void *src);
@@ -598,17 +615,17 @@
void readGamePcText(Common::SeekableReadStream *in);
virtual void readItemChildren(Common::SeekableReadStream *in, Item *item, uint tmp);
void readItemFromGamePc(Common::SeekableReadStream *in, Item *item);
- void loadGamePcFile();
+ virtual void loadGamePcFile();
void readGamePcFile(Common::SeekableReadStream *in);
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 loadSound(uint sound);
- void loadSound(uint sound, int pan, int vol, uint type);
+ void loadSound(uint16 sound, int16 pan, int16 vol, uint16 type);
+ void loadSound(uint16 sound, uint16 freq, uint16 flags);
void loadVoice(uint speechId);
void loadSoundFile(const char *filename);
-
int getUserFlag(Item *item, int a);
int getUserFlag1(Item *item, int a);
int getUserItem(Item *item, int n);
@@ -638,6 +655,7 @@
/* used in debugger */
void dumpAllSubroutines();
+ void dumpAllVgaFiles();
void dumpSubroutines();
void dumpSubroutine(Subroutine *sub);
void dumpSubroutineLine(SubroutineLine *sl, Subroutine *sub);
@@ -707,6 +725,8 @@
bool isBoxDead(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(uint16 id, uint16 x, uint16 y, uint16 width, uint16 height, uint16 msg1, uint16 msg2, uint16 flags);
+
HitArea *findEmptyHitArea();
virtual void resetVerbs();
@@ -749,6 +769,7 @@
virtual int weightOf(Item *x);
void xPlace(Item *x, Item *y);
+ void restoreMenu();
void drawMenuStrip(uint windowNum, uint menuNum);
void lightMenuStrip(int a);
void unlightMenuStrip();
@@ -826,7 +847,7 @@
void loadIconFile();
void loadMenuFile();
- bool processSpecialKeys();
+ virtual bool processSpecialKeys();
void hitarea_stuff_helper();
void permitInput();
@@ -835,12 +856,13 @@
void justifyStart();
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 setImage(uint16 vgaSpriteId, bool vgaScript = false);
- void setWindowImage(uint16 mode, uint16 vgaSpriteId);
- void setWindowImageEx(uint16 mode, uint16 vgaSpriteId);
+ void setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCase = false);
+ virtual void setWindowImageEx(uint16 mode, uint16 vgaSpriteId);
+ void drawEdging();
void skipSpeech();
@@ -908,6 +930,17 @@
void vc41_scrollLeft();
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
void vc17_waitEnd();
void vc22_setPaletteOld();
@@ -1121,11 +1154,12 @@
void clearVideoBackGround(uint16 windowNum, uint16 color);
void setPaletteSlot(uint16 srcOffs, uint8 dstOffs);
+ void checkOnStopTable();
void checkWaitEndTable();
- bool ifObjectHere(uint16 val);
- bool ifObjectAt(uint16 a, uint16 b);
- bool ifObjectState(uint16 a, int16 b);
+ virtual bool ifObjectHere(uint16 val);
+ virtual bool ifObjectAt(uint16 a, uint16 b);
+ virtual bool ifObjectState(uint16 a, int16 b);
bool isVgaQueueEmpty();
void haltAnimation();
@@ -1152,7 +1186,7 @@
void colorBlock(WindowBlock *window, uint16 x, uint16 y, uint16 w, uint16 h);
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 *getBackGround();
@@ -1162,7 +1196,7 @@
bool decrunchFile(byte *src, byte *dst, uint32 size);
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);
void openGameFile();
@@ -1247,6 +1281,253 @@
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 {
public:
AGOSEngine_Elvira1(OSystem *system);
@@ -1322,6 +1603,10 @@
};
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 {
Modified: scummvm/trunk/engines/agos/charset-fontdata.cpp
===================================================================
--- scummvm/trunk/engines/agos/charset-fontdata.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/charset-fontdata.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -1767,6 +1767,107 @@
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) {
const byte *src;
byte color, *dst;
@@ -1851,6 +1952,12 @@
w = 6;
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;
Modified: scummvm/trunk/engines/agos/charset.cpp
===================================================================
--- scummvm/trunk/engines/agos/charset.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/charset.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -610,13 +610,21 @@
window->textColumnOffset = (getGameType() == GType_ELVIRA2) ? 4 : 0;
window->textLength = 0;
- if (window->textRow == window->height) {
- if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 ||
- getGameType() == GType_WW) {
+ if (getGameType() == GType_PN) {
+ window->textRow++;
+ if (window->textRow == window->height) {
windowScroll(window);
+ window->textRow--;
}
} else {
- window->textRow++;
+ if (window->textRow == window->height) {
+ if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 ||
+ getGameType() == GType_WW) {
+ windowScroll(window);
+ }
+ } else {
+ window->textRow++;
+ }
}
}
Modified: scummvm/trunk/engines/agos/cursor.cpp
===================================================================
--- scummvm/trunk/engines/agos/cursor.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/cursor.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -474,6 +474,71 @@
_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() {
uint x;
@@ -721,8 +786,15 @@
} else {
const uint16 *src;
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);
if (getGameType() == GType_WW) {
Modified: scummvm/trunk/engines/agos/debug.cpp
===================================================================
--- scummvm/trunk/engines/agos/debug.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/debug.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -231,8 +231,10 @@
strn = str = simon1_videoOpcodeNameTable[opcode];
} else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
strn = str = ww_videoOpcodeNameTable[opcode];
+ } else if (getGameType() == GType_ELVIRA1) {
+ strn = str = elvira1_videoOpcodeNameTable[opcode];
} else {
- strn = str = elvira1_videoOpcodeNameTable[opcode];
+ strn = str = pn_videoOpcodeNameTable[opcode];
}
if (strn == NULL) {
@@ -295,6 +297,24 @@
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) {
const byte *pp;
const byte *p;
Modified: scummvm/trunk/engines/agos/debug.h
===================================================================
--- scummvm/trunk/engines/agos/debug.h 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/debug.h 2009-03-08 08:45:21 UTC (rev 39216)
@@ -2324,6 +2324,79 @@
"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[] = {
/* 0 */
"x|RET",
Modified: scummvm/trunk/engines/agos/detection.cpp
===================================================================
--- scummvm/trunk/engines/agos/detection.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/detection.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -65,6 +65,7 @@
};
static const PlainGameDescriptor simonGames[] = {
+ {"pn", "Personal Nightmare"},
{"elvira1", "Elvira - Mistress of the Dark"},
{"elvira2", "Elvira II - The Jaws of Cerberus"},
{"waxworks", "Waxworks"},
@@ -132,6 +133,9 @@
bool res = true;
switch (gd->gameType) {
+ case AGOS::GType_PN:
+ *engine = new AGOS::AGOSEngine_PN(syst);
+ break;
case AGOS::GType_ELVIRA1:
*engine = new AGOS::AGOSEngine_Elvira1(syst);
break;
Modified: scummvm/trunk/engines/agos/detection_tables.h
===================================================================
--- scummvm/trunk/engines/agos/detection_tables.h 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/detection_tables.h 2009-03-08 08:45:21 UTC (rev 39216)
@@ -26,6 +26,93 @@
namespace AGOS {
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
{
{
Modified: scummvm/trunk/engines/agos/event.cpp
===================================================================
--- scummvm/trunk/engines/agos/event.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/event.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -185,14 +185,13 @@
if (!(_lockWord & 0x10))
return;
- _window4Flag = 2;
+ if (getGameType() != GType_PN) {
+ _window4Flag = 2;
+ setMoveRect(0, 0, 224, 127);
+ displayScreen();
+ }
- setMoveRect(0, 0, 224, 127);
- displayScreen();
-
_lockWord &= ~0x10;
-
- // Check picture queue
}
void AGOSEngine::addVgaEvent(uint16 num, uint8 type, const byte *codePtr, uint16 curSprite, uint16 curZoneNum) {
@@ -520,6 +519,9 @@
setBitFlag(92, false);
_rightButtonDown++;
break;
+ case Common::EVENT_RBUTTONUP:
+ _rightClick = true;
+ break;
case Common::EVENT_RTL:
case Common::EVENT_QUIT:
return;
@@ -611,6 +613,45 @@
_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() {
if (_lockWord & 0x80E9 || _lockWord & 2)
return;
Modified: scummvm/trunk/engines/agos/gfx.cpp
===================================================================
--- scummvm/trunk/engines/agos/gfx.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/gfx.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -928,6 +928,12 @@
_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;
@@ -1057,7 +1063,7 @@
vsp->y = y;
vsp->x = x;
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;
else
vsp->palette = palette;
@@ -1168,7 +1174,7 @@
uint16 count;
const byte *vc_ptr_org;
- zoneNum = vgaSpriteId / 100;
+ zoneNum = (getGameType() == GType_PN) ? 0 : vgaSpriteId / 100;
for (;;) {
vpe = &_vgaBufferPointers[zoneNum];
@@ -1185,6 +1191,7 @@
_noOverWrite = 0xFFFF;
} else {
_curSfxFile = vpe->sfxFile;
+ _curSfxFileSize = vpe->sfxFileEnd - vpe->sfxFile;
_zoneNumber = zoneNum;
if (vpe->vgaFile1 != NULL)
@@ -1234,8 +1241,17 @@
}
assert(READ_BE_UINT16(&((ImageHeader_WW *) b)->id) == vgaSpriteId);
- if (!vgaScript)
- clearVideoWindow(_windowNum, READ_BE_UINT16(&((ImageHeader_WW *) b)->color));
+ if (!vgaScript) {
+ 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) {
@@ -1262,6 +1278,14 @@
_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) {
_window3Flag = 0;
@@ -1299,7 +1323,7 @@
}
}
-void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId) {
+void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCase) {
uint16 updateWindow;
_windowNum = updateWindow = mode;
@@ -1307,7 +1331,7 @@
if (getGameType() == GType_FF || getGameType() == GType_PP) {
vc27_resetSprite();
- } else {
+ } else if (!specialCase) {
VgaTimerEntry *vte = _vgaTimerList;
while (vte->type != ANIMATE_INT)
vte++;
@@ -1331,7 +1355,7 @@
}
}
- setImage(vgaSpriteId);
+ setImage(vgaSpriteId, specialCase);
if (getGameType() == GType_FF || getGameType() == GType_PP) {
fillBackGroundFromBack();
@@ -1423,6 +1447,9 @@
src = _window4BackScn;
srcWidth = _videoWindows[18] * 16;
}
+ } else {
+ src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth;
+ srcWidth = _screenWidth;
}
_boxStarHeight = height;
@@ -1433,7 +1460,14 @@
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;
int size = 67 * _screenWidth;
@@ -1449,4 +1483,26 @@
_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
Modified: scummvm/trunk/engines/agos/icons.cpp
===================================================================
--- scummvm/trunk/engines/agos/icons.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/icons.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -302,7 +302,7 @@
_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 *src;
@@ -329,6 +329,43 @@
_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) {
Item *item_ptr_org = itemRef;
WindowBlock *window;
@@ -923,7 +960,7 @@
void AGOSEngine_Simon1::removeArrows(WindowBlock *window, uint num) {
if (getGameType() == GType_SIMON1) {
- restoreBlock(200, 320, 146, 304);
+ restoreBlock(304, 146, 320, 200);
}
}
@@ -941,7 +978,7 @@
if (num != 2) {
uint y = window->height * 4 + window->y - 19;
uint x = window->width + window->x;
- restoreBlock(y + 38, x + 16, y, x);
+ restoreBlock(x, y, x + 16, y + 38);
} else {
colorBlock(window, 240, 151, 16, 38);
}
@@ -984,4 +1021,94 @@
_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
Modified: scummvm/trunk/engines/agos/input.cpp
===================================================================
--- scummvm/trunk/engines/agos/input.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/input.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -606,6 +606,129 @@
return verbCode;
}
-} // End of namespace AGOS
+// 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
Modified: scummvm/trunk/engines/agos/intern.h
===================================================================
--- scummvm/trunk/engines/agos/intern.h 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/intern.h 2009-03-08 08:45:21 UTC (rev 39216)
@@ -214,6 +214,22 @@
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 {
kOFText = 0x1,
kOFSize = 0x2,
@@ -251,11 +267,13 @@
GAME_TBLFILE = 1 << 7,
GAME_XTBLFILE = 1 << 8,
GAME_RESTFILE = 1 << 9,
+ GAME_TEXTFILE = 1 << 10,
- GAME_GFXIDXFILE = 1 << 10
+ GAME_GFXIDXFILE = 1 << 11
};
enum GameIds {
+ GID_PN,
GID_ELVIRA1,
GID_ELVIRA2,
GID_WAXWORKS,
Modified: scummvm/trunk/engines/agos/menus.cpp
===================================================================
--- scummvm/trunk/engines/agos/menus.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/menus.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -53,6 +53,27 @@
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
void AGOSEngine::drawMenuStrip(uint windowNum, uint menuNum) {
WindowBlock *window = _windowArray[windowNum % 8];
Modified: scummvm/trunk/engines/agos/module.mk
===================================================================
--- scummvm/trunk/engines/agos/module.mk 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/module.mk 2009-03-08 08:45:21 UTC (rev 39216)
@@ -20,6 +20,7 @@
midi.o \
midiparser_s1d.o \
oracle.o \
+ pn.o \
res.o \
res_ami.o \
res_snd.o \
@@ -28,6 +29,7 @@
script.o \
script_e1.o \
script_e2.o \
+ script_pn.o \
script_ww.o \
script_s1.o \
script_s2.o \
@@ -39,6 +41,7 @@
verb.o \
vga.o \
vga_e2.o \
+ vga_pn.o \
vga_ww.o \
vga_s1.o \
vga_s2.o \
Added: scummvm/trunk/engines/agos/pn.cpp
===================================================================
--- scummvm/trunk/engines/agos/pn.cpp (rev 0)
+++ scummvm/trunk/engines/agos/pn.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -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
Property changes on: scummvm/trunk/engines/agos/pn.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Modified: scummvm/trunk/engines/agos/res.cpp
===================================================================
--- scummvm/trunk/engines/agos/res.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/res.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -27,6 +27,7 @@
#include "common/file.h"
+#include "common/util.h"
#include "agos/agos.h"
#include "agos/intern.h"
@@ -149,6 +150,46 @@
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() {
Common::File in;
int fileSize;
@@ -646,6 +687,96 @@
#undef SD_TYPE_LITERAL
#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) {
uint32 offs, size;
@@ -690,7 +821,7 @@
}
}
-void AGOSEngine::loadVGAVideoFile(uint16 id, uint8 type) {
+void AGOSEngine::loadVGAVideoFile(uint16 id, uint8 type, bool useError) {
File in;
char filename[15];
byte *dst;
@@ -729,12 +860,16 @@
sprintf(filename, "%c%d.out", 48 + id, type);
} else if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2) {
sprintf(filename, "%.2d%d.pkd", id, type);
+ } else if (getGameType() == GType_PN) {
+ sprintf(filename, "%c%d.in", id + 48, type);
} else {
sprintf(filename, "%.3d%d.pkd", id, type);
}
} else {
if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
sprintf(filename, "%.2d%d.VGA", id, type);
+ } else if (getGameType() == GType_PN) {
+ sprintf(filename, "%c%d.out", id + 48, type);
} else {
sprintf(filename, "%.3d%d.VGA", id, type);
}
@@ -742,19 +877,42 @@
in.open(filename);
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();
- if (getFeatures() & GF_CRUNCHED) {
- byte *srcBuffer = (byte *)malloc(srcSize);
- if (in.read(srcBuffer, srcSize) != srcSize)
+ if (getGameType() == GType_PN && getPlatform() == Common::kPlatformPC && id == 17 && type == 2) {
+ // The A2.out file isn't compressed in PC version of Personal Nightmare
+ dst = allocBlock(dstSize + extraBuffer);
+ if (in.read(dst, dstSize) != dstSize)
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);
- dst = allocBlock (dstSize + extraBuffer);
- decrunchFile(srcBuffer, dst, srcSize);
- free(srcBuffer);
+ for (uint i = 0; i < srcSize / 4; ++i)
+ data.push(in.readUint32BE());
+
+ 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 {
dst = allocBlock(dstSize + extraBuffer);
if (in.read(dst, dstSize) != dstSize)
Modified: scummvm/trunk/engines/agos/res_ami.cpp
===================================================================
--- scummvm/trunk/engines/agos/res_ami.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/res_ami.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -92,7 +92,7 @@
}
}
-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];
byte *uncptr[kMaxColorDepth];
int length, i, j;
@@ -119,11 +119,20 @@
uncbfroutptr = uncbfrout;
const int chunkSize = colorDepth > 4 ? 16 : 8;
- for (i = 0; i < width / 16; ++i) {
+ if (horizontal) {
for (j = 0; j < height; ++j) {
- memcpy(dst + width * chunkSize / 16 * j + chunkSize * i, uncbfroutptr, chunkSize);
- uncbfroutptr += chunkSize;
+ for (i = 0; i < width / 16; ++i) {
+ 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;
+ }
+ }
}
free(uncbfrout);
@@ -152,7 +161,7 @@
byte *dst = _planarBuf;
if (compressed) {
- convertCompressedImage(src, dst, colorDepth, height, width);
+ convertCompressedImage(src, dst, colorDepth, height, width, (getGameType() == GType_PN));
} else {
length = (width + 15) / 16 * height;
for (i = 0; i < length; i++) {
Modified: scummvm/trunk/engines/agos/res_snd.cpp
===================================================================
--- scummvm/trunk/engines/agos/res_snd.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/res_snd.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -364,6 +364,8 @@
sprintf(filename, "%c%d.out", 48 + id, type);
} else if (getGameType() == GType_ELVIRA1 || getGameType() == GType_ELVIRA2) {
sprintf(filename, "%.2d%d.out", id, type);
+ } else if (getGameType() == GType_PN) {
+ sprintf(filename, "%c%d.in", id + 48, type);
} else {
sprintf(filename, "%.3d%d.out", id, type);
}
@@ -375,6 +377,8 @@
sprintf(filename, "%.2d.SND", elvira1_soundTable[id]);
} else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) {
sprintf(filename, "%.2d%d.VGA", id, type);
+ } else if (getGameType() == GType_PN) {
+ sprintf(filename, "%c%d.out", id + 48, type);
} else {
sprintf(filename, "%.3d%d.VGA", id, type);
}
@@ -386,7 +390,19 @@
}
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);
if (in.read(srcBuffer, srcSize) != srcSize)
error("loadVGASoundFile: Read failed");
@@ -457,41 +473,9 @@
_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;
-
if (getGameId() == GID_DIMP) {
File in;
char filename[15];
@@ -532,14 +516,69 @@
dst = _curSfxFile + READ_LE_UINT32(_curSfxFile + sound * 4);
}
- if (type == 3)
- _sound->playSfx5Data(dst, sound, pan, vol);
- else if (type == 2)
+ if (type == Sound::TYPE_AMBIENT)
_sound->playAmbientData(dst, sound, pan, vol);
- else
+ else if (type == Sound::TYPE_SFX)
_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) {
if (getGameType() == GType_PP && speechId == 99) {
_sound->stopVoice();
Modified: scummvm/trunk/engines/agos/saveload.cpp
===================================================================
--- scummvm/trunk/engines/agos/saveload.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/saveload.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -125,12 +125,21 @@
return buf;
}
-char *AGOSEngine::genSaveName(int slot) {
+char *AGOSEngine_Elvira1::genSaveName(int slot) {
static char buf[20];
sprintf(buf, "elvira1.%.3d", slot);
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() {
// Quick load & save is only supported complete version of Simon the Sorcerer 1/2
if (getGameType() == GType_PP || getGameType() == GType_FF ||
@@ -1544,4 +1553,125 @@
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
Modified: scummvm/trunk/engines/agos/script_e2.cpp
===================================================================
--- scummvm/trunk/engines/agos/script_e2.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/script_e2.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -574,9 +574,7 @@
void AGOSEngine_Elvira2::oe2_playEffect() {
// 174: play sound
uint soundId = getVarOrWord();
- loadSound(soundId);
-
- debug(0, "oe2_playEffect: stub (%d)", soundId);
+ loadSound(soundId, 0, 0);
}
void AGOSEngine_Elvira2::oe2_getDollar2() {
@@ -636,7 +634,7 @@
void AGOSEngine_Elvira2::oe2_isAdjNoun() {
// 179: item unk1 unk2 is
Item *item = getNextItemPtr();
- int16 a = getNextWord(), b = getNextWord();
+ int16 a = getNextWord(), n = getNextWord();
if (getGameType() == GType_ELVIRA2) {
// WORKAROUND bug #1745996: A NULL item can occur when
@@ -647,7 +645,7 @@
}
}
- setScriptCondition(item->adjective == a && item->noun == b);
+ setScriptCondition(item->adjective == a && item->noun == n);
}
void AGOSEngine_Elvira2::oe2_b2Set() {
Added: scummvm/trunk/engines/agos/script_pn.cpp
===================================================================
--- scummvm/trunk/engines/agos/script_pn.cpp (rev 0)
+++ scummvm/trunk/engines/agos/script_pn.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -0,0 +1,1109 @@
+/* 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 "agos/agos.h"
+#include "agos/vga.h"
+
+namespace AGOS {
+
+#define OPCODE(x) _OPCODE(AGOSEngine_PN, x)
+
+void AGOSEngine_PN::setupOpcodes() {
+ static const OpcodeEntryPN opcodes[] = {
+ /* 00 */
+ OPCODE(opn_opcode00),
+ OPCODE(opn_opcode01),
+ OPCODE(opn_opcode02),
+ OPCODE(opn_opcode03),
+ /* 04 */
+ OPCODE(opn_opcode04),
+ OPCODE(opn_opcode05),
+ OPCODE(opn_opcode06),
+ OPCODE(opn_opcode07),
+ /* 08 */
+ OPCODE(opn_opcode08),
+ OPCODE(opn_opcode09),
+ OPCODE(opn_opcode10),
+ OPCODE(opn_opcode11),
+ /* 12 */
+ OPCODE(opn_opcode12),
+ OPCODE(opn_opcode13),
+ OPCODE(opn_opcode14),
+ OPCODE(opn_opcode15),
+ /* 16 */
+ OPCODE(opn_opcode16),
+ OPCODE(opn_opcode17),
+ OPCODE(opn_opcode18),
+ OPCODE(opn_opcode19),
+ /* 20 */
+ OPCODE(opn_opcode20),
+ OPCODE(opn_opcode21),
+ OPCODE(opn_opcode22),
+ OPCODE(opn_opcode23),
+ /* 24 */
+ OPCODE(opn_opcode24),
+ OPCODE(opn_opcode25),
+ OPCODE(opn_opcode26),
+ OPCODE(opn_opcode27),
+ /* 28 */
+ OPCODE(opn_opcode28),
+ OPCODE(opn_opcode29),
+ OPCODE(opn_opcode30),
+ OPCODE(opn_opcode31),
+ /* 32 */
+ OPCODE(opn_opcode32),
+ OPCODE(opn_opcode33),
+ OPCODE(opn_opcode34),
+ OPCODE(opn_opcode35),
+ /* 36 */
+ OPCODE(opn_opcode36),
+ OPCODE(opn_opcode37),
+ OPCODE(opn_opcode38),
+ OPCODE(opn_opcode39),
+ /* 40 */
+ OPCODE(opn_opcode40),
+ OPCODE(opn_opcode41),
+ OPCODE(opn_opcode42),
+ OPCODE(opn_opcode43),
+ /* 44 */
+ OPCODE(opn_opcode44),
+ OPCODE(opn_opcode45),
+ OPCODE(opn_opcode46),
+ OPCODE(opn_opcode47),
+ /* 48 */
+ OPCODE(opn_opcode48),
+ OPCODE(opn_opcode49),
+ OPCODE(opn_opcode50),
+ OPCODE(opn_opcode51),
+ /* 52 */
+ OPCODE(opn_opcode52),
+ OPCODE(opn_opcode53),
+ OPCODE(opn_opcode54),
+ OPCODE(opn_opcode55),
+ /* 56 */
+ OPCODE(opn_opcode56),
+ OPCODE(opn_opcode57),
+ OPCODE(o_invalid),
+ OPCODE(o_invalid),
+ /* 60 */
+ OPCODE(o_invalid),
+ OPCODE(o_invalid),
+ OPCODE(opn_opcode62),
+ OPCODE(opn_opcode63),
+ };
+
+ _opcodesPN = opcodes;
+ _numOpcodes = 64;
+}
+
+void AGOSEngine_PN::executeOpcode(int opcode) {
+ OpcodeProcPN op = _opcodesPN[opcode].proc;
+ (this->*op) ();
+}
+
+#define readfromline() (_linct-- ? (int)*_workptr++ : readoverr())
+
+int readoverr() {
+ error("Internal Error - Line Over-run");
+}
+
+// -----------------------------------------------------------------------
+// Personal Nightmare Opcodes
+// -----------------------------------------------------------------------
+
+void AGOSEngine_PN::opn_opcode00() {
+ uint8 *str = _workptr;
+ varval();
+ writeval(str, varval());
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode01() {
+ uint8 *str = _workptr;
+ int32 sp = varval() + varval();
+ _variableArray[12] = sp % 65536;
+ _variableArray[13] = sp / 65536;
+ if (sp > 65535)
+ sp=65535;
+ writeval(str, (int)sp);
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode02() {
+ uint8 *str = _workptr;
+ int32 sp = varval();
+ sp -= varval();
+ _variableArray[12] = sp % 65536;
+ _variableArray[13] = sp / 65536;
+ if(sp < 0)
+ sp = 0;
+ writeval(str, (int)sp);
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode03() {
+ uint8 *str = _workptr;
+ int32 sp = varval() * varval();
+ _variableArray[12] = sp % 65536;
+ _variableArray[13] = sp / 65536;
+ if (sp > 65535)
+ sp = 65535;
+ writeval(str, (int)sp);
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode04() {
+ uint8 *str = _workptr;
+ int32 sp = varval();
+ int32 sp2 = varval();
+ if (sp2 == 0)
+ error("Division by 0");
+ sp = sp / sp2;
+ _variableArray[12] = sp % 65536;
+ _variableArray[13] = sp / 65536;
+ writeval(str, (int)sp);
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode05() {
+ pcf((uint8)'\n');
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode06() {
+ pmesd(varval());
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode07() {
+ int32 sp = varval();
+ plocd((int)sp, varval());
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode08() {
+ int32 sp = varval();
+ pobjd((int)sp, varval());
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode09() {
+ pmesd(varval());
+ pcf((uint8)'\n');
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode10() {
+ int32 sp = varval();
+ plocd((int)sp, varval());
+ pcf((uint8)'\n');
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode11() {
+ int32 sp = varval();
+ pobjd((int)sp, varval());
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode12() {
+ char bf[8];
+ int a = 0;
+ sprintf(bf,"%d", varval());
+ while(bf[a])
+ pcf(bf[a++]);
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode13() {
+ char bf[8];
+ int a = 0;
+ sprintf(bf,"%d", varval());
+ while(bf[a])
+ pcf(bf[a++]);
+ pcf((uint8)'\n');
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode14() {
+ clearWindow(_windowArray[_curWindow]);
+ pcf((uint8)255);
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode15() {
+ int32 x = varval();;
+ if ((x < 0) || (x > 4))
+ x = 0;
+
+ pcf((unsigned char)254);
+ _curWindow = x;
+ _xofs = (8 * _windowArray[_curWindow]->textLength) / 6 + 1;
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode16() {
+ int32 sp = varval();
+ setScriptReturn((sp >= 0 && sp <= 4));
+}
+
+void AGOSEngine_PN::opn_opcode17() {
+ int16 v1 = varval();
+ int16 v2 = varval();
+ setScriptReturn(v1 < v2);
+}
+
+void AGOSEngine_PN::opn_opcode18() {
+ int16 v1 = varval();
+ int16 v2 = varval();
+ setScriptReturn(v1 > v2);
+}
+
+void AGOSEngine_PN::opn_opcode19() {
+ int16 v1 = varval();
+ int16 v2 = varval();
+ setScriptReturn(v1 == v2);
+}
+
+void AGOSEngine_PN::opn_opcode20() {
+ int16 v1 = varval();
+ int16 v2 = varval();
+ setScriptReturn(v1 != v2);
+}
+
+void AGOSEngine_PN::opn_opcode21() {
+ setposition(_procnum, varval());
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode22() {
+ int pf[8];
+ int a;
+ a = varval();
+ funcentry(pf, a);
+ funccpy(pf);
+ setposition(a, 0);
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode23() {
+ setScriptReturn(actCallD(varval()));
+}
+
+void AGOSEngine_PN::opn_opcode24() {
+ popstack(-1);
+ longjmp(*(_stackbase->savearea), 2);
+ setScriptReturn(false);
+}
+
+void AGOSEngine_PN::opn_opcode25() {
+ popstack(-1);
+ longjmp(*(_stackbase->savearea), 1);
+ setScriptReturn(false);
+}
+
+void AGOSEngine_PN::opn_opcode26() {
+ while ((_stackbase->classnum != -1) && (_stackbase != NULL))
+ junkstack();
+ dumpstack();
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode27() {
+ quitGame();
+ // Make sure the quit event is processed immediately.
+ delay(0);
+}
+
+void AGOSEngine_PN::opn_opcode28() {
+ addstack(varval());
+ _stackbase->savearea = _cjmpbuff;
+ setScriptReturn(false);
+}
+
+void AGOSEngine_PN::opn_opcode29() {
+ popstack(varval());
+ longjmp(*(_stackbase->savearea), -1);
+ setScriptReturn(false);
+}
+
+void AGOSEngine_PN::opn_opcode30() {
+ _variableArray[1] = varval();
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode31() {
+ int a, slot = 0;
+ char bf[60];
+
+ if ((a = varval()) > 2) {
+ setScriptReturn(false);
+ return;
+ }
+
+ switch (a) {
+ case 0:
+ getFilename();
+ slot = matchSaveGame(_saveFile, countSaveGames());
+ strcpy(bf, genSaveName(slot));
+ break;
+ case 1:
+ strcpy(bf, "test.sav");
+ break;
+ case 2:
+ // NOTE: Is this case ever used?
+ error("opn_opcode31: case 2");
+ break;
+ }
+
+ a = loadfl(bf);
+ if (a)
+ setScriptReturn(badload(a));
+ else
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode32() {
+ char bf[60];
+ int a;
+
+ if ((a = varval()) > 2) {
+ setScriptReturn(true);
+ return;
+ }
+
+ switch (a) {
+ case 0:
+ getFilename();
+ strcpy(bf, genSaveName(countSaveGames()));
+ break;
+ case 1:
+ strcpy(bf, "test.sav");
+ break;
+ case 2:
+ // NOTE: Is this case ever used?
+ error("opn_opcode32: case 2");
+ break;
+ }
+
+ a = savfl(bf);
+ setScriptReturn(a);
+}
+
+void AGOSEngine_PN::opn_opcode33() {
+ setScriptReturn((varval() < 3) ? 1 : 0);
+}
+
+void AGOSEngine_PN::opn_opcode34() {
+ uint16 msgNum1, msgNum2;
+ varval();
+ getResponse((int)_variableArray[166], (int)_variableArray[167], msgNum1, msgNum2);
+ _variableArray[168]= msgNum1;
+ _variableArray[169]= msgNum2;
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode35() {
+ int a;
+ uint8 *sav = _workptr;
+ varval();
+ a = varval();
+ if ((a = gvwrd((uint8 *)_wordcp, a)) == -1) {
+ setScriptReturn(false);
+ return;
+ }
+
+ writeval(sav, a);
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode36() {
+ int ct = 0;
+ while (ct < _dataBase[57] + 1)
+ _wordcp[ct++] = 0;
+ ct = 1;
+ if (isspace(*_inpp))
+ while ((*_inpp) && (isspace(*_inpp)))
+ _inpp++;
+ if (*_inpp == 0) {
+ setScriptReturn(false);
+ return;
+ }
+ _curwrdptr = _inpp;
+ _wordcp[0] = *_inpp++;
+ if ((_wordcp[0] == '.') || (_wordcp[0] == ',') || (_wordcp[0] == '"')) {
+ setScriptReturn(true);
+ return;
+ }
+ while ((*_inpp != '.') && (*_inpp != ',') && (!isspace(*_inpp)) && (*_inpp != '\0') &&
+ (*_inpp!='"')) {
+ if (ct < _dataBase[57])
+ _wordcp[ct++] = *_inpp;
+ _inpp++;
+ }
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode37() {
+ _curwrdptr = NULL;
+
+ _inputReady = 1;
+ interact(_inputline, 49);
+
+ if ((_inpp = strchr(_inputline,'\n')) != NULL)
+ *_inpp = '\0';
+ _inpp = _inputline;
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode38() {
+ _noScanFlag = 1;
+ clearInputLine();
+ writeval(_workptr, _keyPressed.ascii);
+ _keyPressed.reset();
+ _noScanFlag = 0;
+ varval();
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode39() {
+ pcf((uint8)varval());
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode40() {
+ setScriptReturn(doaction() | doaction());
+}
+
+void AGOSEngine_PN::opn_opcode41() {
+ setScriptReturn(doaction() & doaction());
+}
+
+void AGOSEngine_PN::opn_opcode42() {
+ setScriptReturn(doaction() ^ doaction());
+}
+
+void AGOSEngine_PN::opn_opcode43() {
+ setScriptReturn(!(doaction()));
+}
+
+void AGOSEngine_PN::opn_opcode44() {
+ pcf((uint8)254);
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode45() {
+ uint8 *myptr;
+ int x;
+
+ if (_havinit == 0) {
+ _seed = (int16)getTime();
+ _havinit = 1;
+ }
+ _seed = 1 + (75 * (_seed + 1) - 1) % 65537;
+ myptr = _workptr;
+ varval();
+ x = varval();
+ if (x == 0)
+ error("Illegal range specified for RANDOM");
+ writeval(myptr, (_seed % x));
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode46() {
+ char *x = _curwrdptr;
+ if (x == NULL) {
+ setScriptReturn(true);
+ return;
+ }
+ pcf(*x);
+ if ((*x == '.') || (*x == '"') || (*x == ',')) {
+ setScriptReturn(true);
+ return;
+ }
+ x++;
+ while ((*x != '.') && (*x != ',') && (*x != '"') && (!isspace(*x)) && (*x != '\0'))
+ pcf(*x++);
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode47() {
+ pmesd(varval() * 256 + varval());
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode48() {
+ pmesd(varval() * 256 + varval());
+ pcf((uint8)'\n');
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode49() {
+ setScriptReturn(findentry());
+}
+
+void AGOSEngine_PN::opn_opcode50() {
+ _fnst = 0;
+ setScriptReturn(findset());
+}
+
+void AGOSEngine_PN::opn_opcode51() {
+ _fnst = varval();
+ setScriptReturn(findset());
+}
+
+void AGOSEngine_PN::opn_opcode52() {
+ int32 mode = varval();
+ if (mode == 1) {
+ setWindowImage(mode, varval(), true);
+ } else {
+ setWindowImageEx(mode, varval());
+ }
+
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode53() {
+ vc27_resetSprite();
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode54() {
+ stopAnimate(varval());
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode55() {
+ varval();
+ varval();
+ varval();
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode56() {
+ varval();
+ varval();
+ varval();
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode57() {
+ uint16 windowNum = varval();
+ uint16 vgaSpriteId = varval();
+ int16 x = varval();
+ int16 y = varval();
+ uint16 palette = varval();
+
+ _lockWord |= 0x40;
+ animate(windowNum, 0, vgaSpriteId, x, y, palette);
+ _lockWord &= ~0x40;
+
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode62() {
+ int32 zoneNum = varval();
+
+ _lockWord |= 0x80;
+
+ vc29_stopAllSounds();
+
+ _hitCalled = 0;
+ _oneClick = 0;
+
+ loadZone(zoneNum);
+
+ setWindowImage(2, 2);
+
+ _copyScnFlag = 0;
+ _vgaSpriteChanged = 0;
+
+ _lockWord &= ~0x80;
+
+ setScriptReturn(true);
+}
+
+void AGOSEngine_PN::opn_opcode63() {
+ int a = readfromline();
+ switch (a) {
+ case 65:
+ setScriptReturn(inventoryOn(varval()));
+ break;
+ case 64:
+ setScriptReturn((_lockWord & 0x10) != 0);
+ break;
+ case 63:
+ setScriptReturn(inventoryOff());
+ break;
+ default:
+ error("opn_opcode63: unknown code %d", a);
+ }
+}
+
+int AGOSEngine_PN::inventoryOn(int val) {
+ writeVariable(210, val);
+ if (_lockWord & 0x10) {
+ iconPage();
+ } else {
+ _lockWord |= 0x10;
+ _hitAreaList = _invHitAreas;
+
+ _windowArray[2]->textColor = 0;
+ windowPutChar(_windowArray[2], 13);
+
+ clearVideoWindow(4, 0);
+ drawIconHitBar();
+
+ _objects = _variableArray[211];
+ _objectCountS = -1;
+ iconPage();
+ }
+ return 1;
+}
+
+int AGOSEngine_PN::inventoryOff() {
+ if (_lockWord & 0x10) {
+ _windowArray[2]->textColor = 15;
+
+ restoreBlock(48, 2, 272, 130);
+
+ _hitAreaList = _hitAreas;
+ _lockWord &= ~0x10;
+ _vgaSpriteChanged++;
+ }
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+// Personal Nightmare Script Code
+// -----------------------------------------------------------------------
+
+
+static int bitvalue[8] = {128, 64, 32, 16, 8, 4, 2, 1};
+
+int AGOSEngine_PN::bitextract(uint32 ptr, int offs) {
+ return ((bitvalue[offs % 8] & _dataBase[ptr + offs / 8]) != 0);
+}
+
+uint16 AGOSEngine_PN::getptr(uint32 pos) {
+ if (pos > _dataBaseSize)
+ error("getptr: Read beyond EOF (%d)", pos);
+ return (int)READ_LE_UINT16(_dataBase + pos);
+}
+
+uint32 AGOSEngine_PN::getlong(uint32 pos) {
+ if (pos > _dataBaseSize)
+ error("getlong: Read beyond EOF (%d)", pos);
+ return (uint32)READ_LE_UINT24(_dataBase + pos);
+}
+
+int AGOSEngine_PN::varval() {
+ int a;
+ int b;
+
+ if ((a = readfromline()) < 247) {
+ return a;
+ }
+
+ switch (a) {
+ case 249:
+ b = readfromline();
+ return((int)(b + 256 * readfromline()));
+ break;
+ case 250:
+ return(readfromline());
+ case 251:
+ return((int)_variableArray[varval()]);
+ case 252:
+ b = varval();
+ return((int)_dataBase[_quickptr[0] + b * _quickshort[0] + varval()]);
+ case 254:
+ b = varval();
+ return((int)_dataBase[_quickptr[3] + b * _quickshort[2] + varval()]);
+ case 247:
+ b = varval();
+ return((int)getptr(_quickptr[11] + (b * _quickshort[4]) + (2 * varval())));
+ case 248:
+ b = varval();
+ return((int)getptr(_quickptr[12] + (b * _quickshort[5]) + (2 * varval())));
+ case 253:
+ b = varval();
+ return(bitextract((int32)_quickptr[1] + b * _quickshort[1], varval()));
+ case 255:
+ b = varval();
+ return(bitextract((int32)_quickptr[4] + b * _quickshort[3], varval()));
+ default:
+ error("VARVAL : Illegal code encountered");
+ }
+}
+
+void AGOSEngine_PN::writeval(uint8 *ptr, int val) {
+ uint8 *savpt = _workptr;
+ int lsav = _linct, a, b, x;
+ _workptr = ptr;
+ _linct = 255;
+
+ if ((a = readfromline()) < 247)
+ error("Write to constant");
+
+ switch (a) {
+ case 249:
+ error("Write to constant");
+ break;
+ case 250:
+ error("Write to constant");
+ break;
+ case 251:
+ _variableArray[varval()] = val;
+ break;
+ case 252:
+ b = varval();
+ _dataBase[_quickptr[0] + b * _quickshort[0] + varval()] = val;
+ break;
+ case 254:
+ b = varval();
+ _dataBase[_quickptr[3] + b * _quickshort[2] + varval()] = val;
+ break;
+ case 247:
+ b = varval();
+ x = _quickptr[11] + b * _quickshort[4] + varval() * 2;
+ WRITE_LE_UINT16(_dataBase + x, val);
+ break;
+ case 248:
+ b = varval();
+ x = _quickptr[12] + b * _quickshort[5] + varval() * 2;
+ WRITE_LE_UINT16(_dataBase + x, val);
+ break;
+ case 253:
+ b = varval();
+ setbitf((uint32)_quickptr[1] + b * _quickshort[1], varval(), val);
+ break;
+ case 255:
+ b = varval();
+ setbitf((uint32)_quickptr[4] + b * _quickshort[3], varval(), val);
+ break;
+ default:
+ error("WRITEVAL : undefined evaluation");
+ }
+ _linct = lsav;
+ _workptr = savpt;
+}
+
+void AGOSEngine_PN::setbitf(uint32 ptr, int offs, int val) {
+ ptr += offs / 8;
+ _dataBase[ptr] &= (255 - bitvalue[offs % 8]);
+ if (val != 0)
+ _dataBase[ptr] |= bitvalue[offs % 8];
+}
+
+int AGOSEngine_PN::actCallD(int n) {
+ int pf[8];
+ funcentry(pf, n);
+ addstack(-1);
+ funccpy(pf);
+ setposition(n, 0);
+ return(doline(1));
+}
+
+int AGOSEngine_PN::doaction() {
+ if (_linct == 0)
+ return 0;
+
+ _opcode = readfromline();
+
+ if (_opcode > 63) {
+ return (actCallD(_opcode - 64));
+ }
+
+ setScriptReturn(0);
+ executeOpcode(_opcode);
+ delay(0);
+
+ return getScriptReturn();
+}
+
+int AGOSEngine_PN::doline(int needsave) {
+ int x;
+ jmp_buf *ljmpbuff = NULL;
+ jmp_buf *mybuf;
+
+ mybuf = (jmp_buf *)malloc(sizeof(jmp_buf));
+ if (mybuf == NULL)
+ error("Out of memory - stack overflow");
+
+ if ((x = setjmp(*mybuf)) > 0) {
+ dumpstack();
+ _cjmpbuff = ljmpbuff;
+ free((char *)mybuf);
+ return (x - 1);
+ }
+
+ if (x == -1) {
+ _cjmpbuff = mybuf;
+ goto carryon;
+ }
+ ljmpbuff = _cjmpbuff;
+ _cjmpbuff = mybuf;
+ if (needsave)
+ _stackbase->savearea = mybuf;
+
+nln: _linct = ((*_linebase) & 127) - 1;
+ _workptr = _linebase + 1;
+ if (*_linebase > 127) {
+ x = varval();
+ if (x != (int)_variableArray[1])
+ goto skipln;
+ }
+
+carryon:
+ while((x = doaction()) && !shouldQuit());
+
+skipln: _linebase += 127 & *_linebase;
+ _linembr++;
+
+ if (!shouldQuit())
+ goto nln;
+
+ return 0;
+}
+
+int AGOSEngine_PN::findentry() {
+ int stepmt;
+ int curObj = 0;
+ uint32 ofs = _quickptr[11];
+ int c1, c2;
+
+ c1 = varval();
+ c2 = varval();
+ stepmt = _quickshort[4];
+
+ while (curObj < _quickshort[6]) {
+ if (((c1 == 255) || (c1 == getptr(ofs))) &&
+ (c2 == getptr(ofs + 2))) {
+ _variableArray[23] = curObj;
+ return 1;
+ }
+ curObj++;
+ ofs += stepmt;
+ }
+ return 0;
+}
+
+int AGOSEngine_PN::findset() {
+ int curObj = _fnst;
+ int c1, c2, c3, c4;
+ int stepmt = _quickshort[4];
+ uint32 ofs = _quickptr[11] + stepmt * curObj;
+ c1 = varval();
+ c2 = varval();
+ c3 = varval();
+ c4 = varval();
+ while (curObj < _quickshort[6]) {
+ if (((c1 ==255) || (c1 == getptr(ofs))) &&
+ ((c2 == 255) || (c2 == getptr(ofs + 2))) &&
+ ((c3 == 255) || (c3 == getptr(ofs + 4))) &&
+ ((c4 == 255) || (c4 == getptr(ofs + 6)))) {
+ _variableArray[23] = curObj;
+ _fnst = curObj + 1;
+ return 1;
+ }
+ curObj++;
+ ofs += stepmt;
+ }
+ return 0;
+}
+
+void AGOSEngine_PN::funccpy(int *store) {
+ int a = 0;
+ int b = 24;
+
+ while (a < 8) {
+ _variableArray[b++] = *store++;
+ a++;
+ }
+}
+
+void AGOSEngine_PN::funcentry(int *store, int procn) {
+ int ct = 0;
+ int nprm;
+
+ nprm = _dataBase[getlong(_quickptr[6] + 3L * procn)];
+ while (ct < nprm) {
+ *store++ = varval();
+ ct++;
+ }
+}
+
+int AGOSEngine_PN::gvwrd(uint8 *wptr, int mask) {
+ int val, code, q = _dataBase[57];
+ uint8 *vocbase = _dataBase + getlong(15);
+ while (*vocbase != 255) {
+ if (*vocbase < 128) {
+ val = vocbase[q] + 256 * vocbase[q + 1];
+ code = vocbase[q + 2];
+ }
+ if (wrdmatch(vocbase, mask, wptr, code))
+ return val;
+ vocbase += (*vocbase > 127) ? q : q + 3;
+ }
+ return -1;
+}
+
+int AGOSEngine_PN::samewrd(uint8 *w1, uint8 *w2, int ln) {
+ int ct = 0;
+
+ while (ct < ln) {
+ if (toupper(*w1) > toupper(*w2))
+ return 1;
+ if (toupper(*w1) < toupper(*w2))
+ return -1;
+ ct++;
+ w1++;
+ w2++;
+ }
+ return 0;
+}
+
+int AGOSEngine_PN::setposition(int process, int line) {
+ uint8 *ourptr;
+ int np;
+ int ct = 0;
+ ourptr = _dataBase + getlong(_quickptr[6] + 3L * process);
+ np = *ourptr++;
+ while (ct < line) {
+ ourptr += (127 & *ourptr);
+ ct++;
+ }
+x1: _linebase = ourptr;
+ _linct = (127 & (*ourptr)) - 1;
+ if (*ourptr++ > 127) {
+ ct = varval();
+ if (ct != (int)_variableArray[1]) {
+ ourptr += _linct - 1;
+ line++;
+ goto x1;
+ }
+ }
+ _linembr = line;
+ _procnum = process;
+ _variableArray[0] = process;
+ _workptr = ourptr;
+ return np;
+}
+
+int AGOSEngine_PN::wrdmatch(uint8 *word1, int mask1, uint8 *word2, int mask2) {
+ uint8 sv;
+
+ if ((mask1 & mask2) == 0)
+ return 0;
+
+ sv = *word1;
+ *word1 &= 127;
+ if (samewrd(word1, word2, _dataBase[57])) {
+ *word1 = sv;
+ return 0;
+ }
+ *word1 = sv;
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+// Personal Nightmare Stack Code
+// -----------------------------------------------------------------------
+
+void AGOSEngine_PN::addstack(int type) {
+ struct stackframe *a;
+ int pt, ct = 0;
+
+ a = (struct stackframe *)malloc(sizeof(struct stackframe));
+ if (a == NULL)
+ error("Out of memory - stack overflow");
+
+ a->nextframe = _stackbase;
+ _stackbase = a;
+ pt = 0;
+ while (ct < 6)
+ a->flag[ct++] = _variableArray[pt++];
+ ct = 0;
+ pt = 24;
+ while (ct < 8)
+ a->param[ct++] = _variableArray[pt++];
+ a->classnum = type;
+ a->ll = _linct;
+ a->linenum = _linembr;
+ a->linpos = _workptr;
+ a->lbase = _linebase;
+ a->process = _procnum;
+}
+
+void AGOSEngine_PN::dumpstack() {
+ struct stackframe *a;
+
+ if (_stackbase == NULL)
+ error("Stack underflow or unknown longjmp");
+
+ a = _stackbase->nextframe;
+ free((char *)_stackbase);
+ _stackbase = a;
+}
+
+void AGOSEngine_PN::junkstack() {
+ struct stackframe *a;
+
+ if (_stackbase == NULL)
+ error("Stack underflow or unknown longjmp");
+
+ a = _stackbase->nextframe;
+ if (_stackbase->classnum == -1)
+ free((char *)_stackbase->savearea);
+ free((char *)_stackbase);
+ _stackbase = a;
+}
+
+void AGOSEngine_PN::popstack(int type) {
+ int a = 0, b;
+
+ while ((_stackbase != NULL) && (_stackbase->classnum != type))
+ junkstack();
+
+ if (_stackbase == NULL)
+ error("Stack underflow or unknown longjmp");
+
+ _linct = _stackbase->ll;
+ _linebase = _stackbase->lbase;
+ _workptr = _stackbase->linpos;
+ _procnum = _stackbase->process;
+ _linembr = _stackbase->linenum;
+ b = 0;
+ while (a < 6)
+ _variableArray[b++] = _stackbase->flag[a++];
+ b = 24;
+ a = 0;
+ while (a < 8)
+ _variableArray[b++] = _stackbase->param[a++];
+}
+
+} // End of namespace AGOS
Property changes on: scummvm/trunk/engines/agos/script_pn.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Modified: scummvm/trunk/engines/agos/sound.cpp
===================================================================
--- scummvm/trunk/engines/agos/sound.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/sound.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -389,6 +389,11 @@
_ambientPlaying = 0;
+ _soundQueuePtr = 0;
+ _soundQueueNum = 0;
+ _soundQueueSize = 0;
+ _soundQueueFreq = 0;
+
if (_vm->getFeatures() & GF_TALKIE) {
loadVoiceFile(gss);
@@ -649,6 +654,10 @@
return _hasVoiceFile;
}
+bool Sound::isSfxActive() const {
+ return _mixer->isSoundHandleActive(_effectsHandle);
+}
+
bool Sound::isVoiceActive() const {
return _mixer->isSoundHandleActive(_voiceHandle);
}
@@ -660,6 +669,10 @@
_ambientPlaying = 0;
}
+void Sound::stopSfx() {
+ _mixer->stopHandle(_effectsHandle);
+}
+
void Sound::stopVoice() {
_mixer->stopHandle(_voiceHandle);
}
@@ -686,8 +699,33 @@
}
}
+// 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
-void Sound::playRawData(byte *soundData, uint sound, uint size) {
+void Sound::playRawData(byte *soundData, uint sound, uint size, uint freq) {
if (_effectsPaused)
return;
@@ -695,9 +733,9 @@
memcpy(buffer, soundData, size);
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
- _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
Modified: scummvm/trunk/engines/agos/sound.h
===================================================================
--- scummvm/trunk/engines/agos/sound.h 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/sound.h 2009-03-08 08:45:21 UTC (rev 39216)
@@ -26,6 +26,7 @@
#ifndef AGOS_SOUND_H
#define AGOS_SOUND_H
+#include "sound/audiostream.h"
#include "sound/mixer.h"
#include "agos/intern.h"
#include "common/str.h"
@@ -60,12 +61,23 @@
bool _hasEffectsFile;
bool _hasVoiceFile;
- uint _ambientPlaying;
+ uint16 _ambientPlaying;
+ // Personal Nightmare specfic
+ byte *_soundQueuePtr;
+ uint16 _soundQueueNum;
+ uint32 _soundQueueSize;
+ uint16 _soundQueueFreq;
public:
Sound(AGOSEngine *vm, const GameSpecificSettings *gss, Audio::Mixer *mixer);
~Sound();
+ enum TypeFlags {
+ TYPE_AMBIENT = 1 << 0,
+ TYPE_SFX = 1 << 1,
+ TYPE_SFX5 = 1 << 2
+ };
+
void loadVoiceFile(const GameSpecificSettings *gss);
void loadSfxFile(const GameSpecificSettings *gss);
@@ -77,8 +89,12 @@
void playEffects(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
- void playRawData(byte *soundData, uint sound, uint size);
+ void playRawData(byte *soundData, uint sound, uint size, uint freq);
// Feeble Files specific
void playAmbientData(byte *soundData, uint sound, uint pan, uint vol);
@@ -89,8 +105,10 @@
void switchVoiceFile(const GameSpecificSettings *gss, uint disc);
bool hasVoice() const;
+ bool isSfxActive() const;
bool isVoiceActive() const;
void stopAllSfx();
+ void stopSfx();
void stopSfx5();
void stopVoice();
void stopAll();
Modified: scummvm/trunk/engines/agos/string.cpp
===================================================================
--- scummvm/trunk/engines/agos/string.cpp 2009-03-08 08:17:59 UTC (rev 39215)
+++ scummvm/trunk/engines/agos/string.cpp 2009-03-08 08:45:21 UTC (rev 39216)
@@ -910,4 +910,649 @@
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);
@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list