diff --git a/engines/private/code.cpp b/engines/private/code.cpp index b587ea1b8a1..000f33c9596 100644 --- a/engines/private/code.cpp +++ b/engines/private/code.cpp @@ -171,6 +171,9 @@ int eval() /* evaluate variable on stack */ } else if (d.u.sym->type == STRING) { d.type = STRING; d.u.str = d.u.sym->u.str; + } else if (d.u.sym->type == RECT) { + d.type = RECT; + d.u.rect = d.u.sym->u.rect; } else if (d.u.sym->type == NAME) { //debug("NAME %s", d.sym->name->c_str()); //d.sym = d.sym; @@ -188,6 +191,23 @@ int add() /* add top two elems on stack */ Datum d1, d2; d2 = pop(); d1 = pop(); + if (d1.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d1.u.val = d1.u.sym->u.val; + d1.type = NUM; + } + + if (d2.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d2.u.val = d2.u.sym->u.val; + d2.type = NUM; + } + + assert(d1.type == NUM); + assert(d2.type == NUM); + //printf("adding %d %d\n",d1.val, d2.val); d1.u.val += d2.u.val; push(d1); @@ -234,6 +254,21 @@ int gt() Datum d1, d2; d2 = pop(); d1 = pop(); + if (d1.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d1.u.val = d1.u.sym->u.val; + d1.type = NUM; + } + + if (d2.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d2.u.val = d2.u.sym->u.val; + d2.type = NUM; + } + + d1.u.val = (int)(d1.u.val > d2.u.val); push(d1); return 0; @@ -244,6 +279,21 @@ int lt() Datum d1, d2; d2 = pop(); d1 = pop(); + if (d1.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d1.u.val = d1.u.sym->u.val; + d1.type = NUM; + } + + if (d2.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d2.u.val = d2.u.sym->u.val; + d2.type = NUM; + } + + d1.u.val = (int)(d1.u.val < d2.u.val); push(d1); return 0; @@ -254,6 +304,21 @@ int ge() Datum d1, d2; d2 = pop(); d1 = pop(); + if (d1.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d1.u.val = d1.u.sym->u.val; + d1.type = NUM; + } + + if (d2.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d2.u.val = d2.u.sym->u.val; + d2.type = NUM; + } + + d1.u.val = (int)(d1.u.val >= d2.u.val); push(d1); return 0; @@ -264,6 +329,21 @@ int le() Datum d1, d2; d2 = pop(); d1 = pop(); + if (d1.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d1.u.val = d1.u.sym->u.val; + d1.type = NUM; + } + + if (d2.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d2.u.val = d2.u.sym->u.val; + d2.type = NUM; + } + + d1.u.val = (int)(d1.u.val <= d2.u.val); push(d1); return 0; @@ -274,6 +354,21 @@ int eq() Datum d1, d2; d2 = pop(); d1 = pop(); + if (d1.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d1.u.val = d1.u.sym->u.val; + d1.type = NUM; + } + + if (d2.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d2.u.val = d2.u.sym->u.val; + d2.type = NUM; + } + + d1.u.val = (int)(d1.u.val == d2.u.val); push(d1); return 0; @@ -284,7 +379,22 @@ int ne() Datum d1, d2; d2 = pop(); d1 = pop(); - d1.u.val = (int)(d1.u.val != d2.u.val); + if (d1.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d1.u.val = d1.u.sym->u.val; + d1.type = NUM; + } + + if (d2.type == NAME) { + //char *name = d1.u.sym->name->c_str(); + //debug("eval %s to %d", + d2.u.val = d2.u.sym->u.val; + d2.type = NUM; + } + + + d1.u.val = (int)(d1.u.val != d2.u.val); push(d1); return 0; } diff --git a/engines/private/detection.cpp b/engines/private/detection.cpp index d8068c3e46c..2ba708a9163 100644 --- a/engines/private/detection.cpp +++ b/engines/private/detection.cpp @@ -18,12 +18,22 @@ static const ADGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO1(GUIO_NOMIDI) }, + { + "private-eye", + 0, + AD_ENTRY1s("GAME.TXT", "28ee7295db2cf6d9358ad737e3a4c4c0", 19286), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + GUIO1(GUIO_NOMIDI) + }, + AD_TABLE_END_MARKER }; } // End of namespace Private static const char *const directoryGlobs[] = { - "support", // english CD + "assets", // english CD 0 }; diff --git a/engines/private/funcs.cpp b/engines/private/funcs.cpp index a4fc91671aa..82d706ba2ef 100644 --- a/engines/private/funcs.cpp +++ b/engines/private/funcs.cpp @@ -18,10 +18,12 @@ void ChgMode(ArgArray args) { if (g_private->_mode == 0) { g_private->_origin->x = 0; g_private->_origin->y = 0; + // TODO: should clear the screen? } else if (g_private->_mode == 1) { g_private->_origin->x = 63; g_private->_origin->y = 48; + g_private->drawScreenFrame(); } else assert(0); @@ -57,6 +59,11 @@ void DossierAdd(ArgArray args) { debug("WARNING: DossierAdd is not implemented"); } +void Inventory(ArgArray args) { + // assert types + debug("WARNING: Inventory is not implemented"); +} + void SetFlag(ArgArray args) { // assert types debug("SetFlag(%s, %d)", args[0].u.sym->name->c_str(), args[1].u.val); @@ -66,7 +73,7 @@ void SetFlag(ArgArray args) { void Exit(ArgArray args) { // assert types assert(args[2].type == RECT || args[2].type == NAME); - debug("Exit(..)"); //, args[0].u.str, args[1].u.sym->name->c_str(), "RECT"); + debug("Exit(%d %d %d)", args[0].type, args[1].type, args[2].type); //, args[0].u.str, args[1].u.sym->name->c_str(), "RECT"); ExitInfo *e = (ExitInfo*) malloc(sizeof(ExitInfo)); if (args[0].type == NUM && args[0].u.val == 0) @@ -79,7 +86,13 @@ void Exit(ArgArray args) { else e->cursor = args[1].u.sym->name; + if (args[2].type == NAME) { + assert(args[2].u.sym->type == RECT); + args[2].u.rect = args[2].u.sym->u.rect; + } + e->rect = args[2].u.rect; + debug("Rect %d %d %d %d", args[2].u.rect->top, args[2].u.rect->left, args[2].u.rect->bottom, args[2].u.rect->right); g_private->_exits.push_front(*e); } @@ -102,10 +115,25 @@ void Sound(ArgArray args) { } } +void LoopedSound(ArgArray args) { + // assert types + assert(args.size() == 1); + debug("LoopedSound(%s)", args[0].u.str); + if (strcmp("\"\"", args[0].u.str) != 0) { + Common::String *s = new Common::String(args[0].u.str); + g_private->playSound(*s); + //assert(0); + } else { + g_private->stopSound(); + } +} + + + void Transition(ArgArray args) { // assert types debug("Transition(%s, %s)", args[0].u.str, args[1].u.str); - //g_private->_nextMovie = new Common::String(args[0].u.str); + g_private->_nextMovie = new Common::String(args[0].u.str); g_private->_nextSetting = new Common::String(args[1].u.str); } @@ -187,7 +215,13 @@ void Mask(ArgArray args, bool drawn) { void Timer(ArgArray args) { - debug("Timer(%d, %s, %s)", args[0].u.val, args[1].u.str, args[2].u.str); + assert (args.size() == 2 || args.size() == 3); + + if (args.size() == 3) + debug("Timer(%d, %s, %s)", args[0].u.val, args[1].u.str, args[2].u.str); + else + debug("Timer(%d, %s)", args[0].u.val, args[1].u.str); + g_system->delayMillis(100 * args[0].u.val); Common::String *s = new Common::String(args[1].u.str); g_private->_nextSetting = s; @@ -208,6 +242,12 @@ void execFunction(char *name, ArgArray args) { else if (strcmp(name, "Sound") == 0) { Sound(args); } + else if (strcmp(name, "SoundEffect") == 0) { + Sound(args); // Unclear how this is different from Sound + } + else if (strcmp(name, "LoopedSound") == 0) { + LoopedSound(args); + } else if (strcmp(name, "Bitmap") == 0) { Bitmap(args); } @@ -242,6 +282,9 @@ void execFunction(char *name, ArgArray args) { else if (strcmp(name, "DossierAdd") == 0) { DossierAdd(args); } + else if (strcmp(name, "Inventory") == 0) { + Inventory(args); + } else if (strcmp(name, "VSPicture") == 0) { VSPicture(args); } diff --git a/engines/private/grammar.h b/engines/private/grammar.h index 2986cfc5b91..d5728058b8b 100644 --- a/engines/private/grammar.h +++ b/engines/private/grammar.h @@ -116,6 +116,8 @@ extern int lt(); extern int gt(); extern int le(); extern int ge(); +extern int eq(); +extern int ne(); // Code Execution diff --git a/engines/private/grammar.y b/engines/private/grammar.y index 2a67f65d2c6..d5adc8eab1d 100644 --- a/engines/private/grammar.y +++ b/engines/private/grammar.y @@ -68,7 +68,12 @@ statements: /* nothing */ { $$ = progp; } | statement statements -statement: GOTOTOK expr ';' { /*TODO*/ } +statement: GOTOTOK NAME ';' { + code2(strpush, (Private::Inst) Private::addconstant(STRING, 0, $NAME)); + code2(constpush, (Private::Inst) Private::addconstant(NUM, 1, NULL)); + code2(strpush, (Private::Inst) Private::addconstant(STRING, 0, "goto")); + code1(funcpush); + } | fcall ';' { } | if cond body end { /* else-less if */ @@ -98,7 +103,8 @@ cond: '(' expr ')' { code(STOP); $$ = $2; } define: /* nothing */ | NAME ',' RECT '(' NUM ',' NUM ',' NUM ',' NUM ')' ',' define { - Common::Rect *r = new Common::Rect($5->u.val, $7->u.val, $9->u.val, $11->u.val); + Common::Rect *r = new Common::Rect($5->u.val, $7->u.val, $9->u.val, $11->u.val); + assert(r->isValidRect()); define($NAME, r); } | NAME ',' RECT '(' NUM ',' NUM ',' NUM ',' NUM ')' { @@ -146,13 +152,13 @@ value: NULLTOK { code2(Private::constpush, (Private::Inst) Private::addconst expr: value { $$ = $1; } | '!' value { code1(Private::negate); $$ = $2; } - | value EQ value - | value NEQ value + | value EQ value { code1(Private::eq); } + | value NEQ value { code1(Private::ne); } | value '+' value { code1(Private::add); } | value '<' value { code1(Private::lt); } | value '>' value { code1(Private::gt); } | value LTE value { code1(Private::le); } | value GTE value { code1(Private::ge); } - | value '+' - | RANDOMTOK '(' NUM '%' ')' + | value '+' { code1(fail); } + | RANDOMTOK '(' NUM '%' ')' { code1(fail); } ; diff --git a/engines/private/private.cpp b/engines/private/private.cpp index 2b629f85efc..90dc6212d5b 100644 --- a/engines/private/private.cpp +++ b/engines/private/private.cpp @@ -79,6 +79,8 @@ PrivateEngine::PrivateEngine(OSystem *syst) _nextMovie = NULL; _modified = false; _mode = -1; + _frame = new Common::String("inface/general/inface2.bmp"); + } @@ -94,7 +96,9 @@ PrivateEngine::~PrivateEngine() { Common::Error PrivateEngine::run() { Common::File *file = new Common::File(); - assert(file->open("GAME.DAT")); + if (!file->open("GAME.DAT")) // if the full game is not used + assert(file->open("assets/GAME.TXT")); // open the demo file + void *buf = malloc(191000); file->read(buf, 191000); initFuncs(); @@ -118,21 +122,6 @@ Common::Error PrivateEngine::run() { _compositeSurface->create(_screenW, _screenH, _pixelFormat); _compositeSurface->setTransparentColor(_transparentColor); - // You could use backend transactions directly as an alternative, - // but it isn't recommended, until you want to handle the error values - // from OSystem::endGFXTransaction yourself. - // This is just an example template: - //_system->beginGFXTransaction(); - // // This setup the graphics mode according to users seetings - // initCommonGFX(false); - // - // // Specify dimensions of game graphics window. - // // In this example: 320x200 - // _system->initSize(320, 200); - //FIXME: You really want to handle - //OSystem::kTransactionSizeChangeFailed here - //_system->endGFXTransaction(); - // Create debugger console. It requires GFX to be initialized Console *console = new Console(this); setDebugger(console); @@ -164,13 +153,20 @@ Common::Error PrivateEngine::run() { // Events switch (event.type) { + case Common::EVENT_KEYDOWN: + if (event.kbd.keycode == Common::KEYCODE_ESCAPE && _videoDecoder) + skipVideo(); + break; + case Common::EVENT_QUIT: case Common::EVENT_RETURN_TO_LAUNCHER: break; case Common::EVENT_LBUTTONDOWN: selectMask(mousePos); - selectExit(mousePos); + if (!_nextSetting) + selectExit(mousePos); + g_system->delayMillis(30); break; default: @@ -199,10 +195,7 @@ Common::Error PrivateEngine::run() { continue; } - //if (_compositeSurface) - // drawScreen(); - - if (_nextSetting != NULL) { + if (_nextSetting != NULL) { debug("Executing %s", _nextSetting->c_str()); _exits.clear(); _masks.clear(); @@ -211,8 +204,6 @@ Common::Error PrivateEngine::run() { CursorMan.showMouse(false); execute(prog); CursorMan.showMouse(true); - - } g_system->updateScreen(); @@ -223,7 +214,8 @@ Common::Error PrivateEngine::run() { } void PrivateEngine::selectExit(Common::Point mousePos) { - //debug("Mousepos %d %d", mousePos.x, mousePos.y); + debug("Mousepos %d %d", mousePos.x, mousePos.y); + mousePos = mousePos - *_origin; Common::String *ns = NULL; int rs = 100000000; int cs = 0; @@ -231,9 +223,9 @@ void PrivateEngine::selectExit(Common::Point mousePos) { for (ExitList::iterator it = _exits.begin(); it != _exits.end(); ++it) { e = *it; cs = e.rect->width()*e.rect->height(); - //debug("Testing exit %s %d", e.nextSetting->c_str(), cs); + debug("Testing exit %s %d", e.nextSetting->c_str(), cs); if (e.rect->contains(mousePos)) { - //debug("Inside! %d %d", cs, rs); + debug("Inside! %d %d", cs, rs); if (cs < rs && e.nextSetting != NULL) { // TODO: check this debug("Found Exit %s %d", e.nextSetting->c_str(), cs); rs = cs; @@ -249,7 +241,8 @@ void PrivateEngine::selectExit(Common::Point mousePos) { } void PrivateEngine::selectMask(Common::Point mousePos) { - //debug("Mousepos %d %d", mousePos.x, mousePos.y); + //debug("Mousepos %d %d", mousePos.x, mousePos.y); + mousePos = mousePos - *_origin; Common::String *ns = NULL; MaskInfo m; for (MaskList::iterator it = _masks.begin(); it != _masks.end(); ++it) { @@ -324,8 +317,8 @@ void PrivateEngine::playSound(const Common::String &name) { if (!file->open(path)) error("unable to find sound file %s", path.c_str()); - Audio::AudioStream *stream; - stream = Audio::makeWAVStream(file, DisposeAfterUse::YES); + Audio::LoopingAudioStream *stream; + stream = new Audio::LoopingAudioStream(Audio::makeWAVStream(file, DisposeAfterUse::YES), 1); stopSound(); _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume); } @@ -344,13 +337,20 @@ void PrivateEngine::playVideo(const Common::String &name) { } +void PrivateEngine::skipVideo() { + _videoDecoder->close(); + delete _videoDecoder; + _videoDecoder = nullptr; +} + + void PrivateEngine::stopSound() { debugC(3, kPrivateDebugExample, "%s", __FUNCTION__); if (_mixer->isSoundHandleActive(_soundHandle)) _mixer->stopHandle(_soundHandle); } -void PrivateEngine::loadImage(const Common::String &name, int x, int y) { +void PrivateEngine::loadImage(const Common::String &name, int x, int y, bool drawn) { debugC(1, kPrivateDebugExample, "%s : %s", __FUNCTION__, name.c_str()); Common::File file; Common::String path = convertPath(name); @@ -362,10 +362,22 @@ void PrivateEngine::loadImage(const Common::String &name, int x, int y) { //for (int i = 0; i < 30; i=i+3) // debug("%x %x %x", *(_image->getPalette()+i), *(_image->getPalette()+i+1), *(_image->getPalette()+i+2)); - _compositeSurface->transBlitFrom(*_image->getSurface()->convertTo(_pixelFormat, _image->getPalette()), Common::Point(x,y), _transparentColor); + _compositeSurface->transBlitFrom(*_image->getSurface()->convertTo(_pixelFormat, _image->getPalette()), *_origin + Common::Point(x,y), _transparentColor); drawScreen(); } +void PrivateEngine::drawScreenFrame() { + Common::File file; + Common::String path = convertPath(*_frame); + if (!file.open(path)) + error("unable to load image %s", path.c_str()); + + _image->loadStream(file); + _compositeSurface->transBlitFrom(*_image->getSurface()->convertTo(_pixelFormat, _image->getPalette()), Common::Point(0,0)); + //drawScreen(); +} + + Graphics::ManagedSurface *PrivateEngine::loadMask(const Common::String &name, int x, int y, bool drawn) { debugC(1, kPrivateDebugExample, "%s : %s", __FUNCTION__, name.c_str()); Common::File file; @@ -393,6 +405,9 @@ void PrivateEngine::drawScreen() { if (_videoDecoder ? _videoDecoder->needsUpdate() : false || _compositeSurface) { Graphics::Surface *screen = g_system->lockScreen(); //screen->fillRect(Common::Rect(0, 0, g_system->getWidth(), g_system->getHeight()), 0); + // + //if (_mode == 1) + // drawScreenFrame(); Graphics::ManagedSurface *surface = _compositeSurface; diff --git a/engines/private/private.h b/engines/private/private.h index 704fc02a3f3..1f3ec553f6f 100644 --- a/engines/private/private.h +++ b/engines/private/private.h @@ -82,11 +82,14 @@ public: Common::String convertPath(Common::String); void playSound(const Common::String &name); - void playVideo(const Common::String &name); + void playVideo(const Common::String &name); + void skipVideo(); void stopSound(); - void loadImage(const Common::String &, int, int); - Graphics::ManagedSurface *loadMask(const Common::String &, int, int, bool); + void loadImage(const Common::String &file, int x, int y, bool drawn = true); + void drawScreenFrame(); + + Graphics::ManagedSurface *loadMask(const Common::String &, int, int, bool); uint32 _transparentColor; void drawScreen(); @@ -95,6 +98,7 @@ public: Common::Point *_origin; Common::String *_nextSetting; Common::String *_nextVS; + Common::String *_frame; int _mode; bool _modified; diff --git a/engines/private/symbol.cpp b/engines/private/symbol.cpp index c0b9270a37a..9e3248a5ad9 100644 --- a/engines/private/symbol.cpp +++ b/engines/private/symbol.cpp @@ -31,7 +31,7 @@ void showSymbol(Symbol *s) else if (s->type == STRING) debug("%s %s", s->name->c_str(), s->u.str); else if (s->type == NAME) - debug("%s",s->name->c_str()); + debug("%s %d",s->name->c_str(), s->type); else debug("%s %d", s->name->c_str(), s->type); } @@ -40,7 +40,13 @@ void showSymbol(Symbol *s) Symbol *lookup(Common::String s, SymbolMap symlist) /* find s in symbol table symlist */ { //debug("looking up %s", s.c_str()); - return symlist.getVal(s); + Symbol *r = symlist.getVal(s); + /*if (strcmp(s.c_str(), "m_640x480") == 0) { + showSymbol(r); + assert(0); + }*/ + + return r; } Symbol *lookupName(char *n) /* install s in some symbol table */ @@ -106,7 +112,7 @@ void installall(char *n) { else if (strcmp(n, "rects") == 0) { assert(r != NULL); - install(s, NAME, 0, NULL, r, &rects); + install(s, RECT, 0, NULL, r, &rects); } else assert(0);